我正在尝试使用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>
答案 0 :(得分:2)
问题是@PreMatching
注释。
可应用于容器请求过滤器的全局绑定注释,以指示在实际资源匹配发生之前,该过滤器应全局应用于应用程序中的所有资源。
该键在“发生实际资源匹配之前”的突出显示部分。因此,即使在资源与请求匹配之前,也会调用过滤器。而且,如果还没有匹配的资源,那么就不可能从ResourceInfo
获取任何信息。如果仅删除@PreMatching
批注,则在找到匹配资源后,过滤器将被称为 ,您将能够从ResourceInfo
访问所有信息。