如何使用 Spring Security Oauth 保护 Struts2 Rest 服务

Posted

技术标签:

【中文标题】如何使用 Spring Security Oauth 保护 Struts2 Rest 服务【英文标题】:How to securize Struts2 Rest services with Spring Security Oauth 【发布时间】:2015-12-11 19:58:37 【问题描述】:

我在配置 spring security Oauth 以在 Struts2 应用程序上使用它来保护其余 Web 服务时遇到了困难。 我已经使用 Spring Security 很长时间了。

如果我很好理解的话,问题是 Spring security Oauth 需要在 root 上设置 spring mvc 调度程序。这和 Struts2 有冲突。

这是我的尝试

2) 根目录上的 Struts2 和 /oauth/* 上的 Spring MVC

<!-- Struts 2 -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/struts/*</url-pattern>
    </filter-mapping>

<servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

这对 Oauth 来说没问题,但 Struts2 不再工作了。

1) 根目录上的 Struts2 和 Spring MVC

<!-- Struts 2 -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/struts/*</url-pattern>
    </filter-mapping>

<servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/oauth/*</url-pattern>
    </servlet-mapping>

Struts2,oauth 正在识别权限,但响应是在 /token 而不是 /oauth/token 上做出的,所以我收到 404 错误。

spring-security.xml的摘录在这里:

<http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="clientAuthenticationManager"
        xmlns="http://www.springframework.org/schema/security">
        <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
        <anonymous enabled="false" />
        <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <!-- include this only if you need to authenticate clients via request 
            parameters -->
        <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
        <access-denied-handler ref="oauthAccessDeniedHandler" />

</http>

<!-- This is where we tells spring security what URL should be protected 
    and what roles have access to them -->
<http pattern="/api/**.api" create-session="never"
    entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager"
    xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />
    <intercept-url pattern="/api/**.api" access="ROLE_API" />
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

【问题讨论】:

Ryder,如果您找到了答案,请将其发布给其他人。他们要求它并删除他们的答案。谢谢。当然,你已经一个多月没有登录了,所以没有人屏住呼吸。 【参考方案1】:

解决方案是使用 2 个不同的 Spring Dispatchers:

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/oauth/*</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>rest-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>rest-dispatcher</servlet-name>
    <url-pattern>/restapi/*</url-pattern>
</servlet-mapping>

一个用于 Rest WS,另一个用于安全化。

之后,您将把代币赌在 /oauth/token 上,而不是在 /oauth/oauth/token 上

要解决这个问题,你必须复制 Spring Security Parameterization :

<http pattern="/oauth/token" create-session="stateless"
    authentication-manager-ref="clientAuthenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <!-- include this only if you need to authenticate clients via request 
        parameters -->
    <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

<http pattern="/oauth/oauth/token" create-session="stateless"
    authentication-manager-ref="clientAuthenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/oauth/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <!-- include this only if you need to authenticate clients via request 
        parameters -->
    <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

【讨论】:

以上是关于如何使用 Spring Security Oauth 保护 Struts2 Rest 服务的主要内容,如果未能解决你的问题,请参考以下文章

在没有 servlet api 的 webflux 项目中使用 OAuth2 和 Spring Security OAuth2 和 reactor netty

具有密码授予类型的 WebClient 的 Spring Security OAuth 客户端不要求新令牌

Spring security:Spring security 如何在 SessionRegistry 中注册新会话?

如何使用 Spring Security 模拟身份验证和授权

如何禁用 spring-security 登录屏幕?

如何使用 Spring-Security 3 和 Hibernate 4 将 spring security xml 配置 hibernate 转换为 java config