Core Walkthrough
This walks through masking a field with the Jackson backend (ihawu-jackson) alone — no web framework,
just Jackson. On Spring Boot, the starter does all of this wiring for
you; see Getting Started.
-
Add the Jackson backend. It pulls
ihawu-coretransitively.implementation("org.ihawu:ihawu-jackson:0.4.1") -
Annotate the response type with the resource name policies resolve against.
import org.ihawu.core.annotation.IhawuResource@IhawuResource("employee")data class EmployeeResponse(val id: String,val fullName: String,val salary: Double,val socialSecurityNumber: String,) -
Define the policies. Use the batteries-included static resolver, or implement the
ResourcePolicyResolverSPI to pull rules from your own source. Either way you get aResourcePolicyResolverto hand the module in the next step.import org.ihawu.core.masking.MaskingStrategyimport org.ihawu.core.policy.FieldPolicyimport org.ihawu.core.policy.ResourcePolicyimport org.ihawu.core.policy.RoleBasedResourcePolicyResolverval resolver = RoleBasedResourcePolicyResolver(listOf(ResourcePolicy(resourceName = "employee",roleFieldPolicies = mapOf("MANAGER" to listOf(FieldPolicy("socialSecurityNumber", MaskingStrategy.REDACT, "***-**-****"),),),),),)import org.ihawu.core.masking.MaskingStrategyimport org.ihawu.core.policy.FieldPolicyimport org.ihawu.core.policy.IhawuPrincipalimport org.ihawu.core.policy.ResourcePolicyResolver// Resolve rules from wherever they live — a database, OPA, a per-tenant service.val resolver = object : ResourcePolicyResolver {override fun resolve(principal: IhawuPrincipal, resource: String): List<FieldPolicy> =if (resource == "employee" && "MANAGER" in principal.roles) {listOf(FieldPolicy("socialSecurityNumber", MaskingStrategy.REDACT, "***-**-****"))} else {emptyList()}} -
Register the Jackson module on your
ObjectMapper.import com.fasterxml.jackson.databind.ObjectMapperimport org.ihawu.jackson.IhawuModuleval mapper = ObjectMapper().registerModule(IhawuModule(resolver)) -
Serialize with the caller attached. Supply the
IhawuPrincipalfor the write via theIhawuSerialization.PRINCIPALattribute; Ihawu masks per the resolved policy.import org.ihawu.core.policy.IhawuPrincipalimport org.ihawu.jackson.IhawuSerializationval principal = IhawuPrincipal("u1", roles = setOf("MANAGER"), attributes = emptyMap())val employee = EmployeeResponse("42", "Jane Doe", 145_000.0, "123-45-6789")val json = mapper.writer().withAttribute(IhawuSerialization.PRINCIPAL, principal).writeValueAsString(employee)// socialSecurityNumber is now "***-**-****"; the other fields are untouched.
See it wired in Spring
Section titled “See it wired in Spring”The Spring Boot starter handles the identity bridge, module registration, and request-scoped caching for you. The runnable sample shows the whole flow end to end against a live endpoint.