我可以向 JAX-RS 方法添加自定义注释以验证访问权限吗?

2022-01-13 00:00:00 annotations java jax-rs

例如我有以下方法:

@GET
    @Path("/get/current")
    public Response getCurrentInfo(@HeaderParam("Authorization") String token){

        Gson gson = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS")
        .setPrettyPrinting().create();          

        String email = SecurityProvider.decryptTokenAndGetEmail(token);

        if(DB.isAccessPermitted(email)){
            Info info = DB.getCurrentInfo();
            String json = gson.toJson(info);
            return Response.ok(json).build();
        }else{
           return Response.status(401).build();
        }

    }

所以改为写在每个方法中:

So instead to write in every method:

          if(DB.isAccessPermitted(email)){
                Info info = DB.getCurrentInfo();
                String json = gson.toJson(info);
                return Response.ok(json).build();
            }else{
               return Response.status(401).build();
            }

我将创建例如 @SecurityCheck 注释,注释每个访问受限的方法并仅在一个地方执行检查.是否可以通过注释来实现,是否可以提供 MVCE?谢谢.

I will create for example @SecurityCheck annotation, annotate every method which has limited access and perform check only in a single place. Is it possible to achieve with annotations and can MVCE be provided? Thank you.

推荐答案

如果你使用的是JAX-RS 2.0,可以注入ResourceInfo 变成一个ContainerRequestFilter,然后得到java.lang.reflect.Method 来自.从Method,你可以得到注解.例如

If you are using JAX-RS 2.0, you can inject ResourceInfo into a ContainerRequestFilter, then get the java.lang.reflect.Method from the. From the Method, you can get the annotation. For example

@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {

    @Context
    private ResourceInfo resourceInfo;

    // You can get the header from the `requestContext`
    @Override
    public void filter(ContainerRequestContext requestContext) {
        Method resourceMethod = resourceInfo.getResourceMethod();
        SecurityCheck annotation = resourceMethod.getAnnotation(SecurityCheck.class);
        // get some value from annotation

        if (notAllowedAccess) {
            throw new WebApplicationException(403);
        }
    }
}

这个(ResourceInfo)只有在你需要从注解中获取一些值时才需要,比如@SecurityCheck("SomeRoleAllowed").

This (the ResourceInfo) is only necessary though if you need to get some value from the annotation, like @SecurityCheck("SomeRoleAllowed").

如果您不需要该值,并且您想要的只是对任何带注释的方法进行过滤,那么您可以创建一个 DynamicFeature,在其中将每个方法绑定到一个过滤器.例如

If you don't need the value, and all you want is for any method annotated to be filtered, then you can either create a DynamicFeature, where you bind each method to a filter. For example

@Provider
public class SecurityCheckDynamicFeature implements DynamicFeature {
    @Override
    public void configure(ResourceInfo info, FeatureContext context) {
        Method method = info.getResourceMethod();
        SecurityCheck annotation = method.getAnnotation(SecurityCheck.class);
        if (annotation != null) {
            context.register(SecurityFilter.class);
        }
    }
}

或者另一种方法是在自定义注释上使用 @NameBinding

Or another way is to just use @NameBinding on the custom annotation

@NameBinding
@Target(...)
@Retention
public @interface SecurityCheck {}

然后你需要用注解来注解 SecurityFilter 类.任何带注释的方法或类都将通过过滤器.

Then you need to annotate the SecurityFilter class with the annotation also. Any method or class annotated will go through the filter.

其他资源:

  • 过滤器和拦截器

相关文章