Is there any way to dynamically exclude a bean property from being serialized if the logged user has not the permissions to see a specific field?
For example, if a bean has fields A,B,C may be that, in the REST response, the admin can see fields A,B,C while a simple user can see only fields A,B. How could I annotate the getter of field C? Can I integrate such annotation with the SecurityContext of Jersey?
I am using Jersey 2.1 and Jackson.
Thanks
One possible approach would be to use @JsonView (see also JacksonJsonViews).
Views:
// View definitions:
class Views {
static class User { }
static class Admin extends User { }
}
Bean:
public class Bean {
@JsonView(Views.User.class)
private A a;
@JsonView(Views.User.class)
private B b;
@JsonView(Views.Admin.class)
private C c;
}
You would need to create a ContextResolver as described in Jackson section in the user guide. You can inject SecurityContext to this ContextResolver
from which you can find out what role is a user in. Your ContextResolver
may look like:
@Provider
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {
@Context
private SecurityContext securityContext;
@Override
public ObjectMapper getContext(Class<?> type) {
final ObjectMapper objectMapper = new ObjectMapper();
if (securityContext.isUserInRole("admin")) {
objectMapper.getSerializationConfig().setSerializationView(Views.Admin.class);
} else {
objectMapper.getSerializationConfig().setSerializationView(Views.User.class);
}
return objectMapper;
}
}
EDIT 1:
There is a RFE filed for a similar (more user friendly) use case already (see JERSEY-2013).
If you use the same JAX-RS resources for requests with different user roles, you should consider the following solution:
@Provider
public class SecuritySerializerFilter extends JacksonJaxbJsonProvider {
@Context
SecurityContext securityContext;
@Override
public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
ObjectMapper current = locateMapper(type, mediaType);
setMapper(current.setSerializationConfig(
current.getSerializationConfig().withView(
securityContext.isUserInRole("admin") ? Views.Admin.class : Views.User.class
)
));
super.writeTo(value, type, genericType, annotations, mediaType, httpHeaders, entityStream);
}
}