我正在使用默认的Spring Security来处理注销/登录。我有一个处理的Controller方法/login。
/login
注销后,我看到Spring Security将我重定向到app/login?logout。这个Spring创建的参数(有时也存在app/login?error)的存在使我可以将Login处理程序编写为:
app/login?logout
app/login?error
@GetMapping("/participant/login") public ModelAndView loginPage(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "error", required = false) String error, @RequestParam(value = "logout", required = false) String logout) { log.info("Entering participant login page"); ModelAndView mav = new ModelAndView(LOGIN_JSP); if (null != error) { // We're coming to the login page after an Error mav.addObject("info", "My generic error message"); } else if(null != logout){ // We're coming to the login page after a Logout mav.addObject("info", "My generic logout message"); } // ...Otherwise, normal Login page, no extra information
现在的问题是,当我注销时,我需要 将自定义参数传递给/ logout并转移到/ login 。目标是我需要接受一个参数,/login因为我可以像检查系统创建的error和一样检查logout。
error
logout
假设此自定义参数为exitMsg。
exitMsg
从我的应用程序中,我发出以下Spring Security注销URL(注销是自动的,因此我没有针对它的特定处理程序):
myapp.com/app/logout?exitMsg=MyMessage
立即,登录处理程序会丢失此参数,而我没有。
我考虑编写自己的/logout处理程序,在该程序中我手动注销(使会话无效),然后使用此参数重定向到“登录我自己”。这是这里的建议。但是,如果这样做, 我将失去获得Spring的自动 ?logout和?error请求参数的能力。在自动场景中,我正在获取它们,但现在没有。我只得到自己指定的自定义参数。我需要保留?logout并且?error还要测试自己的新参数。
/logout
?logout
?error
任何想法高度赞赏。
Spring安全配置:
@Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/participant/**").authorizeRequests() .antMatchers("/participant/id/**").permitAll() .antMatchers("/participant/faq").permitAll() .antMatchers("/participant/forgetPassword").permitAll() .antMatchers("/participant/securityQuestions").permitAll() .antMatchers("/participant/securityCheck").permitAll() .antMatchers("/participant/resetPassword").permitAll() .antMatchers("/participant/**").authenticated() .and() .formLogin().loginPage("/participant/login").permitAll() .failureUrl("/participant/login?error").permitAll() .defaultSuccessUrl("/participant/home") .usernameParameter("username").passwordParameter("password") .and() .logout().logoutUrl("/participant/logout") .logoutSuccessUrl("/participant/login?logout").permitAll() .and() .csrf().disable(); }
您需要logoutSuccessHandler代替下面的.logoutSuccessUrl("/login?logout") 配置logoutSuccessHandler
logoutSuccessHandler
.logoutSuccessUrl("/login?logout")
@Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/resources/**", "/", "/login", "/api/**") .permitAll() .antMatchers("/app/admin/*") .hasRole("ADMIN") .antMatchers("/app/user/*") .hasAnyRole("ADMIN", "USER") .and().exceptionHandling().accessDeniedPage("/403") .and().formLogin() .loginPage("/login").usernameParameter("userName") .passwordParameter("password") .defaultSuccessUrl("/app/user/dashboard") .failureUrl("/login?error=true") .and().logout() .logoutSuccessHandler(new CustomLogoutSuccessHandler()) .invalidateHttpSession(true) .and().csrf().disable(); http.sessionManagement().maximumSessions(1).expiredUrl("/login?expired=true"); }
我考虑过写自己的/ logout处理程序
实际上,这不是注销处理程序,而是注销启动器。 使用CustomLogoutSuccessHandler,可以在其中获取请求参数,然后可以再次设置它,如下所示。
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { Cookie cookie = new Cookie("JSESSIONID", null); cookie.setPath(request.getContextPath()); cookie.setMaxAge(0); response.addCookie(cookie); if(request.getParameter("expired") != null) { response.sendRedirect(request.getContextPath()+"/login?expired=true"); } else { response.sendRedirect(request.getContextPath() + "/login?logout=true"); } } }
从我的应用程序中,我发出了这个Spring Security注销URL(注销是自动的,因此我没有特定的处理程序)
servlet / spring安全性没有自动注销功能。只有我们能实现的是 1.自动化客户端以发送注销请求 。2.在服务器中,我们可以设置会话的maxInactiveInterval,以便可以通过删除cookie /将cookie的使用期限设置为过去的日期来使会话无效。一旦会话对下一个请求无效,spring安全过滤器链中的一个过滤器会将其重定向到/ param过期的/ login页面。/login?expired 如果您启动注销,spring security将删除cookie /使会话无效,并使用param注销重定向到/ login页面。/login?logout 在Spring Security中,有两种配置可以实现注销。
/login?expired
/login?logout
.and().logout() .invalidateHttpSession(true) //or .deleteCookies("JSESSIONID")
编辑:看到OP的答案后。 缺少在此处添加的信息。OP和我在临时答案(该聊天和答案已被删除)中进行了长时间聊天,我们在其中找到了 LOGIN- WALL 。
“登录墙”是配置错误的结果,您将在其中定义一个自定义登录页面,并将其配置为在身份验证后允许访问的资源。(access=isAuthenticated),但如果我们在使会话无效的情况下重定向到登录页面,则从CustomLogoutSuccessHandler进行弹簧安全性阻止登录页面访问(401-未授权),因为该页面仅允许经过身份验证的用户使用。阻止Spring安全性后,将负责重定向到配置中配置的页面。`.loginPage(“ / someloginpage”)。它迫使人们认为注销正确发生,可以正确重定向到登录页面,但是我在查询字符串中发送的参数没有进入登录页面。 如果我称其为难题,那没错,这很难猜 。
access=isAuthenticated