Spring Security,注销:将参数从/logout 传递到/login [英] Spring Security, Logout: Pass parameter from /logout to /login
问题描述
我使用默认的 Spring Security 来处理注销/登录.我有一个处理 /login
的 Controller 方法.
当我注销时,我看到 Spring Security 将我重定向到 app/login?logout
.这个 Spring 创建的参数(有时还有 app/login?error
)的存在允许我将我的登录处理程序编写为:
@GetMapping("/参与者/登录")公共 ModelAndView loginPage(HttpServletRequest 请求,HttpServletResponse 响应,@RequestParam(value = "error", required = false) 字符串错误,@RequestParam(value = "logout", required = false) String logout) {log.info("进入参会者登录页面");ModelAndView mav = new ModelAndView(LOGIN_JSP);如果(空!= 错误){//我们在错误后进入登录页面mav.addObject("info", "我的通用错误信息");} else if(null !=注销){//我们在注销后进入登录页面mav.addObject("info", "我的通用注销消息");}//...否则,正常登录页面,没有额外信息
现在的问题是,当我注销时,我需要将自定义参数传递给/logout 并传输到/login.目标是我需要在 /login
中接收一个参数,我可以像系统创建的 error
和 logout
一样检查它.
假设这个自定义参数是exitMsg
.
我从我的应用程序发出这个 Spring Security 注销 URL(注销是自动的,所以我没有特定的处理程序):
myapp.com/app/logout?exitMsg=MyMessage
立即,登录处理程序丢失了这个参数,而我没有.
我考虑编写自己的 /logout
处理程序,在其中手动注销(使会话无效),然后使用此参数重定向到自己登录.这是此处的建议.但是如果我这样做,我将失去获得 Spring 自动 ?logout
和 ?error
请求参数的能力.在自动场景中,我得到了它们,现在我没有.我只得到我自己指定的自定义参数.我需要保留 ?logout
和 ?error
并测试我自己的新参数.
高度赞赏任何想法.
Spring 安全配置:
@Overrideprotected void configure(HttpSecurity http) 抛出异常 {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("/参与者/登录").permitAll().failureUrl("/participant/login?error").permitAll().defaultSuccessUrl("/参与者/家").usernameParameter("用户名").passwordParameter("密码").and().logout().logoutUrl("/参与者/注销").logoutSuccessUrl("/participant/login?logout").permitAll().and().csrf().disable();}
你需要 logoutSuccessHandler
而不是 .logoutSuccessUrl("/login?logout")
配置 logoutSuccessHandler
如下
@Overrideprotected void configure(final HttpSecurity http) 抛出异常{http.authorizeRequests().antMatchers("/resources/**", "/", "/login", "/api/**").permitAll().antMatchers("/app/admin/*").hasRole("管理员").antMatchers("/app/user/*").hasAnyRole("管理员","用户").and().exceptionHandling().accessDeniedPage("/403").and().formLogin().loginPage("/login").usernameParameter("userName").passwordParameter("密码").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;导入 javax.servlet.ServletException;导入 javax.servlet.http.Cookie;导入 javax.servlet.http.HttpServletRequest;导入 javax.servlet.http.HttpServletResponse;导入 org.springframework.security.core.Authentication;导入 org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;公共类 CustomLogoutSuccessHandler 扩展 SimpleUrlLogoutSuccessHandler{@覆盖public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) 抛出 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");}别的{response.sendRedirect(request.getContextPath() + "/login?logout=true");}}}
<块引用>
我从我的应用程序发出这个 Spring Security 注销 URL(注销是自动的,所以我没有特定的处理程序)
servlet/spring security 中没有自动注销功能.我们能达到的只有
1.自动客户端发送注销请求
2.在服务器端我们可以设置session的maxInactiveInterval,这样可以通过删除cookie/设置cookie的年龄为过去日期来使session失效.一旦会话对于下一个请求无效,spring 安全过滤器链中的一个过滤器会将其重定向到/login 页面,参数已过期./login?expired
如果您启动注销,spring security 将删除 cookie/使会话无效并使用参数 logout 重定向到/login 页面./login?logout
spring security中实现注销的配置有两种.
.and().logout().invalidateHttpSession(true)//或.deleteCookies("JSESSIONID")
<小时>
在看到 OP 的回答之后.在此处添加缺少的信息.OP 和我在临时回答中进行了长时间聊天(该聊天和回答已被删除),我们在那里找到了 LOGIN-WALL.
登录墙"是错误*配置的结果,您将在其中定义自定义登录页面,并将其配置为在身份验证后允许访问的资源.(access=isAuthenticated
) 但来自 CustomLogoutSuccessHandler 如果我们在会话无效后重定向到登录页面 spring 安全阻止登录页面访问(401-Un 授权),因为该页面仅允许经过身份验证的用户使用.阻止后,spring security 负责重定向到配置中配置的页面.`.loginPage("/someloginpage").它强制认为注销正确发生,正确重定向到登录页面,但我在查询字符串中发送的参数没有进入登录页面.如果我将其称为非常难以猜测的谜题也没有错.
I'm using default Spring Security to handle logout/login. I have a Controller method that handles /login
.
When I log out, I see that Spring Security redirects me to app/login?logout
. The existence of this Spring-created parameter (and also sometimes app/login?error
) allows me to write my Login handler as:
@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
Now the problem is that when I log out, I need to pass a custom parameter to /logout with a transfer to /login. The goal is I need to receive a param in /login
that I can examine just like the system-created error
and logout
.
Suppose this custom param is exitMsg
.
From my app I issue this Spring Security Logout URL (logout is automatic, so I don't have a specific handler for it):
myapp.com/app/logout?exitMsg=MyMessage
Right away, the Login handler loses this param and I don't have it.
I considered writing my own /logout
handler, where I manually log out (invalidate the session), and then redirect to Login myself with this param. This is the suggestion here. But if I do that, I lose the ability to get Spring's automatic ?logout
and ?error
Request Params. In the automatic scenario I was getting them, and now I'm not. I'm only getting the custom parameter I specify myself. I need to keep ?logout
and ?error
and also test for my own new param.
Any thoughts highly appreciated.
Spring Security Config:
@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();
}
You need logoutSuccessHandler
instead of .logoutSuccessUrl("/login?logout")
Configure logoutSuccessHandler
as given below
@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");
}
I considered writing my own /logout handler
In fact that is not logout handler but it is logout initiator.
Use CustomLogoutSuccessHandler, where you can get request param's and you can set it again, as given below.
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");
}
}
}
From my app I issue this Spring Security Logout URL (logout is automatic, so I don't have a specific handler for it)
There is no automatic logout feature in servlet/spring security. Only what we can achieve is
1. Automate client to send logout request
2. In server we can set session's maxInactiveInterval, so that session can be invalidated by deleting cookie/setting age of cookie to past date. Once session is invalidated for the next request one of filter in spring security filter chain redirects it to /login page with param expired./login?expired
If you initiates logout spring security will delete the cookie/invalidate the session and redirects to /login page with param logout./login?logout
There are two types of configuration of achieving logout in spring security.
.and().logout()
.invalidateHttpSession(true)
//or
.deleteCookies("JSESSIONID")
EDIT: After Seeing OP's Answer. Missing info adding here. OP and i had a long chat in temporary answer(That chat and answer has been deleted) where we found the LOGIN-WALL.
"login-wall" is a outcome of bad* configuration where you will define a custom login page and it is configured as resource that is allowed to access after authentication. (access=isAuthenticated
) but from CustomLogoutSuccessHandler if we redirect to login page after invalidating session spring security blocks login page access(401-Un Authorized) since that page is allowed only for authenticated-user. After blocking spring security takes care of redirects to the page configured in configuration. `.loginPage("/someloginpage"). What it forces to think is logout happening correctly, redirecting to login page correctly but params i sent in query string are not coming to loginpage.
Nothing wrong if i call this as puzzle which is very hard to guess.
这篇关于Spring Security,注销:将参数从/logout 传递到/login的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!