springboot~uaa~scope对实体的字段添加限制

scope授权思路

通过实现JsonSerializer抽象类的serialize方法来进行指定类型的序列化,在序列化中对持有ScopeSet注解的字段进行解析,当没有对象的scope时,
对字段不进行渲染,从而保护了字段资源。

之前的尝试MappingJackson2HttpMessageConverter

之前使用MappingJackson2HttpMessageConverter的定义,将@ScopeSet进行检查,并对字段按着scope值进行输出,最后的结果是失败的,因为
MappingJackson2HttpMessageConverter只在程序启动时执行一次,将类对应的字段添加到它的字典之后,如果下次有相同的实体字段,就不会去再执行
MappingJackson2HttpMessageConverter了,而我们要求的是每次序列化时都需要进行重新的解析,以查询当前用户的scope是否有对应的权限。

JsonSerializer的实现

接口在每次从服务端响应时都需要使用jackson的JsonSerializer功能,它有默认的实现方式,而我们可以重新去实现自己的方法,它在每次接口响应时都会被执行
ScopeSet

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ScopeSet {
    /**
     * 授权范围.
     *
     * @return
     */
    String value() default "";
}

在实体的和字段上添加scope
1
ScopeJsonSerializer序列化

@Slf4j
public class ScopeJsonSerializer<T> extends JsonSerializer<T> {
    @SneakyThrows
    @Override
    public void serialize(T t, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        //引用类型
        jsonGenerator.writeStartObject();
        for (Field field : t.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            if (field.getAnnotation(ScopeSet.class) != null) {
                String value = field.getAnnotation(ScopeSet.class).value();
                if (Arrays.asList(SecurityUser.getScope()).contains(value)) {
                    jsonGenerator.writeObjectField(field.getName(), field.get(t));
                }
            } else {
                jsonGenerator.writeObjectField(field.getName(), field.get(t));
            }
        }
        jsonGenerator.writeEndObject();
    }
}

在DTO实体中使用,先在实体上声明注解@JsonSerialize(using = ScopeJsonSerializer.class),之后在需要保护的字段上添加@ScopeSet注解即可。

当你的token.scope没有read时,你的字段email将不会被输出
2
感谢各位阅读!

posted @ 2020-12-01 16:10  张占岭  阅读(528)  评论(0编辑  收藏  举报