Spring security 3.1.4带有form-login的多个http元素

时间:2014-02-21 19:19:19

标签: java spring spring-security

我完全清楚这个问题已被多次提出,但我还没有找到答案。如果它在那里,我道歉并且非常感谢它的链接。

当前,工作配置

下面是我当前工作配置的一个片段,它允许访问上面的<http />元素块而没有任何安全性,但需要具有其中一个角色的经过身份验证的用户才能登录。

<http pattern="/" security="none" disable-url-rewriting="true" />
<http pattern="/login" security="none" disable-url-rewriting="true" />
<http pattern="/cookieInfo" security="none" disable-url-rewriting="true" />
<http pattern="/error" security="none" disable-url-rewriting="true" />
<http pattern="/cookiesDisabled" security="none" disable-url-rewriting="true" />
<http pattern="/loginFailed" security="none" disable-url-rewriting="true" />
<http pattern="/static/**" security="none" disable-url-rewriting="true" />

<http access-decision-manager-ref="accessDecisionManager" disable-url-rewriting="true">
    <custom-filter before="FIRST" ref="cookiePresentFilter" />
    <intercept-url pattern="/**" access="ROLE_1,ROLE_2,ROLE_3" />
    <form-login login-page="/login" default-target-url='/loginSuccess' always-use-default-target='true' authentication-failure-url="/loginFailed" />
    <logout />
</http>

期望的,不工作的配置

我想要一个特殊的部分,如下所示为<http pattern="/foo/**" ...,它没有强制使用的默认目标。我希望在捕获之前只有一个更具体的模式就足够了,但是它似乎只是在所有情况下使用最终捕获所有块。我试过intercept-url pattern="/**" intercept-url pattern="/foo/**"也无济于事。

有什么想法吗?!

<http pattern="/" security="none" disable-url-rewriting="true" />
<http pattern="/login" security="none" disable-url-rewriting="true" />
<http pattern="/loginFailed" security="none" disable-url-rewriting="true" />
<http pattern="/static/**" security="none" disable-url-rewriting="true" />

<http pattern="/foo/**" access-decision-manager-ref="accessDecisionManager" disable-url-rewriting="true">
    <intercept-url pattern="/**" access="ROLE_1,ROLE_2,ROLE_3" />
    <form-login login-page="/login" authentication-failure-url="/loginFailed" />
    <logout />
</http>

<http access-decision-manager-ref="accessDecisionManager" disable-url-rewriting="true">
    <intercept-url pattern="/**" access="ROLE_1,ROLE_2,ROLE_3" />
    <form-login login-page="/login" default-target-url='/loginSuccess' always-use-default-target='true' authentication-failure-url="/loginFailed" />
    <logout />
</http>

2 个答案:

答案 0 :(得分:2)

为什么这不起作用

这不起作用的原因是因为发生了以下情况:

  • 如果您请求与/ foo / **匹配的网址,则该网页会缓存在RequestCache中。默认实现是通过在HttpSession中缓存请求来实现的。
  • 然后Spring Security会将您发送到/ login,其上可能有一个表单,发布到/ j_spring_security_check
  • 当用户对请求进行身份验证时,/ j_spring_security_check与/ foo / **不匹配,因此第二个元素对其进行身份验证。 always-use-default-target="true"在身份验证时应用,而不是发送到登录表单的时间。由于身份验证请求与/ foo / **不匹配,因此用户将始终发送到default-target-url

修复此设置

要解决此问题,您需要执行以下操作:

<http pattern="/foo/**" ...>
    <intercept-url pattern="/foo/login" access="ROLE_ANONYMOUS"/>
    <intercept-url pattern="/**" access="ROLE_1,ROLE_2,ROLE_3" />
    <form-login
        ... 
        default-target-url="/loginSuccess 
        login-page="/foo/login" 
        login-processing-url="/foo/authenticate" />
    ...
</http>

<强> /富/登录

<form method="post" action="<c:url value='/foo/authenticate'/>">
   ...
</form>

变化的重点:

  • 更新阻止配置以发送到其他登录页面。这允许提交与/ foo / **
  • 匹配的自定义URL
  • 确保自定义登录页面被授予匿名用户访问权限
  • 更新阻止配置以处理与/ foo / **匹配的网址的身份验证。这可确保always-use-default-target="false"

更好的选择

如果RequestCache为空,Spring Security会将用户发送到default-target-url。这意味着如果RequestCache忽略您要发送到default-target-url的请求,一切都会有效。

对于您的示例,您可以执行以下操作:

<http access-decision-manager-ref="accessDecisionManager" disable-url-rewriting="true">
    <intercept-url pattern="/**" access="ROLE_1,ROLE_2,ROLE_3" />
    <form-login login-page="/login" default-target-url='/loginSuccess' always-use-default-target='true' authentication-failure-url="/loginFailed" />
    <logout />

    <request-cache ref="requestCache"/>
</http>

<bean:bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache">
    <bean:property name="requestMatcher">
        <bean:bean class="org.springframework.security.web.util.RegexRequestMatcher">
            <bean:constructor-arg value="^(?!/foo/).+"/>
            <bean:constructor-arg><bean:null/></bean:constructor-arg>
            <bean:constructor-arg value="true"/>
        </bean:bean>
    </bean:property>
</bean:bean>

亮点:

  • 仅使用main(不要使用/ foo / **块)
  • 更新块以使用request-cache元素
  • 创建一个HttpSessionRequestCache实例,该实例仅保存应重定向到的请求。换句话说,忽略应始终发送到default-target-url的请求。示例配置会将任何与/ foo / **不匹配的请求发送到default-target-url。

答案 1 :(得分:0)

将配置文件更改为以下内容:

<http access-decision-manager-ref="accessDecisionManager" disable-url-rewriting="true">
    <intercept-url pattern="/foo/**" access="permitAll" />
    <intercept-url pattern="/**" access="ROLE_1,ROLE_2,ROLE_3" />
    <form-login login-page="/login" default-target-url='/loginSuccess' always-use-default-target='true' authentication-failure-url="/loginFailed" />
    <logout />
</http>