首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SpringSecurity3.1.4带有窗体登录的多个http元素

SpringSecurity3.1.4带有窗体登录的多个http元素
EN

Stack Overflow用户
提问于 2014-02-21 19:19:19
回答 2查看 2.1K关注 0票数 1

我完全知道这个问题已经问过很多次了,但我还没有发现答案。如果它在那里,我道歉,并将非常感谢与它的链接。

电流,工作配置

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

代码语言:javascript
复制
<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/**" ...,它没有强制使用的默认目标。我希望在捕获之前有一个更具体的模式就足够了,但是在所有情况下,它似乎都只是使用最后的catch all块。我已经尝试过了,intercept-url pattern="/**"intercept-url pattern="/foo/**"也是徒劳。

有什么主意吗?!

代码语言:javascript
复制
<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>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-21 21:54:35

为什么这不管用

这样做不起作用的原因是正在发生以下情况:

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

修复此设置

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

代码语言:javascript
复制
<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>

/foo/登录

代码语言:javascript
复制
<form method="post" action="<c:url value='/foo/authenticate'/>">
   ...
</form>

变化的要点:

  • 更新块配置以发送到另一个登录页面。这允许向与/foo/**匹配的自定义URL提交。
  • 确保自定义登录页被授予对匿名用户的访问权限
  • 更新块配置以处理与/foo/**匹配的URL上的身份验证,这将确保always-use-default-target="false"

更好的选择

如果RequestCache为空,Security将将用户发送到默认的目标url。这意味着,如果RequestCache忽略了要发送到默认目标url的请求,那么一切都会正常工作。

对于您的例子,您可以这样做:

代码语言:javascript
复制
<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>

亮点:

  • 只使用主程序(不要使用/foo/**块)
  • 更新块以使用请求缓存元素
  • 创建一个只保存应该重定向到的请求的HttpSessionRequestCache实例。换句话说,忽略应该始终发送到默认目标-url的请求。示例配置将发送与/foo/**不匹配的任何请求到默认目标-url。
票数 2
EN

Stack Overflow用户

发布于 2014-02-21 19:28:16

将配置文件更改为:

代码语言:javascript
复制
<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>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21943338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档