会话管理
Spring Security
认证成功之后会保存会话信息,将认证信息保存在Session
,发送JSESSIONID
数据给浏览器保存在Cookie
中,浏览器访问的时候携带Cookie
,服务器根据JSESSIONID
找到Session
。
在Spring Security
中会话创建策略有下面几种:
设置超时:
// 会话
http.sessionManagement(session -> {
session
// 创建会话策略
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
// 会话超时访问url
.invalidSessionUrl("/login")
// 一个账号最大登录设备数量
.maximumSessions(1)
// 当一个账号有多个用户登录时提示
.expiredSessionStrategy(new SessionInformationExpiredStrategyImpl());
});
public class SessionInformationExpiredStrategyImpl implements SessionInformationExpiredStrategy {
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
Map<String,Object> map = new HashMap<>();
map.put("code", "-1");
map.put("message", "登录失败");
map.put("data", "当前账号已在其它设备登录");
String json = new ObjectMapper().writeValueAsString(map);
HttpServletResponse response = event.getResponse();
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(json);
}
}
密码编辑器
密码编辑器接口PasswordEncoder
默认Spring Security
提供一些实现类:
在5.0之后的默认密码编辑器是DelegatingPasswordEncoder
,可以根据前缀匹配不同的密码编辑器,比如下面这样:
格式:{算法名}加密后密码
{bcrypt}$2a$10$c2jp7iXCNwjEgtA9d2zQde01HpKIUpihEKo4Z.uasrvt.cTxWjFgy
在配置文件中我们可以指定某一种密码编辑器:
/**
* 密码器
* @return BCrypt密码器
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
Remember-me(记住我)
Remember-me(记住我)或persistent-login认证是指网站能够在两次会话之间记住委托人的身份。这通常是通过向浏览器发送一个cookie来实现的,在未来的会话中可以检测到cookie,并导致自动登录的发生。Spring Security为这些操作提供了必要的钩子,并有两个具体的“记住我”的实现。一个使用散列法来保护基于cookie的令牌的安全性,另一个使用数据库或其他持久性存储机制来存储生成的令牌。
请注意,这两种实现都需要一个 UserDetailsService
。如果你使用一个不使用 UserDetailsService
的认证 provider(例如,LDAP provider),除非你在你的应用程序上下文中也有一个 UserDetailsService
Bean,否则它不会工作。
在Spring Security
中开启记住我,只需要在配置文件中开启配置即可。
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 认证相关
http.authorizeRequests(authorize ->
authorize
// /login.html请求不需要验证
.requestMatchers(new AntPathRequestMatcher("/login")
,new AntPathRequestMatcher("/logout")).permitAll()
.anyRequest()
.authenticated()
);
http.formLogin(Customizer.withDefaults());
http.rememberMe();
}
这里我们使用默认的登录表单,效果如下:
使用F12
查看登录参数,会发现多了一个remember-me
在登录之后关闭浏览器再次访问: