Using @RolesAllowed to filter entity properties with RESTEasy and Jackson

后端 未结 1 1644
一向
一向 2021-01-24 06:34

With RESTEasy and Jackson, is it possible to use the @RolesAllowed annotation in my model, in order to avoid certain properties to be serialized in output, dependin

相关标签:
1条回答
  • 2021-01-24 07:21

    If you are not willing to use @JsonView, you could consider @JsonFilter. You first need to extend SimpleBeanPropertyFilter and control the serialization according to the user roles:

    public class RoleBasedPropertyFilter extends SimpleBeanPropertyFilter {
    
        private String allowedRole;
    
        public RoleBasedPropertyFilter(String allowedRole) {
            this.allowedRole = allowedRole;
        }
    
        @Override
        public void serializeAsField(Object pojo, JsonGenerator jgen,
                                     SerializerProvider provider, 
                                     PropertyWriter writer) throws Exception {
    
            PermitAll permitAll = writer.getAnnotation(PermitAll.class);
            if (permitAll != null) {
                serializeAsField(pojo, jgen, provider, writer);
                return;
            }
    
            DenyAll denyAll = writer.getAnnotation(DenyAll.class);
            if (denyAll != null) {
                writer.serializeAsOmittedField(pojo, jgen, provider);
                return;
            }
    
            RolesAllowed rolesAllowed = writer.getAnnotation(RolesAllowed.class);
            if (rolesAllowed != null) {
                if (!Arrays.asList(rolesAllowed.value()).contains(allowedRole)) {
                    writer.serializeAsOmittedField(pojo, jgen, provider);
                    return;
                }
            }
    
            // If no annotation is provided, the property will be serialized
            writer.serializeAsField(pojo, jgen, provider);
        }
    }
    

    To apply the filter to a certain bean, annotate it with @JsonFilter("roleBasedPropertyFilter"):

    @JsonFilter("roleBasedPropertyFilter")
    public class User {
    
        private String firstName;
        private String lastName;
        private String email;
        private String password;
    
        public String getFirstName() {
            return firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        @RolesAllowed({"ADMIN"})
        public String getEmail() {
            return email;
        }
    
        @DenyAll
        public String getPassword() {
            return password;
        }
    
        // Other getters and setters
    }
    

    Then register your filter in your the ContextResolver for ObjectMapper:

    String currentUserRole = // Get role from the current user
    
    FilterProvider filterProvider = new SimpleFilterProvider()
            .addFilter("roleBasedPropertyFilter", 
                    new RoleBasedPropertyFilter(currentUserRole));
    
    ObjectMapper mapper = new ObjectMapper();
    mapper.setFilterProvider(filterProvider);
    

    If you want to make your filter "global", that is, to be applied to all beans, you can create a mix-in class and annotate it with @JsonFilter("roleBasedPropertyFilter"):

    @JsonFilter("roleBasedPropertyFilter")
    public class RoleBasedPropertyFilterMixIn {
    
    }
    

    Then bind the mix-in class to Object:

    mapper.addMixIn(Object.class, RoleBasedPropertyFilterMixIn.class);
    
    0 讨论(0)
提交回复
热议问题