使用@RolesAllowed 通过 RESTEasy 和 Jackson 过滤实体属性

Using @RolesAllowed to filter entity properties with RESTEasy and Jackson

使用 RESTEasy 和 Jackson,是否可以在我的模型中使用 @RolesAllowed 注释,以避免某些属性在输出中被序列化,具体取决于用户的角色?

我已经找到了大量关于如何使用 Jersey 执行此操作的文档,但没有找到关于 RESTEasy 的文档。

我在这个架构上受阻,所以切换库不是一个选项,使用自定义 ObjectMapper 解释 here 也不是一个选项,因为模型足够大标记大型数据集的每个 属性 以进行正确序列化太耗时了。另外,这是指 Jackson 库的旧版本,我不确定如何使其与新版本一起使用。

编辑

具体请参阅 this blog post 以了解我要完成的工作。请注意,这是 Jersey 特有的,到目前为止我没有找到关于 RESTEasy 的文档来完成这个。

如果你不愿意使用@JsonView, you could consider @JsonFilter. You first need to extend SimpleBeanPropertyFilter并根据用户角色控制序列化:

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);
    }
}

要将过滤器应用于某个 bean,请使用 @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
}

然后在 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);

如果你想使你的过滤器"global",即应用于所有bean,你可以创建一个mix-in class并用@JsonFilter("roleBasedPropertyFilter")注释它:

@JsonFilter("roleBasedPropertyFilter")
public class RoleBasedPropertyFilterMixIn {

}

然后将混音 class 绑定到 Object:

mapper.addMixIn(Object.class, RoleBasedPropertyFilterMixIn.class);