登录后 Spring Boot 重定向到请求的 URL

Posted

技术标签:

【中文标题】登录后 Spring Boot 重定向到请求的 URL【英文标题】:Spring Boot Redirect to requested URL after login 【发布时间】:2018-11-16 20:04:24 【问题描述】:

我有一个 Spring Boot UI 应用程序。我正在尝试在登录后将用户重定向到最初请求的 URL。

当用户请求http://www.example.com/myapp/user/22 时,应用程序会适当地重定向到http://www.example.com/myapp/login。用户登录后,应用程序将重定向到http://www.example.com/myapp/dashboard。我希望应用程序重定向到http://www.example.com/myapp/user/22。

我浏览了几个链接,感觉我的配置正确,但是重定向没有按预期工作。

我的安全配置是

public class SecurityConfig extends WebSecurityConfigurerAdapter 
.....
....

    @Autowired
    private MyAuthenticationSuccessHandler authenticationSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.
        authorizeRequests()
                .antMatchers("/user/**").authenticated()
                .and().csrf().disable().formLogin()
                .successHandler(authenticationSuccessHandler)
......

我的成功处理程序是

    @Component
    public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler 
    ...
public MyAuthenticationSuccessHandler() 
        super();
        this.setDefaultTargetUrl("/myapp/dashboard");
        this.setUseReferer(true);
    

        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws IOException, ServletException 
            //Do something ..........
            ........
            .........
            super.onAuthenticationSuccess(request, response, authentication);

我也尝试过使用 SavedRequestAwareAuthenticationSuccessHandler。

我注意到我的成功处理程序被调用,但目标 URL 始终是 /user/login 并且我的登录控制器被调用..

@RequestMapping("/login")
public ModelAndView login(@ModelAttribute() 
    if(!userIdentified) 
        //go to login page
     else 
        new ModelAndView("redirect:/myapp/dashboard");
    

并且用户被重定向到“仪表板”。

我还缺少什么?

【问题讨论】:

【参考方案1】:

使用会话属性中的“Referer”获取最新的请求 URL。在我的应用程序上,我使用这个

public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler 

    public static final String REDIRECT_URL_SESSION_ATTRIBUTE_NAME = "REDIRECT_URL";

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException 

        Object redirectURLObject = request.getSession().getAttribute(REDIRECT_URL_SESSION_ATTRIBUTE_NAME);

        if(redirectURLObject != null)
            setDefaultTargetUrl(redirectURLObject.toString());
        else
            setDefaultTargetUrl("/");
        

        request.getSession().removeAttribute(REDIRECT_URL_SESSION_ATTRIBUTE_NAME);
        super.onAuthenticationSuccess(request, response, authentication);
    


编辑:

对不起,我忘了显示登录控制器

@RequestMapping(method = RequestMethod.GET, value = "/login")
    String login(Model model, Principal principal, HttpServletRequest request) throws Exception
        String referer = request.getHeader("Referer"); //Get previous URL before call '/login'

        //save referer URL to session, for later use on CustomAuthenticationSuccesshandler
        request.getSession().setAttribute(CustomAuthenticationSuccessHandler.REDIRECT_URL_SESSION_ATTRIBUTE_NAME, referer); 


        return principal == null ?  "login" : "redirect:/"; 
    

【讨论】:

嗯……重定向 url 对象始终为空。我是否缺少其他配置?该属性是如何/在哪里设置的? 抱歉,刚刚更新了答案,如果有效请告诉我 Referer 也是 null :( 触发失败 URL... .failureUrl("/myapp/login?error=true") 我猜这就是 /login 的调用方式。 我的运行良好,可能只是缺少安全配置。查看here 和here 啊!!!想通了这个问题。我们有一个带有 @ExceptionHandler(AccessDeniedException.class) 注释方法的 ExceptionResolver,它重定向到 /myapp/login。因此,我得到了一个 302 重定向,它将引用者设置为 /login。现在,我在这个方法的 session 中设置了 referer,并在 MyAuthenticationSuccessHandler 中使用它来重定向。我也这样做了。setUseReferer(false);现在一切都按预期工作。谢谢辛吉。【参考方案2】:

虽然Singgih S 回答有效,但但是有一个更好的方法如下: 参考: https://www.baeldung.com/spring-security-redirect-login

Spring Security 中这些易于使用的功能没有什么神奇之处。 当请求安全资源时,请求将是 由一系列不同的过滤器过滤。身份验证主体和 权限将被检查。如果请求会话不是 尚未通过身份验证,将抛出 AuthenticationException。

AuthenticationException 将在 ExceptionTranslationFilter,其中将进行身份验证过程 开始,导致重定向到登录页面。

因此: 1. 当重定向到“/login”页面时,您的安全请求 url 在会话中保存为 DefaultSavedRequest 对象。 2. 我们还知道,当基于表单的登录成功发生时,会调用 AuthenticationSuccessHandler 的实现之一。 因此我们可以创建一个自定义类并在其中获取 DefaultSavedRequest,如下所示:

public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler 


    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException 
        DefaultSavedRequest defaultSavedRequest = (DefaultSavedRequest) request.getSession().getAttribute("SPRING_SECURITY_SAVED_REQUEST");
        if(defaultSavedRequest != null)
            getRedirectStrategy().sendRedirect(request, response, defaultSavedRequest.getRedirectUrl());
        else
            super.onAuthenticationSuccess(request, response, authentication);
        
    

3. 我们要在 WebSecurityConfigurerAdapter 中引入这个类:

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.(...).anyRequest().authenticated().and()
                        .formLogin()
                        .loginPage("/login")
                        .loginProcessingUrl("/login")
                        .successHandler(new CustomAuthenticationSuccessHandler());

所以你可以在上面的 onAuthenticationSuccess 方法中实现你的逻辑。 最好的祝福

【讨论】:

【参考方案3】:

Spring 路由,扩展 SavedRequestAwareAuthenticationSuccessHandlerSimpleUrlAuthenticationSuccessHandler 可能有点笨拙。在控制器中(例如处理登录的 POST 方法),您可以自己进行标头请求;例如:

HttpServletRequest request =null;

String priorUrl = request.getHeader("Referer");

您会注意到,在手动(由用户启动)注销或会话超时(由 Spring 会话处理)之前,您将拥有该 URL:您将获得一个 https://iAmPriorUrl.com/...。然后你可以用它做任何你想做的事情。

【讨论】:

以上是关于登录后 Spring Boot 重定向到请求的 URL的主要内容,如果未能解决你的问题,请参考以下文章

Spring登录后如何重定向到请求的页面?

成功登录后 Spring Boot Security 重定向 - 未定义

会话超时后,Spring 安全性不会重定向到上次请求的页面登录

spring boot项目在eclipse里跑可以访问登录页,但是打jar包后访问登录页报重定向次数过多

spring boot 重定向到页面登录

通过 Okta 进行身份验证后,会话 cookie 不会发送到 Spring Boot 应用程序