【发布时间】:2019-01-31 19:55:16
【问题描述】:
我正在尝试使用 Apache CXF 和 Spring 构建基于令牌的身份验证和授权系统。我完全关注this fantastic post 这样做。 但是我在一开始就遇到了我的 AuthorizationFilter 问题。我看过很多关于它的帖子,apache JIRA,github cmets,但还没有找到关于这个看似 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>
【问题讨论】:
-
不能在预匹配过滤器中使用 ResourceInfo。还没有匹配到的资源,所以你没有任何关于它的信息。
-
你是救生员。这解决了我的问题。非常感谢。我如何接受它作为正确答案?
标签: spring rest jax-rs cxf ws-security