重写 spring-security 重定向 URL

Posted

技术标签:

【中文标题】重写 spring-security 重定向 URL【英文标题】:Rewrite spring-security redirect URLs 【发布时间】:2010-12-18 06:15:18 【问题描述】:

我正在尝试让 Tuckey UrlRewriteFilter 整理我的 web 应用程序的 URL。我遇到的一个问题是,当 spring-security 注意到匿名用户试图访问受保护的资源时,它会重定向到包含 servlet 路径的 URL。

例如,我想要的是:

> GET http://localhost:8080/my-context/protected-resource
< Location: http://localhost:8080/my-context/login

我目前得到的是:

> GET http://localhost:8080/my-context/protected-resource
< Location: http://localhost:8080/my-context/-/login

目前我找到的相关文件:

DefaultRedirectStrategy,执行相关的实际重定向:http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/DefaultRedirectStrategy.html。它有一个很诱人的 contextRelative 属性,但如果我能找到配置它的方法,我认为不会削减它。

帮助我走到这一步的一篇博文:http://nonrepeatable.blogspot.com/2009/11/using-spring-security-with-tuckey.html

我想知道的是:

    我可以/应该说服 Tuckey 重写 Location 标头。 在这里似乎没有任何帮助。 我可以/应该以某种方式调整 SS 配置以发出重写的 URL。我不认为这很整洁,如果禁用重写它会中断。

web.xml 看起来像

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    <init-param>
        <param-name>LogLevel</param-name>
        <param-value>log4j</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

<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>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

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

urlrewrite.xml 看起来像:

<urlrewrite>
    <rule>
        <from>^/(.*)$</from>
        <to>/-/$1</to>
    </rule>
</urlrewrite>

applicationContent-security.xml 看起来像:

<http auto-config="true">
    <!-- allow GET requests to /login without authentication -->
    <intercept-url pattern="/-/login" method="GET" filters="none"/>

    <intercept-url pattern="/-/admin/**" access="ROLE_ADMIN"/>
    <intercept-url pattern="/-/**" access="ROLE_USER"/>

    <form-login login-page="/-/login"
                login-processing-url="/-/login.do"
                authentication-failure-url="/-/login?login_error"
                default-target-url="/-/index"
                always-use-default-target="true"/>

    <logout logout-url="/-/logout"
            logout-success-url="/-/login"/>

    <access-denied-handler error-page="/-/access-denied"/>
</http>

【问题讨论】:

并将 login-page 属性设置为 /login? 【参考方案1】:

我遇到了同样的问题,但似乎在 Tuckey 的 3.2.0 版中已修复。 即 response.encodeRedirectUrl() 现在由 Tuckeys UrlRewriteWrappedResponse 包装,其中执行出站规则。

【讨论】:

【参考方案2】:

Spring 安全性正在使用像 http://example.org/-/login 这样的绝对 URL 进行重定向

尝试使用不带^ start of string 标记的出站规则来匹配spring 生成的绝对url。

<outbound-rule>
    <from>/-/login(.*)$</from>
    <to>/login$1</to>
</outbound-rule>    

【讨论】:

【参考方案3】:

去年我为我们的项目研究了这个问题,当时的问题是 Tucky 没有与 response.encodeRedirectUrl() 合作来重写重定向 URL。我联系了他们,但我还没有跟进。

我的解决方案是让凌乱的 URL 返回到客户端,然后使用 Tucky 重定向规则(第二次重定向)清理它。

因此,从安全重定向中添加另一条与您的丑陋 URL 匹配的规则,并将您自己的重定向发出到干净的 URL:

<rule>
    <from>^/whatever/ugly.*$</from>
    <to type="redirect">/login</to>
</rule>

是的,它涉及两个重定向,但客户端永远不会看到它......这可能是重点。

【讨论】:

【参考方案4】:

我从未使用过 Tuckey,但在快速查看文档后,我会尝试为登录案例添加一条规则:

<urlrewrite>
    <rule>
        <from>^/my-context/login$</from>
        <to>/my-context/login</to>
    </rule>
    <rule>
        <from>^/(.*)$</from>
        <to>/-/$1</to>
    </rule>
</urlrewrite>

编辑 好的,像这样:

<urlrewrite>
    <rule>
        <from>^/-/login$</from>
        <to>/login</to>
    </rule>
    <rule>
        <from>^/(.*)$</from>
        <to>/-/$1</to>
    </rule>
</urlrewrite>

【讨论】:

问题不在于入站请求不会被重写,而是作为重定向的一部分的出站 Location 标头不会被重写。从那以后,我发现具有完整协议、主机、端口、上下文等的出站规则将捕获 Location 标头,但这也不是很好。

以上是关于重写 spring-security 重定向 URL的主要内容,如果未能解决你的问题,请参考以下文章

spring-security login?logout 重定向到登录

Spring security *always* 重定向到登录表单

.htaccess 结合 301 重定向和 URI 重写

mod_rewrite:重写规则还是重定向?

Lumen + nginx = 错误 500,重写或内部重定向循环,同时内部重定向到“/index.php”

关于请求转发重定向url重写