如何重定向到j_spring_security_check

时间:2018-02-13 08:52:42

标签: java spring-mvc redirect spring-security

我有一个spring security,我使用3.2.5实现了登录部分。我使用的spring安全版本是<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd"> <!-- enable use-expressions --> <http auto-config="true" use-expressions="true"> <intercept-url pattern="/login" access="isAnonymous()" /> <form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/login?error" username-parameter="username" password-parameter="password" /> <logout logout-success-url="/login?logout" invalidate-session="false" /> <!-- access denied page --> <access-denied-handler error-page="/403" /> </http> <beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> <beans:property name="userDetailsService" ref="userDetailsService"/> </beans:bean> <beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager"> <beans:property name="providers"> <beans:list> <beans:ref local="daoAuthenticationProvider" /> </beans:list> </beans:property> </beans:bean> <!-- Declare an authentication-manager to use a custom userDetailsService --> <authentication-manager> <authentication-provider user-service-ref="userDetailsService"> <password-encoder hash="bcrypt" /> </authentication-provider> </authentication-manager> </beans:beans> 。我的spring-security.xml文件如下:

@RequestMapping(value = "/edu-login", method = RequestMethod.POST)
public String eduLogin(@ModelAttribute ("username") String username, @ModelAttribute ("password") String password, Model model, HttpServletRequest request, HttpServletResponse response, RedirectAttributes ra)
    {
        //My custom logic to stroe url to session
        ra.addAttribute("username", username);
        ra.addAttribute("password", password);
        return "redirect:/j_spring_security_check";
    }

现在我有一个要求,我最初会显示一些内容,然后用户必须登录才能查看完整内容。所以我提供了一个登录链接,它将显示登录表单。但是当用户登录时,会显示默认页面。我希望将用户重定向到用户已经在的URL。我还尝试将表单发布到我的一个自定义控制器方法,然后从那里重定向到弹簧安全检查。我打算将当前URL存储到方法的会话中,并将用户从spring security的默认目标方法重定向到该方法。但重定向到弹簧安全检查总是给我无效的用户名或密码错误,因为它无法验证用户。我的自定义方法如下:

{{1}}

我的问题有解决办法吗?我想要的只是用户在登录后返回浏览器上的URL。

1 个答案:

答案 0 :(得分:0)

您的用例有一个解决方案,但这不是您应该应用的正确流程。此外,您无法以这种方式使用RedirectAttributes,因为它仅适用于MVC图层,form-login过滤器位于过滤层中。

您尝试实现的顺序是:

public_url > [login:if required] > private_url

对于这样的流程,有一个你可以利用的组件,org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler。正如它在javadoc中所述:

  

身份验证成功策略,可以使用DefaultSavedRequest可能已存储在会话中的ExceptionTranslationFilter。当拦截这样的请求并且需要认证时,存储请求数据以在认证过程开始之前记录原始目的地,并且当重定向到相同URL时允许重建请求。如果适用,此类负责执行重定向到原始URL。

因此,假设您现有的不受保护的网址为/public/edu,而第二个网址(受保护的网址)为/private/edu

/public/edu中,您应该提供指向/private/edu的链接。访问/private/edu时,SpringSecurityFilterChain将检查用户是否经过身份验证并具有所需的授权。

  • 如果用户已经过身份验证,则会直接联系到该网址。
  • 如果没有,它将重定向到登录,同时保持请求的网址/private/edu临时会话。用户执行正确的登录后,SavedRequestAwareAuthenticationSuccessHandler会将用户重定向到/private/edu,而不是默认的成功网址页。

这可能是一个示例配置:

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <!-- enable use-expressions -->
    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/login" access="isAnonymous()" />
        <intercept-url pattern="/private/edu" access="isAnonymous()" />

        <form-login 
            login-page="/login" 
            authentication-success-handler-ref="savedRequestSuccesHandler" 
            authentication-failure-url="/login?error" 
            username-parameter="username"
            password-parameter="password" />

        <logout logout-success-url="/login?logout" invalidate-session="false" />

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

    <beans:bean id="savedRequestSuccesHandler" 
        class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
        <beans:property name="defaultTargetUrl" value="/welcome" />     
    </beans:bean>

    <beans:bean id="daoAuthenticationProvider"
            class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <beans:property name="userDetailsService" ref="userDetailsService"/>
    </beans:bean>

    <beans:bean id="authenticationManager"
            class="org.springframework.security.authentication.ProviderManager">
        <beans:property name="providers">
            <beans:list>
                <beans:ref local="daoAuthenticationProvider" />
            </beans:list>
        </beans:property>
    </beans:bean>

    <!-- Declare an authentication-manager to use a custom userDetailsService -->
    <authentication-manager>
        <authentication-provider user-service-ref="userDetailsService">
        <password-encoder hash="bcrypt" />
        </authentication-provider>
    </authentication-manager>

</beans:beans>

注意我已删除了default-target-url="/welcome"元素的<http>,并引入了属性authentication-success-handler-ref="savedRequestSuccesHandler",它引用了我刚刚创建的新bean:

<beans:bean id="savedRequestSuccesHandler" 
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
      <beans:property name="defaultTargetUrl" value="/welcome" />   
</beans:bean>