java - Spring security 3.1.4 带有表单登录的多个http元素

标签 java spring spring-security

我完全知道这个问题已经被问过很多次了,但我还没有偶然发现答案。如果有的话,我深表歉意,并且非常感谢您提供指向它的链接。

当前工作配置

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

<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 之前有一个更具体的模式就足够了,但是似乎在所有情况下都只使用最终的 catch all block 。我尝试过 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>

最佳答案

为什么这不起作用

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

  • 如果您请求与/foo/** 匹配的 URL,该页面将缓存在 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>

/foo/登录

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

变化要点:

  • 更新 block 配置以发送到不同的登录页面。这允许提交到与/foo/** 匹配的自定义 URL
  • 确保自定义登录页面被授予匿名用户访问权限
  • 更新 block 配置以处理与/foo/** 匹配的 URL 上的身份验证,这可确保 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/** block )
  • 更新 block 以使用 request-cache元素
  • 创建 HttpSessionRequestCache 的实例,仅保存应重定向到的请求。换句话说,忽略应始终发送到 default-target-url 的请求。示例配置会将任何与/foo/** 不匹配的请求发送到 default-target-url。

关于java - Spring security 3.1.4 带有表单登录的多个http元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21943338/

相关文章:

java - 从 HTML [JAVA] [PD4ML] 生成 PDF 时,阿拉伯语内容显示为 "?"

java - Spring MVC 无法转换类型为 'java.lang.Integer' 的属性值

java - Spring Security 过滤器有多个 URL 拦截映射

java - Spring Security oauth2 客户端

java - 什么时候初始化成员?

java - 在 Spring Boot 中处理重定向的正确方法是什么?

java - 当前线程的范围 'request' 不活动 - websocket 版本

json - Spring 3.2RC1 中来自 JodaTime 的 jackson2 JSON ISO 8601 日期

java - @ModelAttribute 不适用于 Spring Security

java - 使用 .proto 模式将 base64 proto 二进制文件转换为人类可读的 (json/xml)