Java 从CustomLogoutHandler重定向到';登录-注销';被重定向到';登录';
我有两个安全区域,我提供基于表单的登录Java 从CustomLogoutHandler重定向到';登录-注销';被重定向到';登录';,java,spring,spring-mvc,spring-security,logout,Java,Spring,Spring Mvc,Spring Security,Logout,我有两个安全区域,我提供基于表单的登录 /user /admin 以下工作如预期: 访问受保护资源时重定向到登录页面 凭据为false时,重定向到登录页面时出现?错误参数 防止基于定义的角色访问受保护的资源 以下操作不起作用: 注销后重定向到登录页面 当注销时,我重定向到/user/login?logout,以显示一条消息“You'e logged out”,指示注销成功。但是,这不起作用,而是重定向到/user/login?注销被重定向到/user/login,因此不显示任何消息
/user
/admin
- 访问受保护资源时重定向到登录页面
- 凭据为false时,重定向到登录页面时出现
?错误
参数
- 防止基于定义的角色访问受保护的资源
- 注销后重定向到登录页面
/user/login?logout
,以显示一条消息“You'e logged out”,指示注销成功。但是,这不起作用,而是重定向到/user/login?注销
被重定向到/user/login
,因此不显示任何消息
当我删除自定义注销处理程序.logoutSuccessHandler(logoutSuccessHandler())
,而是包含.logoutSuccessUrl(“/user/login?logout”).permitAll()
时,它会工作
但是,我希望此处理程序在注销时执行其他操作
@Configuration
@Order(1)
public static class FormLoginUser extends WebSecurityConfigurerAdapter {
@Bean
public AccessDeniedHandler accessDeniedHandler() {
return new UserCustomAccessDeniedHandler();
}
@Bean
public LogoutSuccessHandler logoutSuccessHandler() {
return new UserCustomLogoutSuccessHandler();
}
@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return new UserCustomAuthenticationSuccessHandler();
}
private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource() {
return WebAuthenticationDetails::new;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/user/**")
.authorizeRequests().anyRequest().hasRole("USER")
.and()
.formLogin()
.loginPage("/user/login")
.permitAll()
.authenticationDetailsSource(authenticationDetailsSource())
.successHandler(authenticationSuccessHandler())
.and()
.logout()
.logoutUrl("/user/logout")
.logoutSuccessUrl("/user/login?logout").permitAll()
.logoutSuccessHandler(logoutSuccessHandler())
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler())
;
}
}
@Configuration
@Order(2)
public static class FormLoginAdmin extends WebSecurityConfigurerAdapter {
@Bean
public AccessDeniedHandler adminAccessDeniedHandler() {
return new AdminCustomAccessDeniedHandler();
}
@Bean
public LogoutSuccessHandler adminLogoutSuccessHandler() {
return new AdminCustomLogoutSuccessHandler();
}
@Bean
public AuthenticationSuccessHandler adminAuthenticationSuccessHandler() {
return new AdminCustomAuthenticationSuccessHandler();
}
private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource() {
return WebAuthenticationDetails::new;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/admin/**")
.authorizeRequests().anyRequest().hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/admin/login")
.authenticationDetailsSource(authenticationDetailsSource())
.successHandler(adminAuthenticationSuccessHandler())
.permitAll()
.and()
.logout()
.logoutUrl("/admin/logout")
.logoutSuccessHandler(adminLogoutSuccessHandler())
.and()
.exceptionHandling().accessDeniedHandler(adminAccessDeniedHandler());
}
}
在DevTools中,我可以清楚地看到,每当我尝试访问URL/user/login?logout
时,GET请求将在302中生成,然后对user/login
发出一个新请求。当我在浏览器URL行中手动编辑URL或通过表单Post从应用程序触发注销时,就会发生这种情况
当我删除logoutSuccessHandler
时,我可以在浏览器中手动输入URL,并在应用程序中从我的表单帖子中触发它
我还尝试:
- 将用于登录和注销的URL移出中断登录的路径
->/user
- 使用
定义第三个配置,明确允许登录和注销页面上的GET和POST->这也破坏了登录Order(1)
- 不要使用
,而是使用.antMatcher
,不过我想我将无法拥有两个不同的formlogin.antMatchers
@覆盖
受保护的无效配置(HttpSecurity http)引发异常
{
http
.antMatcher(“/user/**”).authorizedRequests()
.antMatchers(“/user/login”).permitAll()//解决方案
.anyRequest().hasRole(“用户”)
.及()
.formLogin()
.loginPage(“/user/login”)
.permitAll()
.authenticationDetailsSource(authenticationDetailsSource())
.successHandler(authenticationSuccessHandler())
.及()
.logout()
.logoutUrl(“/user/logout”)
.logoutSuccessUrl(“/user/login?logout”).permitAll()
.logoutSuccessHandler(logoutSuccessHandler())
.及()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
}
想知道原因吗?
以前的配置
您的资源/user/login
是受限资源,只有在authenticated=true
和hasRole=“User”
在注销成功处理程序中,您正在使会话无效并重定向到
/user/login?注销
页面,但/user/login
是受限资源,因此过滤器安全Interceptor
将重定向到配置的登录页面(.loginPage(“/user/login”)
。因此,您将不会收到传入查询字符串的任何参数
因此,解决方案将始终使登录页面成为不受限制的资源。
public class UserCustomLogoutSuccessHandler extends
SimpleUrlLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
this.setDefaultTargetUrl("/user/login?logout");
super.onLogoutSuccess(request, response, authentication);
}
}