1.解决 SpringBoot-SpringSecurity 使用中 Redis 共享 Session 时,服务重启后,RedisSession 与 内存 Session 不一致问题。
WebSecurityConfigurerAdapter 子类 :
@Configuration
public class CustomSecurityConfig extends WebSecurityConfigurerAdapter {
private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
@Autowired
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
private FindByIndexNameSessionRepository findByIndexNameSessionRepository;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.roles("admin")
.password("$2a$10$EvmYfZ9xWFwmbDdMuVFqQOLuAu6q.r/c.hFXEHAh25S.bXlz.7jXS")
.and()
.withUser("devops")
.roles("user")
.password("$2a$10$xwCcTjg5WQnfq0rmOC8vuuNvxzEvdhYP6V9m4/8alHi2jMMkMAXVe");
}
@Bean
PasswordEncoder passwordEncoder() {
//return NoOpPasswordEncoder.getInstance();
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return encoder.encode(charSequence.toString());
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return encoder.matches(charSequence, s);
}
};
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
web.ignoring().mvcMatchers("/test/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http);
http.authorizeRequests()//开启登录配置
.antMatchers("/hello").hasRole("admin")//表示访问 /hello 这个接口,需要具备 admin 这个角色
.anyRequest().authenticated()//表示剩余的其他接口,登录之后就能访问
.and()
.formLogin().defaultSuccessUrl("/")
.and()
.logout()
.and()
.httpBasic()
.and()
.csrf().disable()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(false)
.sessionRegistry(sessionRegistry());
}
@Bean
public SpringSessionBackedSessionRegistry sessionRegistry() {
return new SpringSessionBackedSessionRegistry(findByIndexNameSessionRepository);
}
}
2.剔除在线用户,Controller 层实现。
@Autowired
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
private FindByIndexNameSessionRepository findByIndexNameSessionRepository;
@PreAuthorize("hasRole('admin')") //@EnableGlobalMethodSecurity(prePostEnabled=true)
@GetMapping("/logout/{userName}")
@ResponseBody
public String logout(@PathVariable String userName) {
Map<String, Session> byPrincipalName = findByIndexNameSessionRepository.findByPrincipalName(userName);
Set<String> sessonIdSet = byPrincipalName.keySet();
for (String sessonId : sessonIdSet) {
findByIndexNameSessionRepository.deleteById(sessonId);
}
return "ok";
}
注:SpringBoot 版本:2.5.2