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

Can I add a custom annotation to JAX-RS method to validate access?

例如我有以下方法:

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

    }

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

          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? 谢谢。

如果您使用的是 JAX-RS 2.0,您可以将 ResourceInfo 注入一个 ContainerRequestFilter,然后从中获取 java.lang.reflect.Method。从Method,你可以得到注解。例如

@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")

如果您不需要该值,而您只想过滤任何注释的方法,那么您可以创建一个 DynamicFeature,在其中将每个方法绑定到一个过滤器。例如

@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

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

然后你还需要用注解来注解SecurityFilter class。任何方法或 class 注释都将通过过滤器。

其他资源: