gpt4 book ai didi

java - Redirect from CustomLogoutHandler to 'login?logout' 被重定向到 'login'

转载 作者:行者123 更新时间:2023-11-30 10:00:06 30 4
gpt4 key购买 nike

我有两个安全区域,我为其提供基于表单的登录。

  • /用户
  • /admin

以下按预期工作:

  • 访问 protected 资源时重定向到登录页面
  • 当凭据为假时使用 ?error 参数重定向到登录页面
  • 根据定义的角色阻止对 protected 资源的访问

以下不起作用:

  • 注销后重定向到登录页面

注销时,我重定向到 /user/login?logout 以显示消息“您已注销”,表明注销成功。但是,这不起作用,而是将重定向到 /user/login?logout 重定向到 /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());

}
}

这是我的 CustomLogoutHandler:

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

在 DevTools 中,我可以清楚地看到,每当我尝试访问 URL /user/login?logout 时,GET-Request 结果为 302,然后为 发出新请求用户/登录。当我手动编辑浏览器 URL 行中的 URL 或从应用程序通过 FORM-Post 触发注销时,就会发生这种情况。

当我删除 logoutSuccessHandler 时,我可以在浏览器中手动输入 URL 并在应用程序中从我的 FORM-Post 触发它。

我也试过:

  • 将用于登录和注销的 URL 移出路径 /user -> 破坏了登录
  • 使用 Order(1) 定义第三种配置,明确允许在登录和注销页面上使用 GET 和 POST -> 这也破坏了登录
  • 不使用 .antMatcher 而是使用 .antMatchers,但是我认为我将无法拥有两个不同的 FormLogins

最佳答案

我知道这类问题会打上一个大大的问号,让我挠头思考为什么

解决方案是。

@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.antMatcher("/user/**").authorizeRequests()
.antMatchers("/user/login").permitAll() //solution
.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());
}

想知道为什么吗?

来自之前的配置

您的资源 /user/login 是受限资源,只有在
authenticated = truehasRole = "User"
在您的注销成功处理程序中,您正在使 session 无效并重定向到 /user/login?logout 页面,但是 /user/login 是受限资源,因此 FilterSecurityInterceptor 将重定向到配置的登录页面(.loginPage("/user/login")。因此您不会收到任何传入查询字符串的参数。

因此,解决方案总是将登录页面作为不受限制的资源。

关于java - Redirect from CustomLogoutHandler to 'login?logout' 被重定向到 'login',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58338235/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com