成功登录后,Spring Security会重定向到上一页

Chr*_*kis 53 redirect spring login spring-security

我知道之前已经问过这个问题,但是我在这里遇到了一个特殊的问题.

我使用spring security 3.1.3.

我的Web应用程序中有3个可能的登录案例:

  1. 通过登录页面登录:好的.
  2. 通过限制页面登录:也可以.
  3. 通过非限制页面登录:不行......每个人都可以访问"产品"页面,如果用户登录,用户可以发表评论.因此,登录表单包含在同一页面中,以便允许用户连接.

案例3)的问题是我无法将用户重定向到"产品"页面.无论如何,他们会在成功登录后重定向到主页.

请注意,对于案例2),成功登录后,重定向到受限页面的工作开箱即用.

这是我的security.xml文件的相关部分:

<!-- Authentication policy for the restricted page  -->
<http use-expressions="true" auto-config="true" pattern="/restrictedPage/**">
    <form-login login-page="/login/restrictedLogin" authentication-failure-handler-ref="authenticationFailureHandler" />
    <intercept-url pattern="/**" access="isAuthenticated()" />
</http>

<!-- Authentication policy for every page -->
<http use-expressions="true" auto-config="true">
    <form-login login-page="/login" authentication-failure-handler-ref="authenticationFailureHandler" />
    <logout logout-url="/logout" logout-success-url="/" />
</http>
Run Code Online (Sandbox Code Playgroud)

我怀疑"每个页面的身份验证策略"都要对此问题负责.但是,如果我将其删除,我将无法再登录... j_spring_security_check发送404错误.


编辑:

感谢拉尔夫,我找到了解决方案.所以这就是事情:我使用了这个属性

<property name="useReferer" value="true"/>
Run Code Online (Sandbox Code Playgroud)

拉尔夫给我看了.之后我遇到了我的案例问题1):当通过登录页面登录时,用户停留在同一页面(并没有重定向到主页,就像以前一样).直到此阶段的代码如下:

<!-- Authentication policy for login page -->
<http use-expressions="true" auto-config="true" pattern="/login/**">
    <form-login login-page="/login" authentication-success-handler-ref="authenticationSuccessHandlerWithoutReferer" />
</http>

<!-- Authentication policy for every page -->
<http use-expressions="true" auto-config="true">
    <form-login login-page="/login" authentication-failure-handler-ref="authenticationFailureHandler" />
    <logout logout-url="/logout" logout-success-url="/" authentication-success-handler-ref="authenticationSuccessHandler"/>
</http>

<beans:bean id="authenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    <!-- After login, return to the last visited page -->
    <beans:property name="useReferer" value="true" />
</beans:bean>

<beans:bean id="authenticationSuccessHandlerWithoutReferer" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    <!-- After login, stay to the same page -->
    <beans:property name="useReferer" value="false" />
</beans:bean>
Run Code Online (Sandbox Code Playgroud)

至少在理论上这应该有效,但事实并非如此.我仍然不知道为什么,所以如果有人对此有答案,我很乐意创建一个新主题,让他分享他的解决方案.

与此同时,我找到了解决方法.不是最好的解决方案,但就像我说的,如果有人有更好的表现,我会全力以赴.这是登录页面的新身份验证策略:

<http use-expressions="true" auto-config="true" pattern="/login/**" >
    <intercept-url pattern="/**" access="isAnonymous()" />
    <access-denied-handler error-page="/"/>
</http>
Run Code Online (Sandbox Code Playgroud)

这里的解决方案非常明显:只有匿名用户才能使用登录页面.连接用户后,错误处理程序会将其重定向到主页.

我做了一些测试,一切似乎都运行得很好.

Ral*_*lph 44

登录后(用户被重定向到哪个URL)发生的事情由AuthenticationSuccessHandler.处理.

此接口(实现它的具体类SavedRequestAwareAuthenticationSuccessHandler)由方法中的(AbstractAuthenticationProcessingFilterUsernamePasswordAuthenticationFilter)子类(如())调用successfulAuthentication.

因此,为了在案例3中进行其他重定向,您必须进行子类化SavedRequestAwareAuthenticationSuccessHandler并使其成为您想要的.


有时(取决于您的确切用例),足以启用由(超类)调用的useReferer标志.AbstractAuthenticationTargetUrlRequestHandlerSimpleUrlAuthenticationSuccessHandlerSavedRequestAwareAuthenticationSuccessHandler

<bean id="authenticationFilter"
      class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="filterProcessesUrl" value="/login/j_spring_security_check" />
    <property name="authenticationManager" ref="authenticationManager" />
    <property name="authenticationSuccessHandler">
        <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
            <property name="useReferer" value="true"/>
        </bean>
    </property>
    <property name="authenticationFailureHandler">
        <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
            <property name="defaultFailureUrl" value="/login?login_error=t" />
        </bean>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)


Utk*_*mir 39

我想扩展Olcay的好答案.他的方法很好,您的登录页面控制器应该像这样将referrer url放入会话:

@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage(HttpServletRequest request, Model model) {
    String referrer = request.getHeader("Referer");
    request.getSession().setAttribute("url_prior_login", referrer);
    // some other stuff
    return "login";
}
Run Code Online (Sandbox Code Playgroud)

你应该扩展SavedRequestAwareAuthenticationSuccessHandler并覆盖它的onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)方法.像这样的东西:

public class MyCustomLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    public MyCustomLoginSuccessHandler(String defaultTargetUrl) {
        setDefaultTargetUrl(defaultTargetUrl);
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
        HttpSession session = request.getSession();
        if (session != null) {
            String redirectUrl = (String) session.getAttribute("url_prior_login");
            if (redirectUrl != null) {
                // we do not forget to clean this attribute from session
                session.removeAttribute("url_prior_login");
                // then we redirect
                getRedirectStrategy().sendRedirect(request, response, redirectUrl);
            } else {
                super.onAuthenticationSuccess(request, response, authentication);
            }
        } else {
            super.onAuthenticationSuccess(request, response, authentication);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在spring配置中,您应该将此自定义类定义为bean并在安全配置中使用它.如果您使用的是注释配置,它应该如下所示(您扩展的类WebSecurityConfigurerAdapter):

@Bean
public AuthenticationSuccessHandler successHandler() {
    return new MyCustomLoginSuccessHandler("/yourdefaultsuccessurl");
}
Run Code Online (Sandbox Code Playgroud)

configure方法中:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            // bla bla
            .formLogin()
                .loginPage("/login")
                .usernameParameter("username")
                .passwordParameter("password")
                .successHandler(successHandler())
                .permitAll()
            // etc etc
    ;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我有以下解决方案,它对我有用.

每当请求登录页面时,将referer值写入会话:

@RequestMapping(value="/login", method = RequestMethod.GET)
public String login(ModelMap model,HttpServletRequest request) {

    String referrer = request.getHeader("Referer");
    if(referrer!=null){
        request.getSession().setAttribute("url_prior_login", referrer);
    }
    return "user/login";
}
Run Code Online (Sandbox Code Playgroud)

然后,成功登录后自定义实现SavedRequestAwareAuthenticationSuccessHandler将用户重定向到上一页:

HttpSession session = request.getSession(false);
if (session != null) {
    url = (String) request.getSession().getAttribute("url_prior_login");
}
Run Code Online (Sandbox Code Playgroud)

重定向用户:

if (url != null) {
    response.sendRedirect(url);
}
Run Code Online (Sandbox Code Playgroud)