Using @RolesAllowed to filter entity properties wi

2019-07-30 00:20发布

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, depending on the role of the user?

I already found a ton of documentation on how to do this with Jersey, but nothing with RESTEasy.

I'm blocked on this architecture so switching libraries is not an option, and using the custom ObjectMapper as explained here is not an option either, as the model is big enough to make it too time-consuming to mark every single property of a large dataset for correct serialization. Plus, this refers to an older version of the Jackson library and I'm not sure on how to make it work with the new version.

EDIT

Specifically see this blog post to understand what I'm trying to accomplish. Please note that this is Jersey-specific and so far I found no documentation on RESTEasy to accomplish this.

1条回答
霸刀☆藐视天下
2楼-- · 2019-07-30 00:49

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
        serializeAsField(pojo, jgen, provider, writer);
    }
}

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);
查看更多
登录 后发表回答