如何在CXF的ContainerRequestFilter中注入ResourceInfo

时间:2018-08-25 17:27:15

标签: spring rest jax-rs cxf ws-security

我正在尝试使用Apache CXF和Spring构建基于令牌的身份验证和授权系统。为此,我完全遵循this fantastic post。 但是我在一开始就陷入了我的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();

在上面的代码中,注入的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>

1 个答案:

答案 0 :(得分:2)

问题是@PreMatching注释。

  

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

该键在“发生实际资源匹配之前”的突出显示部分。因此,即使在资源与请求匹配之前,也会调用过滤器。而且,如果还没有匹配的资源,那么就不可能从ResourceInfo获取任何信息。如果仅删除@PreMatching批注,则在找到匹配资源后,过滤器将被称为 ,您将能够从ResourceInfo访问所有信息。