Java 具有非可选参数的基于Quarkus注释的拦截器

Java 具有非可选参数的基于Quarkus注释的拦截器,java,interceptor,quarkus,Java,Interceptor,Quarkus,从所问问题的数量来看,这似乎是一个热门话题,但我还没有找到我正在寻找的答案。我想在我的Quarkus应用程序中实现一个简单的授权服务,但我似乎一次又一次地重复代码 基本上,我从Authorization Http头中获取JWT,并检查其中提供的角色是否足以访问我的端点: public void someApiCall(@Context HttpHeaders headers) { authService.validate(ApiToken.SOME_API_CALL, headers);

从所问问题的数量来看,这似乎是一个热门话题,但我还没有找到我正在寻找的答案。我想在我的Quarkus应用程序中实现一个简单的授权服务,但我似乎一次又一次地重复代码

基本上,我从Authorization Http头中获取JWT,并检查其中提供的角色是否足以访问我的端点:

public void someApiCall(@Context HttpHeaders headers) {
    authService.validate(ApiToken.SOME_API_CALL, headers); // Throws an exception when unauthorized
    
    //…
}
现在,我认为这看起来非常笨拙,我不喜欢每个Http端点都需要的额外参数。我对AOP做了一些研究,并知道如何添加一个拦截器,该拦截器可以通过应用于我的方法的注释验证Http头:

@Authorize
public void someApiCall(/*…*/) { /*…*/ }
问题是,我不知道如何将参数传入此注释以指定所需的角色。我想要这样的东西:

@Authorize(UserRole.SYSADMIN)
这看起来很简单,但我想不出来。下面是拦截器和注释类(当然缺少所需的角色):

Authorize.java

@Retention(value=RUNTIME)
@Target(value=METHOD)
public @interface Authorize {}
@InterceptorBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Authorize {
    // Nonbinding is very important. It makes the interceptor fire regardless of the value
    @Nonbinding ApiToken value();
}
AuthorizeInterceptor.java

@Interceptor
@Priority(3000)
@Authorize
public class AuthorizeInterceptor {

    @Inject
    AuthorizationService authService;

    @AroundInvoke
    public void validateRole(InvokationContext ctx) {
        authService.validate(ApiToken.ALL, ((RestEndpoint)ctx.getTarget()).getHttpHeaders());
    }
}
@Interceptor
@Priority(3000)
@Authorize(ApiToken.NULL)
public class AuthorizeInterceptor {
    /* fields */

    public Object validate(InvokationContext ctx) throws Exception {
        authService.validate(/* stays the same */);
        return ctx.proceed();
    }
}
RestEndpoint.java

public class RestEndpoint {

    @Context
    HttpHeaders headers;

    public HttpHeaders getHttpHeaders() { return headers; }
}
SomeResource.java

public class SomeResource extends RestEndpoint {

    @GET
    @Authorize
    public Object someApiCall() {
        /* do code directly */
    }
}
public class SomeResource {
    @GET
    @Authorize(ApiToken.SOME_API_CALL)
    public Object someApiCall() { /* implementation */ }
}
总之,在我编写
@Authorize
的地方,我想让
@Authorize(UserRole.SOME_ROLE)


提前谢谢

所以,我设法弄明白了。事实证明,这并不难,我只是不知道去哪里找

以下是修改后的类:

Authorize.java

@Retention(value=RUNTIME)
@Target(value=METHOD)
public @interface Authorize {}
@InterceptorBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Authorize {
    // Nonbinding is very important. It makes the interceptor fire regardless of the value
    @Nonbinding ApiToken value();
}
AuthorizeInterceptor.java

@Interceptor
@Priority(3000)
@Authorize
public class AuthorizeInterceptor {

    @Inject
    AuthorizationService authService;

    @AroundInvoke
    public void validateRole(InvokationContext ctx) {
        authService.validate(ApiToken.ALL, ((RestEndpoint)ctx.getTarget()).getHttpHeaders());
    }
}
@Interceptor
@Priority(3000)
@Authorize(ApiToken.NULL)
public class AuthorizeInterceptor {
    /* fields */

    public Object validate(InvokationContext ctx) throws Exception {
        authService.validate(/* stays the same */);
        return ctx.proceed();
    }
}
SomeResource.java

public class SomeResource extends RestEndpoint {

    @GET
    @Authorize
    public Object someApiCall() {
        /* do code directly */
    }
}
public class SomeResource {
    @GET
    @Authorize(ApiToken.SOME_API_CALL)
    public Object someApiCall() { /* implementation */ }
}

正如图灵85所指出的,JavaEE中已经存在一个类似的API,它以相同的方式实现授权功能。

您不使用Quarukus现有解决方案的具体原因是什么,例如?这是一个很好的建议。我一定会看一看的。我的问题是针对一般用途的,所以我不提了。它还需要
@Context SecurityContext
作为每个方法调用的参数,因此我认为这也不是一个理想的解决方案。如果您想要访问,例如令牌,您只需要
SecurityContext
。如果您只想退出角色,那么
@RolesAllowed
就足够了。你可以看一看。它列出了使用JWTs的另外两个选项(OAUTH2 RBAC和OIDC)。更多好的建议!谢谢企业是使用这些库,还是通常编写自己的库?