登录后重定向到所需位置

时间:2015-06-12 08:15:31

标签: java spring spring-security

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

我们正在向用户发送邮件,这些用户可以在应用程序中执行某些操作。当用户点击网址时,如果他没有登录,则应该重定向到登录页面,登录后应导航到目标网址。

我正在尝试修复使用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);
        }
    }
}

我使用的配置是:

    @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());
    }

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

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

还尝试使用Custom EntryPoint但无法使用我的入口点重定向。

@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());
    }
}

控制器:

@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;
}

要登录,页面将导航到其他域。我成功登录后将重定向URL传递到该域,将页面重定向回redirecturl

<a href="https://domain/sso/identity/login?channel=abc&ru=${externalUrl.applicationUrl}login" >Sign In</a>

2 个答案:

答案 0 :(得分:4)

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;
}

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

http://your.sso/login?url=${redirectUrl}

您需要做的最后一件事是通过将/login添加到受permitAll()保护的列表,使每个人都可以访问.antMatchers("/privacyPolicy", "/faq", "/aboutus", "/termsofuse", "/feedback","/feedbackSubmit", "/contactSsm", "/resources/**", "/userReply", "/userReplySubmit", "/image", "/logoutExternal", "/closeit", "/login").permitAll() 。如果你不这样做,你将进入循环或最后一个请求被覆盖,并始终指向登录页面。

EntryPoint

您不需要任何其他自定义类,例如AuthenticationSuccessHandlervar res = list.Skip(noOfElementToSkip).Take(noOfElementsToTake); 实现。

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

答案 1 :(得分:0)

您至少会遇到一个问题:getSession(false)

  

的getSession()             返回与此请求关联的当前会话,或者如果请求没有会话,创建一个

如果您希望在没有会话时返回空值,则应使用null

在您的情况下,您永远不会得到libxml2会话。