在 Karaf 中的 JAX-RS 捆绑包上使用 Spring Security

2022-09-02 02:02:27

我有一个 OSGi 捆绑包,它使用 JAX-RS 来处理一些 REST 服务。这个捆绑包在Karaf中与Apache CXF一起运行。我需要将基本的http身份验证应用于某些路径/方法组合。我一直在修补Spring Security,似乎新的3.1版本可以让你做到这一点,但是我在OSGi中让它工作遇到了很多麻烦。

就像测试一样,我创建了一个非常简单的bean.xml文件:

<beans>
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-http.xml"/>
    <import resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml"/>

    <jaxrs:server id="serverTest" address="/test">
        <jaxrs:serviceBeans>
            <ref bean="tstSvr"/>
        </jaxrs:serviceBeans>
    </jaxrs:server>

    <bean id="tstSvr" class="com.demo.Test"/>

    <security:http auto-config="true">
        <security:intercept-url pattern="/admin/**" access="ROLE_ADMIN" method="PUT" />
        <security:intercept-url pattern="/**" access="ROLE_USER" />
    </security:http>

    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="user" password="pass" authorities="ROLE_USER"/>
                <security:user name="admin" password="pass" authorities="ROLE_ADMIN"/>
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

现在,有趣的部分来了...从我一直在做的所有阅读中,我需要一个网络.xml才能使任何这些工作。例如我尝试使用的这个示例:

<web-app>
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

使用这两个文件的组合不起作用。我说的“不起作用”,是指什么也没发生。没有错误消息,没有例外,捆绑包的功能就像我尝试添加弹簧安全性之前一样。我假设问题在于捆绑包需要是 WAR 或 WAB 才能加载 web.xml。这是正确的吗?

更重要的是,有没有办法让春天在没有网络的情况下工作.xml?

我正在假设我需要将捆绑包保留为CXF加载它的捆绑包,因此我无法将其转换为WAR或WAB,但我并不完全确定情况是否如此。

感谢您提供的任何帮助!

更新:在做了一堆额外的谷歌搜索后,我发现了一个论坛帖子,提到添加到你的清单,而不是使用web.xml。但是,您似乎仍然需要使用 WAB 而不是普通捆绑包。我已将该行添加到我的清单中以防万一,但它不起作用。看来我的问题正在变成:如何将 WAB 与 CXF 结合使用?Web-FilterMappings: springSecurityFilterChain;url-patterns:="/*"

更新 2:因为这个问题不够长...我决定尝试使用Spring Security注释而不是intercept-url,只是为了看看会发生什么。当我尝试点击安全路径时,我得到这个有趣的堆栈跟踪:

Caused by: org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:323)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:196)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)[46:org.springframework.aop:3.0.5.RELEASE]

Spring网站表示,当您第一次尝试匿名连接到安全服务时,这种情况就会发生,并且不会再次发生。好吧,它每次对我来说都会发生。从例外情况来看,看起来我在清单中的条目正在被拾取,也许问题与我想象的不同。有人对为什么会发生这种情况有任何想法吗?我是否在bean中缺少一些条目.xml以使基本的http身份验证工作?


答案 1

首先,您需要清楚地了解弹簧和web.xml的作用。

  • Web.xml是用于配置 servlet 容器的标准文件,它通常是一个应用程序服务器,如 Jboss、Glassifsh、Jetty、Tomcat...
  • 你的beans.xml是一个用于spring应用程序上下文的配置文件,因为你没有使用它的任何命名空间,这意味着Karaf使用spring oob。

如果你想在没有容器的情况下使用servlets做Http,我想你必须注册一个HttpService,请参阅:http://karaf.apache.org/manual/latest-2.2.x/users-guide/http.html

发生异常,因为当它到达映射的方法时,SecurityContext 中没有身份验证 Bean。您尚未在映射中定义任何匿名访问,也许这就是它失败的原因。

基本上,要么定义一个AnonymousAuthenticationFilter,要么在你的http配置中使用dismissionAll的URL模式。否则,当您第一次尝试匿名连接同一会话时,您将继续收到该异常。


答案 2

推荐