如何在 CXF 中的 ContainerRequestFilter 中注入 ResourceInfo

Imr*_*n K 0 rest ws-security spring cxf jax-rs

我正在尝试使用 Apache CXF 和 Spring 构建基于令牌的身份验证和授权系统。我完全按照这个很棒的帖子来做这件事。但是我一开始就遇到了 AuthorizationFilter 的问题。我看过很多关于它的帖子,apache JIRA,github 评论,但还没有找到解决这个看似 CXF 问题的方法。

@PreMatching
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
private ResourceInfo resourceInfo;

@Context
public void setResourceInfo(ResourceInfo resourceInfo) {
    this.resourceInfo = resourceInfo;
}

@Override
public void filter(final ContainerRequestContext requestContext) throws IOException {

    Method method = resourceInfo.getResourceMethod();
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,注入的 resourceInfo 是一个代理对象,它没有任何关联的属性存在。因此,来自该resourceInfo对象的任何内容都将返回null,更具体地说resourceInfo.getResourceMethod()null,导致 NPE。这是关于这个问题的JIRA帖子,说:

在某些情况下(例如使用 @ApplicationScoped 注释),CDI 运行时将为特定 bean 创建代理类。结果,CXF 端将把特定的提供者元数据绑定到这个代理实例。它看起来合乎逻辑且毫不含糊。

然而,当 CXF 尝试将上下文代理(@Context 注释)注入提供程序实例时,有趣的事情正在发生。注入成功,但它们的目标对象将是代理实例(而不是其背后的真实实例)。因此,在运行时,当代理将调用委托给支持实例时,所有上下文代理在那里都是空的(简单地说,没有设置)。

参考最近与 Sergey Beryozkin 的讨论,最好的解决方案是将 @Context 注释委托给 CDI 框架(因此,从执行注入工作中减轻 CXF)。这个提议可能需要 JAX-RS 规范方面的支持。

更简单(临时?)可能的解决方案是用 @Context 注入补充 CDI 注入(将这项工作委托给 CXF,因为它现在适用于非代理 bean 和非 CDI 部署)。这可以通过观察 ProcessInjectionTarget 事件并提供我们自己的 InjectionTarget 来完成(这种方法有工作 PoC)。

关于构造函数注入,似乎 CXF 不支持将参数传递给提供程序构造函数(在 CDI 的情况下,没有 @Context 注释)所以我将是另一个(单独的)问题来查看。

有人能帮我指出这种更简单的方法是什么吗:

更简单(临时?)可能的解决方案是用 @Context 注入补充 CDI 注入(将这项工作委托给 CXF,因为它现在适用于非代理 bean 和非 CDI 部署)。这可以通过观察 ProcessInjectionTarget 事件并提供我们自己的 InjectionTarget 来完成(这种方法有工作 PoC)

或者有没有其他方法,Spring Framework 可以以正确的方式注入 ResourceInfo 对象?

我已经在我的applicationContext.xml: 中注册了这样的过滤器:

<jaxrs:server id="endpoints">
    <jaxrs:providers>
            <ref bean="authenticationFilter" />
            <ref bean="authorizationFilter" />
        </jaxrs:providers>
    </jaxrs:server>
Run Code Online (Sandbox Code Playgroud)

Pau*_*tha 6

问题是@PreMatching注释。

可应用于容器请求过滤器的全局绑定注释,以指示此类过滤器应在实际资源匹配发生之前全局应用于应用程序中的所有资源。

关键是“在实际资源匹配发生之前”突出显示的部分。因此,即使在资源与请求匹配之前,过滤器也会被调用。如果还没有匹配的资源,那么就不可能从ResourceInfo. 如果你只是删除@PreMatching批注,则该过滤器将被调用一个匹配的资源被发现,你将能够从访问所有信息ResourceInfo