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

Spring Boot Redirect to requested URL after login

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

当用户请求时 http://www.example.com/myapp/user/22, the application aptly redirects to http://www.example.com/myapp/login. Once the user logs in, the application redirects to http://www.example.com/myapp/dashboard. I would like the application to redirect to 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");
    }
}

并且用户被重定向到 "dashboard"。

我还缺少什么?

使用会话属性中的 "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:/"; 
    }

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

There is no magic in these easy to use features in Spring Security. When a secured resource is being requested, the request will be filtered by a chain of various filters. Authentication principals and permissions will be checked. If the request session is not authenticated yet, AuthenticationException will be thrown.

The AuthenticationException will be caught in the ExceptionTranslationFilter, in which an authentication process will be commenced, resulting in a redirection to the login page.

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

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

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

Spring 路线,扩展 SavedRequestAwareAuthenticationSuccessHandlerSimpleUrlAuthenticationSuccessHandler 实施起来可能有点笨拙。在控制器中(例如处理登录的 POST 方法),您可以自己执行 header 请求;例如:

HttpServletRequest request =null;

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

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