登录后重定向到所需位置

Ami*_*rma 4 java spring spring-security

我知道这个问题可以通过不同的解决方案找到。但我无法让它在我的项目中工作。

我们正在向用户发送邮件,其中包含在应用程序中执行某些操作的链接。当用户点击 url 时,如果他没有登录,他应该被重定向到登录页面,登录后应该导航到目标 URL。

我正在尝试使用 CustomLoginSuccessHandler 进行修复,这里是代码:

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

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
        HttpSession session = request.getSession(false);
        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)

我正在使用的配置是:

    @Bean
    public SavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler(){
        CustomLoginSuccessHandler successHandler = new CustomLoginSuccessHandler();
//        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
//        successHandler.setUseReferer(true);    getting NULL in the controller every time
//        successHandler.setTargetUrlParameter("targetUrl"); this also doesnt work as browser is redirect to /login page and URL parameters are lost
        return successHandler;
    }

protected void configure(HttpSecurity http) throws Exception {
        http
                .logout().logoutUrl("/logout").deleteCookies("JSESSIONID").logoutSuccessUrl("/logoutSuccess")
                .and()
                .authorizeRequests()
                .antMatchers("/privacyPolicy", "/faq", "/aboutus", "/termsofuse", "/feedback","/feedbackSubmit", "/contactSsm", "/resources/**", "/userReply", "/userReplySubmit", "/image", "/logoutExternal", "/closeit").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .successHandler(authenticationSuccessHandler)
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .permitAll();
//            .and().exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint());
    }
Run Code Online (Sandbox Code Playgroud)

使用此配置的问题是,如果我请求 url 说“http:localhost:8080/showPage”,spring security 将导航到“http:localhost:8080/login”,并且我无法从原始 URL 捕获任何内容。当我尝试使用自定义变量 targetUrl 并在同一个 CustomLoginSuccessHandler 中使用它时,会出现同样的问题。

如果我采取了错误的方法或缺少其他内容,请告诉我

还尝试使用自定义入口点,但无法使用我的入口点进行重定向。

@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint{

    private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        request.getSession().setAttribute("targetUrl",request.getRequestURL());
        redirectStrategy.sendRedirect(request,response,request.getRequestURL().toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器 :

@RequestMapping(value="/login")
public ModelAndView loginHandler(HttpServletRequest request) {
    ModelAndView mav = new ModelAndView();

    String targetUrl = request.getParameter("targetUrl");
    if(targetUrl!=null){ // targetUrl is always null as spring security is navigating to /login asd parameters are lost
        request.getSession().setAttribute("url_prior_login",targetUrl);
    }
    mav.setViewName("login");
    return mav;
}
Run Code Online (Sandbox Code Playgroud)

要登录,页面将导航到不同的域。我在成功登录后将重定向 URL 传递到该域,它将页面重定向回重定向 URL

<a href="https://domain/sso/identity/login?channel=abc&ru=${externalUrl.applicationUrl}login" >Sign In</a>
Run Code Online (Sandbox Code Playgroud)

M. *_*num 7

Spring Security 已经使用RequestCache默认实现HttpSessionRequestCache存储了 HTTP 会话中的最后一个请求。您可以使用SPRING_SECURITY_SAVED_REQUEST属性名称来访问它,以从会话中获取它。

在你的控制器中做类似的事情

public ModelAndView login(HttpServletRequest req, HttpSession session) {
    ModelAndView mav = new ModelAndView("login");
    if (session != null) {
        SavedRequest savedRequest = session.getAttribute("SPRING_SECURITY_SAVED_REQUEST");
        if (savedRequest != null) {
            mav.addObject("redirectUrl", savedRequest.getRedirectUrl());
        }
    }
    return mav;
}
Run Code Online (Sandbox Code Playgroud)

然后在您的 JSP 中您可以使用redirectUrl来动态构造您的 URL。

http://your.sso/login?url=${redirectUrl}
Run Code Online (Sandbox Code Playgroud)

您需要做的最后一件事是/login将其添加到受permitAll(). 如果不这样做,您将陷入循环或最后一个请求被覆盖并且始终指向登录页面。

.antMatchers("/privacyPolicy", "/faq", "/aboutus", "/termsofuse", "/feedback","/feedbackSubmit", "/contactSsm", "/resources/**", "/userReply", "/userReplySubmit", "/image", "/logoutExternal", "/closeit", "/login").permitAll()
Run Code Online (Sandbox Code Playgroud)

您不需要任何其他自定义类(例如EntryPoints 或AuthenticationSuccessHandler实现)。

然而,当您使用 SSO 时,最好研究与 SSO 解决方案的正确集成,而不是使用登录页面进行此黑客攻击。