Rewrite spring-security redirect URLs
I'm trying to get Tuckey UrlRewriteFilter to tidy up URLs for my webapp. One problem I've got is that when spring-security notices that an anonymous user is trying to access a protected resource it redirects to a URL which includes the servlet path.
What I'd like is, by example:
> GET http://localhost:8080/my-context/protected-resource
< Location: http://localhost:8080/my-context/login
What I currently get is:
> GET http://localhost:8080/my-context/protected-resource
< Location: http://localhost:8080/my-context/-/login
Relevant documents I've found so far:
DefaultRedirectStrategy, which does the actual redirect in question: http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/DefaultRedirectStrategy.html. It has a contextRelative property which is tempting but I don't think is going to cut it, if I can even find a way of configuring it.
A blog post that helped get me this far: http://nonrepeatable.blogspot.com/2009/11/using-spring-security-with-tuckey.html
What I'd like to know is:
- Can/should I convince Tuckey to rewrite the Location header. <outbound-rule> doesn't seem to help any here.
- Can/should I somehow tweak the SS config to emit the rewritten URL. I don't think this is quite as tidy, as it'd break if rewrite was disabled.
web.xml
looks like
<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
looks like:
<urlrewrite>
<rule>
<from>^/(.*)$</from>
<to>/-/$1</to>
</rule>
</urlrewrite>
applicationContent-security.xml
looks like:
<http auto-config="true"开发者_Go百科>
<!-- 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>
I looked into this issue for our project last year and at that time the problem was that Tucky wasn't cooperating with response.encodeRedirectUrl() to rewrite redirect URLs. I contacted them but I haven't followed up on this.
My solution was to allow the messy URL to go back to the client but then clean it up with a Tucky redirect rule (a second redirect).
So add another rule that matches your ugly URL from the security redirect and issue your own redirect to the clean URL:
<rule>
<from>^/whatever/ugly.*$</from>
<to type="redirect">/login</to>
</rule>
Yes, it involves two redirects, but the client will never see it... which is probably the point.
Spring security is doing the redirect with an absolute URL like http://example.org/-/login
Try to use an outbound-rule without the ^ start of string
marker to match the absolute url generated by spring.
<outbound-rule>
<from>/-/login(.*)$</from>
<to>/login$1</to>
</outbound-rule>
I ran into the same problem, but it seems fixed in version 3.2.0 of Tuckey. i.e. the response.encodeRedirectUrl() is now wrapped by Tuckeys UrlRewriteWrappedResponse where the outbound rule execution takes place.
I'v never used Tuckey, but after a quick look at the documentation I would try adding one rule for the login case:
<urlrewrite>
<rule>
<from>^/my-context/login$</from>
<to>/my-context/login</to>
</rule>
<rule>
<from>^/(.*)$</from>
<to>/-/$1</to>
</rule>
</urlrewrite>
EDIT
Ok, and something like this:
<urlrewrite>
<rule>
<from>^/-/login$</from>
<to>/login</to>
</rule>
<rule>
<from>^/(.*)$</from>
<to>/-/$1</to>
</rule>
</urlrewrite>
精彩评论