SpringSecurity实战解析
Security入门笔记:Spring Security学习笔记
一、Security认证和原理
Spring Security
是一种基于Spring AOP
和Servlet Filter
的安全框架,其核心是一组过滤器链,实现 Web 请求和方法调用级别的用户鉴权和权限控制
1、认证基本流程
1.1 表单认证概述
Spring Security
提供了两种认证方式:HttpBasic 认证和 HttpForm 表单认证。HttpBasic 认证不需要我们编写登录页面,当浏览器请求 URL 需要认证才能访问时,页面会自动弹出一个登录窗口,要求用户输入用户名和密码进行认证。大多数情况下,我们还是通过编写登录页面进行 HttpForm 表单认证(现在默认是这个模式)
1.2 基本流程分析
Spring Security
采取过滤链实现认证与授权,只有当前过滤器通过,才能进入下一个过滤器
绿色部分是认证过滤器,需要我们自己配置,可以配置多个认证过滤器。认证过滤器可以使用Spring Security
提供的认证过滤器,也可以自定义过滤器(例如:验证码验证)。认证过滤器要在configure(HttpSecurity http)
方法中配置,没有配置不生效。下面会重点介绍以下三个过滤器:
UsernamePasswordAuthenticationFilter
过滤器:该过滤器会拦截前端提交的 POST 方式的登录表单请求,并进行身份认证ExceptionTranslationFilter
过滤器:该过滤器不需要我们配置,对于前端提交的请求会直接放行,捕获后续抛出的异常并进行处理(例如:权限访问限制)FilterSecurityInterceptor
过滤器:该过滤器是过滤器链的最后一个过滤器,根据资源权限配置来判断当前请求是否有权限访问对应的资源。如果访问受限会抛出相关异常,并由ExceptionTranslationFilter
过滤器进行捕获和处理
而认证流程是在UsernamePasswordAuthenticationFilter
过滤器中处理的,具体流程如下所示:
具体的源码相关可以查阅:https://www.cnblogs.com/zongmin/p/13783174.html
1.3 权限访问流程
上面介绍了认证流程,下面介绍权限访问流程,主要是对ExceptionTranslationFilter
过滤器和FilterSecurityInterceptor
过滤器进行介绍
ExceptionTranslationFilter
过滤器,该过滤器是用于处理异常的,不需要我们配置,对于前端提交的请求会直接放行,捕获后续抛出的异常并进行处理(例如:权限访问限制)FilterSecurityInterceptor
是过滤器链的最后一个过滤器,该过滤器是过滤器链的最后一个过滤器,根据资源权限配置来判断当前请求是否有权限访问对应的资源。如果访问受限会抛出相关异常,最终所抛出的异常会由前一个过滤器ExceptionTranslationFilter
进行捕获和处理
需要注意,Spring Security
的过滤器链是配置在 SpringMVC 的核心组件 DispatcherServlet 运行之前。也就是说,请求通过Spring Security
的所有过滤器,不意味着能够正常访问资源,该请求还需要通过 SpringMVC 的拦截器链
2、请求间共享认证信息
2.1 概述
一般认证成功后的用户信息是通过 Session 在多个请求之间共享,Spring Security
实现将已认证的用户信息对象 Authentication 与 Session 绑定
2.2 获取认证用户信息
由前文可知,封装了已认证用户信息对象 Authentication 的 SecurityContext 即存储在 SecurityContextHolder 中,也存储在 Session 中,所以这里有几种获取用户数据的方式
1 | // 从 SecurityContextHolder 获取认证用户信息对象 Authentication |
3、认证的几种方式
创建数据库表和数据
1 | DROP TABLE IF EXISTS `user`; |
创建 User 实体类,实现 UserDetails 接口
1 |
|
创建 CustomUserDetailsService 类,实现 UserDetailsService 接口
1 |
|
最后是自定义认证类(第三种方法选用)
1 | /** |
下面是配置文件,我们通过配置文件来选择不同的认证模式
1 | // 开启 MVC Security 安全配置 |
此处需要简单介绍下Spring Security
的授权方式,在Spring Security
中角色属于权限的一部分。对于角色ROLE_ADMIN
的授权方式有两种:hasRole("ADMIN")
和hasAuthority("ROLE_ADMIN")
,这两种方式是等价的。可能有人会疑惑,为什么在数据库中的角色名添加了ROLE_
前缀,而 hasRole() 配置时不需要加ROLE_
前缀。
hasRole() 在判断权限时会自动在角色名前添加ROLE_
前缀,所以配置时不需要添加ROLE_
前缀,同时这也要求 UserDetails 对象的权限集合中存储的角色名要有ROLE_
前缀。如果不希望匹配这个前缀,那么改为调用 hasAuthority() 方法即可
4、注解权限
4.1 概述
要开启Spring
方法级安全,在添加了@Configuration
注解的类上再添加@EnableGlobalMethodSecurity
注解即可
1 |
|
其中注解@EnableGlobalMethodSecurity
有几个方法:
prePostEnabled
****: 确定 前置注解[@PreAuthorize,@PostAuthorize,..]
是否启用(常用/重要)securedEnabled
****: 确定安全注解[@Secured]
是否启用jsr250Enabled
****: 确定JSR-250注解 [@RolesAllowed..]
是否启用
同一个应用程序中,可以启用多个类型的注解,但是只应该设置一个注解对于行为类的接口或者类
1 | public interface UserService { |
4.2 @Secured注解使用方式
@Secured
注解是用来定义业务方法的安全配置。在需要安全[角色/权限等]的方法上指定 @Secured,并且只有那些角色/权限的用户才可以调用该方法。@Secured
缺点(限制)就是不支持Spring EL
表达式。不够灵活。并且指定的角色必须以ROLE_
开头,不可省略。
在上面的例子中,updateUser
方法只能被拥有user
权限的用户调用。deleteUser
方法只能够被拥有admin
或者user
权限的用户调用。而如果想要指定"AND"
条件,即调用deleteUser
方法需同时拥有ADMIN
和DBA
角色的用户,@Secured
便不能实现。这时就需要使用prePostEnabled
提供的注解@PreAuthorize/@PostAuthorize
4.3 jsr250Enabled
@DenyAll
****: 拒绝所有访问@RolesAllowed({"USER", "ADMIN"})
****: 该方法只要具有"USER"
,"ADMIN"
任意一种权限就可以访问。这里可以省略前缀ROLE_
,实际的权限可能是ROLE_ADMIN
@PermitAll
****: 允许所有访问
1 | "test/allow") ( |
4.4 prePostEnabled 规范(重要)
该注解更适合方法级的安全,也支持Spring 表达式语言,提供了基于表达式的访问控制。参见常见内置表达式了解支持表达式的完整列表,上面只使用到了一个注解@PreAuthorize
,启用prePostEnabled
后,提供有四个注解:
@PreAuthorize
****: 进入方法之前验证授权。可以将登录用户的roles
参数传到方法中验证。
1 | // 只能user角色可以访问 |
@PostAuthorize
****: 该注解使用不多,在方法执行后再进行权限验证。 适合验证带有返回值的权限。Spring EL
提供 返回对象能够在表达式语言中获取返回的对象returnObject
。校验通过就返回,否则表示校验失败,将抛出AccessDeniedException
1 | // 查询到用户信息后,再验证用户名是否和登录用户名一致 |
@PreFilter
****: 对集合类型的参数执行过滤,移除结果为false
的元素
1 | // 指定过滤的参数,过滤偶数 |
@PostFilter
****: 对集合类型的返回值进行过滤,移除结果为false
的元素
1 | "filterObject.id%2==0") ( |
5、自定义认证成功/失败处理器
5.1 登录处理的方法介绍
此处先对http.formLogin()
返回值的主要方法进行说明,这些方法涉及用户登录的处理,具体如下:
loginPage(String loginPage)
:设置用户登录页面的访问路径,默认为 GET 请求的/login
。loginProcessingUrl(String loginProcessingUrl)
:设置登录表单提交的路径,默认为是 POST 请求的 loginPage() 设置的路径successForwardUrl(String forwordUrl)
:设置用户认证成功后转发的地址。successHandler(AuthenticationSuccessHandler successHandler)
:配置用户认证成功后的自定义处理器。defaultSuccessUrl(String defaultSuccessUrl)
:设置用户认证成功后重定向的地址。这里需要注意,该路径是用户直接访问登录页面认证成功后重定向的路径,如果是其他路径跳转到登录页面认证成功后会重定向到原始访问路径。可设置第二个参数为 true,使认证成功后始终重定向到该地址。failureForwrad(String forwardUrl)
:设置用户认证失败后转发的地址。failureHandler(AuthenticationFailureHandler authenticationFailureHandler)
:设置用户登录失败后的自定义错误处理器。failureUrl(String authenticationFailureUrl)
:设置用户登录失败后重定向的地址,指定的路径要能匿名访问,默认为loginPage() + ?error
。usernameParamter(String usernameParamter)
:设置登录表单中的用户名参数,默认为 username。passwordParamter(String passwordParamter)
:设置登录表单中的密码参数,默认为 password。
5.2 成功/失败处理器
因为需要用到Jackson,首先对其进行配置
1 | /** |
自定义失败处理器,这里有个判断原因是可以根据header的信息自定义选择如何跳转。真实环境可以根据自己实际情况进行选择
1 | /** |
自定义成功处理器
1 | /** |
最后配置config
1 | // 开启 MVC Security 安全配置 |
6、自定义权限处理器
无权访问自定义处理器
1 | /** |
未登录访问处理器
1 | /** |
最后将处理器配置到security
1 | // 自定义认证授权失败处理 |
二、Security验证码使用
1、原理概述
在用户登录时,一般通过表单的方式进行登录都会要求用户输入验证码,Spring Security
默认没有实现图形验证码的功能,所以需要我们自己实现
前文中实现的用户名、密码登录是在UsernamePasswordAuthenticationFilter
过滤器进行认证的,而图形验证码一般是在用户名、密码认证之前进行验证的,所以需要在UsernamePasswordAuthenticationFilter
过滤器之前添加一个自定义过滤器 ImageCodeValidateFilter
,用来校验用户输入的图形验证码是否正确。自定义过滤器继承 OncePerRequestFilter
类,该类是 Spring 提供的在一次请求中只会调用一次的 filter
自定义的过滤器 ImageCodeValidateFilter
首先会判断请求是否为 POST 方式
的登录表单提交请求,如果是就将其拦截进行图形验证码校验。如果验证错误,会抛出自定义异常类对象 ValidateCodeException
,该异常类需要继承 AuthenticationException
类。在自定义过滤器中,我们需要手动捕获自定义异常类对象,并将捕获到自定义异常类对象交给自定义失败处理器进行处理。
2、实战
2.1 验证码图片的生成
更改安全配置类 SpringSecurityConfig,设置访问/captcha/image
不需要任何权限,访问就会出现一个验证码小图片,其他几种验证码可以参考:Java验证码
首先创建验证码的存储类
1 | public class CheckCode implements Serializable { |
验证码生成类,图片直接返回,结果保存在此次session中
1 |
|
2.2 自定义验证码过滤器
创建自定义异常类 ValidateCodeException
1 | /** |
自定义图形验证码校验过滤器 ImageCodeValidateFilter
1 |
|
更改安全配置类 SpringSecurityConfig,将自定义过滤器添加过滤器链中
1 | // 开启 MVC Security 安全配置 |
3、session异常问题
可能会出现获取验证码的session和需要输入验证码不是同一个的情况,添加以下代码
1 |
|
三、Remember-Me 和注销
1、Remember-Me 功能概述
1.1 概述
在实际开发中,为了用户登录方便常常会启用记住我(Remember-Me)功能。如果用户登录时勾选了“记住我”选项,那么在一段有效时间内,会默认自动登录,免去再次输入用户名、密码等登录操作。该功能的实现机理是根据用户登录信息生成 Token 并保存在用户浏览器的 Cookie 中,当用户需要再次登录时,自动实现校验并建立登录态的一种机制。Spring Security
提供了两种 Remember-Me 的实现方式:
- 简单加密 Token:用散列算法加密用户必要的登录系信息并生成 Token 令牌。
- 持久化 Token:数据库等持久性数据存储机制用的持久化 Token 令牌。
1.2 基本原理
Remember-Me 功能的开启需要在configure(HttpSecurity http)
方法中通过http.rememberMe()
配置,该配置主要会在过滤器链中添加 RememberMeAuthenticationFilter 过滤器,通过该过滤器实现自动登录。该过滤器的位置在其它认证过滤器之后,其它认证过滤器没有进行认证处理时,该过滤器尝试工作:
注意: Remember-Me 功能是用于再次登录(认证)的,而不是再次请求。工作流程如下:
- 当用户成功登录认证后,浏览器中存在两个 Cookie,一个是 remember-me,另一个是 JSESSIONID。用户再次请求访问时,请求首先被
SecurityContextPersistenceFilter
过滤器拦截,该过滤器会根据 JSESSIONID 获取对应 Session 中存储的 SecurityContext 对象。如果获取到的 SecurityContext 对象中存储了认证用户信息对象 Authentiacaion,也就是说线程可以直接获得认证用户信息,那么后续的认证过滤器不需要对该请求进行拦截,remember-me 不起作用。 - 当 JSESSIONID 过期后,浏览器中只存在 remember-me 的 Cookie。用户再次请求访问时,由于请求没有携带 JSESSIONID,SecurityContextPersistenceFilter 过滤器无法获取 Session 中的 SecurityContext 对象,也就没法获得认证用户信息,后续需要进行登录认证。如果没有 remember-me 的 Cookie,浏览器会重定向到登录页面进行表单登录认证;但是 remember-me 的 Cookie 存在,RememberMeAuthenticationFilter 过滤器会将请求进行拦截,根据 remember-me 存储的 Token 值实现自动登录,并将成功登录后的认证用户信息对象 Authentiacaion 存储到 SecurityContext 中。当响应返回时,SecurityContextPersistenceFilter 过滤器会将 SecurityContext 存储在 Session 中,下次请求又通过 JSEESIONID 获取认证用户信息。
**总结:**remember-me 只有在 JSESSIONID 失效和前面的过滤器认证失败或者未进行认证时才发挥作用。此时,只要 remember-me 的 Cookie 不过期,我们就不需要填写登录表单,就能实现再次登录,并且 remember-me 自动登录成功之后,会生成新的 Token 替换旧的 Token,相应 Cookie 的 Max-Age 也会重置。
此处对http.rememberMe()
返回值的主要方法进行说明,这些方法涉及 Remember-Me 配置:
rememberMeParameter(String rememberMeParameter)
:指定在登录时“记住我”的 HTTP 参数,默认为remember-me
key(String key)
:“记住我”的 Token 中的标识字段,默认是一个随机的 UUID 值tokenValiditySeconds(int tokenValiditySeconds)
:“记住我” 的 Token 令牌有效期,单位为秒,即对应的 cookie 的 Max-Age 值,默认时间为 2 周userDetailsService(UserDetailsService userDetailsService)
:指定 Remember-Me 功能自动登录过程使用的 UserDetailsService 对象,默认使用 Spring 容器中的 UserDetailsService 对象tokenRepository(PersistentTokenRepository tokenRepository)
:指定 TokenRepository 对象,用来配置持久化 TokenalwaysRemember(boolean alwaysRemember)
:是否应该始终创建记住我的 Token,默认为 falseuseSecureCookie(boolean useSecureCookie)
:是否设置 Cookie 为安全,如果设置为 true,则必须通过 https 进行连接请求
2、Remember-Me实战
2.1 简单加密 Token(基本使用)
在用户选择“记住我”登录并成功认证后,Spring Security
将默认会生成一个名为 remember-me 的 Cookie 存储 Token 并发送给浏览器;用户注销登录后,该 Cookie 的 Max-Age 会被设置为 0,即删除该 Cookie。Token 值由下列方式组合而成:base64(username + ":" + expirationTime + ":" +md5Hex(username + ":" + expirationTime + ":" + password + ":" + key))
其中,username 代表用户名;password 代表用户密码;expirationTime 表示记住我的 Token 的失效日期,以毫秒为单位;key 表示防止修改 Token 的标识,默认是一个随机的 UUID 值,默认表单如下
1 |
|
修改安全配置类 SpringSecurityConfig
1 | // 开启 MVC Security 安全配置 |
2.2 持久化 Token(基本使用)
在用户选择“记住我”成功登录认证后,默认会生成一个名为 remember-me 的 Cookie 储存 Token,并发送给浏览器,具体实现流程如下:
- 用户选择“记住我”功能成功登录认证后,
Spring Security
会把用户名 username、序列号 series、令牌值 token 和最后一次使用自动登录的时间 last_used 作为一条 Token 记录存入数据库表中,同时生成一个名为 remember-me 的 Cookie 存储series:token
的 base64 编码,该编码为发送给浏览器的 Token - 当用户需要再次登录时,RememberMeAuthenticationFilter 过滤器首先会检查请求是否有 remember-me 的 Cookie。如果存在,则检查其 Token 值中的 series 和 token 字段是否与数据库中的相关记录一致,一致则通过验证,并且系统重新生成一个新 token 值替换数据库中对应记录的旧 token,该记录的序列号 series 保持不变,认证时间 last_used 更新,同时重新生成新的 Token(旧 series : 新 token)通过 Cookie 发送给浏览器,remember-me 的 Cookie 的 Max-Age 也因此重置
- 上述验证通过后,获取数据库中对应 Token 记录的 username 字段,调用 UserDetailsService 获取用户信息。之后进行登录认证,认证成功后将认证用户信息 Authentication 对象存入 SecurityContext
- 如果对应的 Cookie 值包含的 token 字段与数据库中对应 Token 记录的 token 字段不匹配,则有可能是用户的 Cookie 被盗用,这时将会删除数据库中与当前用户相关的所有 Token 记录,用户需要重新进行表单登录
- 如果对应的 Cookie 不存在,或者其值包含的 series 和 token 字段与数据库中的记录不匹配,则用户需要重新进行表单登录。如果用户退出登录,则删除数据库中对应的 Token 记录,并将相应的 Cookie 的 Max-Age 设置为 0
首先创建数据库表 persistent_logins,用于存储自动登录信息
1 | CREATE TABLE `persistent_logins` ( |
修改安全配置类 SpringSecurityConfig
,使用持久化 Token 方式
1 | // 开启 MVC Security 安全配置 |
3、注销登录
3.1 概述
注销登录需要在安全配置类的configure(HttpSecurity http)
里使用http.logout()
配置,该配置主要会在过滤器链中加入 LogoutFilter 过滤器,Spring Security
通过该过滤器实现注销登录功能。此处对http.logout()
返回值的主要方法进行介绍,这些方法设计注销登录的配置,具体如下:
logoutUrl(String outUrl)
:指定用户注销登录时请求访问的地址,默认为 POST 方式的/logout
logoutSuccessUrl(String logoutSuccessUrl)
:指定用户成功注销登录后的重定向地址,默认为/登录页面url?logout
logoutSuccessHandler(LogoutSuccessHandler logoutSuccessHandler)
:指定用户成功注销登录后使用的处理器deleteCookies(String ...cookieNamesToClear)
:指定用户注销登录后删除的 CookieinvalidateHttpSession(boolean invalidateHttpSession)
:指定用户注销登录后是否立即清除用户的 Session,默认为 trueclearAuthentication(boolean clearAuthentication)
:指定用户退出登录后是否立即清除用户认证信息对象 Authentication,默认为 trueaddLogoutHandler(LogoutHandler logoutHandler)
:指定用户注销登录时使用的处理器
需要注意,Spring Security
默认以 POST 方式请求访问/logout
注销登录,以 POST 方式请求的原因是为了防止 csrf(跨站请求伪造),如果想使用 GET 方式的请求,则需要关闭 csrf 防护。前面我们能以 GET 方式的请求注销登录,是因为我们在configure(HttpSecurity http)
方法中关闭了 csrf 防护
默认配置下,成功注销登录后会进行如下三个操作:
- 删除用户浏览器中的指定 Cookie
- 将用户浏览器中 remember-me 的 Cookie 删除,并清除用户在数据库中 remember-me 的 Token 记录
- 当前用户的 Session 删除,并清除当前 SecurityContext 中的用户认证信息对象 Authentication
- 通知用户浏览器重定向到
/登录页面url?logout
3.2 自定义登出处理器
1 | /** |
3.3 安全配置类
1 | // 开启 MVC Security 安全配置 |
四、Session 会话管理
1、Session管理配置
Session 会话管理需要在configure(HttpSecurity http)
方法中通过http.sessionManagement()
开启配置。此处对http.sessionManagement()
返回值的主要方法进行说明,这些方法涉及 Session 会话管理的配置,具体如下:
invalidSessionUrl(String invalidSessionUrl)
:指定会话失效时(请求携带无效的 JSESSIONID 访问系统)重定向的 URL,默认重定向到登录页面invalidSessionStrategy(InvalidSessionStrategy invalidSessionStrategy)
:指定会话失效时(请求携带无效的 JSESSIONID 访问系统)的处理策略maximumSessions(int maximumSessions)
:指定每个用户的最大并发会话数量,-1 表示不限数量maxSessionsPreventsLogin(boolean maxSessionsPreventsLogin)
:如果设置为 true,表示某用户达到最大会话并发数后,新会话请求会被拒绝登录;如果设置为 false,表示某用户达到最大会话并发数后,新会话请求访问时,其最老会话会在下一次请求时失效并根据 expiredUrl() 或者 expiredSessionStrategy() 方法配置的会话失效策略进行处理,默认值为 falseexpiredUrl(String expiredUrl)
:如果某用户达到最大会话并发数后,新会话请求访问时,其最老会话会在下一次请求时失效并重定向到 expiredUrlexpiredSessionStrategy(SessionInformationExpiredStrategy expiredSessionStrategy)
:如果某用户达到最大会话并发数后,新会话请求访问时,其最老会话会在下一次请求中失效并按照该策略处理请求。注意如果本方法与 expiredUrl() 同时使用,优先使用 expiredUrl() 的配置sessionRegistry(SessionRegistry sessionRegistry)
:设置所要使用的 sessionRegistry,默认配置的是 SessionRegistryImpl 实现类
2、Session 会话失效处理
当用户的 Session 会话失效(请求携带着无效的 JSESSIONID 访问系统)时,可以制定相关策略对会话失效的请求进行处理
2.1 Session 失效时间
Session 的失效时间配置是 SpringBoot 原生支持的,可以在 配置文件中直接配置
1 | server: |
2.2 invalidSessionUrl 方法
配置 Session 会话失效时重定向到/login/page
1 | // 开启 MVC Security 安全配置 |
2.3 invalidSessionStrategy 方法
自定义 Session 会话失效处理策略 CustomInvalidSessionStrategy
1 | /** |
修改安全配置类 SpringSecurityConfig,配置使用自定义的 Session 会话失效处理策略
1 | // 开启 MVC Security 安全配置 |
3、Session 会话并发控制
Session 会话并发控制可以限制用户的最大并发会话数量,例如:只允许一个用户在一个地方登陆,也就是说每个用户在系统中只能有一个 Session 会话。在使用 Session 会话并发控制时,最好保证自定义的 UserDetails 实现类重写了 equals() 和 hashCode() 方法
3.1 两种情况分析
- 同一个用户在第二个地方登录,则不允许他二次登录。这里设置
maximumSessions(1)
(单用户的 Session 最大并发会话数量)以及maxSessionsPreventsLogin(true)
(用户达到最大会话并发数后,新会话请求会被拒绝登录);上述配置限制了同一个用户的二次登陆,但是不建议使用该配置。因为用户一旦被盗号,那真正的用户后续就无法登录,只能通过联系管理员解决,所以如果只能一个用户 Session 登录,一般是新会话登录并将老会话踢下线。 - 如果同一个用户在第二个地方登录,则将第一个踢下线
首先自定义最老会话被踢时的处理策略 CustomSessionInformationExpiredStrategy
1 | /** |
修改安全配置类 SpringSecurityConfig
,配置最老会话被踢时的处理策略
1 | // 开启 MVC Security 安全配置 |
3.2 自定义统计session使用
1 |
|
4、 Redis 共享 Session
4.1 操作概述
首先导入依赖
1 | <!-- redis 依赖启动器 --> |
配置文件进行配置,同时Redis 存储 Session 默认的序列化方式为 JdkSerializationRedisSerializer
,所以存入 Session
的对象都要实现 Serializable
接口。因此,要保证前面代码中的验证码 CheckCode
类实现 Serializable
接口
1 | spring: |
最后启动访问即可
4.2 Redis数据解释
一共有三组数据:
-
第一组:string 结构,用于记录指定 Session 的剩余存活时间
spring:session:sessions:9bf69e21-ddd6-4c53-b7e6-976c047158cb
就是这个 string 结构的 key,后缀的字符串是 JSEESIONID 的 base64 解码值。其 value 为空,TTL 时间为对应 Session 的剩余存活时间 -
第二组:hash 结构,用于存储指定 Session 的数据
spring:session:sessions:9bf69e21-ddd6-4c53-b7e6-976c047158cb
就是这个 hash 结构的 key,后缀的字符串是 JSEESIONID 的 base64 解码值。hash 结构的 value 值本身就是一个 map 集合,分别为 lastAccessedTime(最后访问时间)、creationTime(创建时间)、maxInactiveInterval(最大存活时间)、sessionAttr:属性名
(Session 里存储的属性数据) -
第三组:set 结构,用于记录 Session 的过期时间
spring:session:expirations:1602144780000
就是这个 set 结构的 key,后缀的字符串是一个整分钟的时间戳,其 value 是一个 set 集合,存的是这个时间戳的分钟内要失效的 Session 对应的 JSEESIONID 的 base64 解码值
5、remember-me 失效解释(补充)
当配置了.maximumSessions(1).maxSessionsPreventsLogin(false)
要求只能一个用户 Session 登录时,我们在两个地方使用相同的账号,并且都勾选 remember-me 进行登录。最老会话的下一次请求不但会使老会话强制失效,还会使数据库中所有该用户的所有 remember-me 记录被删除。
五、补充与说明
我的config文件,仅供参考
1 | 4j |
另外Security5.7以后该方法就不推荐了,可以用新版的配置文件方式,更加简洁
1 |
|
如果想加token验证的话可以参考:Spring Security配置和Spring Security学习笔记
本次Spring Security的Demo代码地址:Security Demo项目
https://blog.csdn.net/2201_75856701/article/details/128676769
https://www.cnblogs.com/zongmin/tag/Spring Security/