好吧,我没有实现PersistentTokenBasedRememberMeServices
,因此我无法使用.logout(request, response, auth)
。但我使用 JdbcTokenRepositoryImpl
是为了使用 PersistentTokenRepository
来实现记住我功能。
注销 Controller :
@Controller
public class LogoutController {
@RequestMapping(value = {"/logout"}, method = RequestMethod.GET)
public String logout() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if(auth != null) {
SecurityContextHolder.getContext().setAuthentication(null);
}
return "redirect:/login?logout";
}
}
安全配置:
@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/playground").hasAnyRole("ROOT", "MODER", "USER")
.antMatchers("/users/**").hasAnyRole("ROOT", "MODER")
.and()
.formLogin().loginPage("/login").loginProcessingUrl("/login").failureHandler(customAuthenticationFailureHandler())
.and()
.rememberMe().rememberMeParameter("remember-me").tokenRepository(persistentTokenRepository()).userDetailsService(userDetailsService)
.and()
.logout().logoutUrl("/logout");
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setPasswordEncoder(passwordEncoder());
authProvider.setUserDetailsService(userDetailsService);
return authProvider;
}
@Bean
public AuthenticationFailureHandler customAuthenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
return jdbcTokenRepository;
}
当我使用 Remember-me 登录时,我无法注销。我想是因为记住我的功能。我应该向 LogoutController 添加什么才能进行正确的注销过程?
注意:问题是,如果我在注销时仅使用 POST 方法,那么它完全可以工作,但我想使用 GET 方法,因此我必须创建一个注销 Controller 来执行get方法。
最佳答案
尝试禁用 crsf (http.csrf().disable()
)。
spring安全注销过滤器的默认实现是:
if (http.getConfigurer(CsrfConfigurer.class) != null) {
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
}
else {
this.logoutRequestMatcher = new OrRequestMatcher(
new AntPathRequestMatcher(this.logoutUrl, "GET"),
new AntPathRequestMatcher(this.logoutUrl, "POST"),
new AntPathRequestMatcher(this.logoutUrl, "PUT"),
new AntPathRequestMatcher(this.logoutUrl, "DELETE")
);
}
如您所见,如果您的 Csrf 已启用(默认情况下,即使您覆盖 protected void configure(HttpSecurity http)
也会启用它),那么只有 POST
方法才有效,如果不是全部都工作的话。
顺便说一句:您确定您的请求到达了LogoutController
,因为我认为它使用标准的 Spring Security 注销机制? (要禁用它,请执行http.logout().disable()
,与默认情况下启用的csrf相同)
关于java - 如何在注销时使“记住我”失效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54105993/