- 浏览: 189395 次
- 性别:
- 来自: 南京
文章分类
最新评论
前言:
Remember-me认证方式指的是能在不同的会话间记录用户认证信息的功能。通常通过向客户端发送一个cookie,在以后用户访问网站时通过这个cookie中的信息来自动登录实现。spring security 已经为我们提供了必要的hooks实现这个功能,并提供了两种具体的实现。一种是cookie中token包含了所有认证所需信息,并通过hash算法来保护这个token,另一种通过数据库或者其他持久化机制来存储生成的token。两种实现方式都需要我们提供一个UserDetailsService。如果我们采取的认证方式没有用到UserDetailsService(如LDAP),除非我们在application context中创建一个UserDetailsService来适配,否则Remember-me功能将不能正确执行。
一、remember-me功能实现逻辑
二.基于简单hash的方式
1.这种方式MD5算法实现remember-me功能,核心思想是在用户认证成功后通过下面的算法生成一个token,token中包含用户名和密码等信息,并将此token缓存到客户端的cookie中。
通过上面的算法得到的token,如果在有效期内,并且用户名和密码没有变化的情况下就可以实现自动认证功能,过程如下
2.采用这种方式有一个潜在安全问题,就是一个缓存下来的token可以被任何用户使用,一直到设定的时效过期,并且在这个过程中用户本人并不能察觉到,在摘要认证中也有同样的问题。如果非法的使用者做了某种操作使用户发现remember-me token被泄漏了,用户可以通过修改密码来使所有缓存的token失效。另一个安全问题是我们需要把username也放到cookie中,也会造成一定的信息泄露。如果安全级别比较高,应该采用下面讲的第二种方式,将token存入到库中,否则应该禁止使用remember-me功能。
3.在spring boot中通过下面的配置启用
spring boot会自动给我们装配一个UserDetailsService,如果我们系统中有超过一个的UserDetailsService,我们必须明确的通过rememberMe().userDetailsService(userDetailsService)方法指定一个。
具体例子可参考spring-security(五)java config-sample之rememberme
4.基于hash的remember-me功能策略类是TokenBasedRememberMeServices
这个类还实现了LogoutHandler接口,当在用户logout时要删除token的需求时,可以将这个类配置到LogoutFilter中。
三、采用持久化机制实现
1.这种实现方式的核心算法是首次登录成功后生成一个PersistentRememberMeToken对象,包含如下信息
接着将生成的PersistentRememberMeToken存入到PersistentTokenRepository中,spring默认给我们提供了
[list]两种实现InMemoryTokenRepositoryImpl和JdbcTokenRepositoryImpl,其中InMemoryTokenRepositoryImpl中就是一个Map<String, PersistentRememberMeToken> seriesTokens,key值对应的就是series
JdbcTokenRepositoryImpl会将我们的token持久化到数据库中,默认的建表语句如下
主键是series
[/list]
然后将series、tokenValue缓存到客户端的cookie中
2.当用户session过期后用户重新访问系统时通过以下过程实现认证
3.具体实现类PersistentTokenBasedRememberMeServices,这个类也实现了LogoutHandler,当用户执行logout时,这个类会自动将当前用户的所有PersistentRememberMeToken删除
4.由上面的分析可知采用这种形式即可以避免将用户名称返回客户端,并且只要用户点击了logout,就可以将所有缓存的PersistentRememberMeToken都删除,可以避免因为不小心忘记登出而让其他的非法使用者一直利用自己的账号信息的问题。
四、在RememberMeAuthenticationProvider中进行认证时,需要判断key值是否相同,那这个key是怎么设置的,如何和RememberMeServices中的key保持一致呢?
在spring boot的Java config中,我们通过http.rememberme()来配置remember-me功能,下面来看下这个函数
具体的配置在RememberMeConfigurer中
可以看出,在这个配置类里面给我们创建了RememberMeServices和RememberMeAuthenticationProvider并且用的是同一个key值
Remember-me认证方式指的是能在不同的会话间记录用户认证信息的功能。通常通过向客户端发送一个cookie,在以后用户访问网站时通过这个cookie中的信息来自动登录实现。spring security 已经为我们提供了必要的hooks实现这个功能,并提供了两种具体的实现。一种是cookie中token包含了所有认证所需信息,并通过hash算法来保护这个token,另一种通过数据库或者其他持久化机制来存储生成的token。两种实现方式都需要我们提供一个UserDetailsService。如果我们采取的认证方式没有用到UserDetailsService(如LDAP),除非我们在application context中创建一个UserDetailsService来适配,否则Remember-me功能将不能正确执行。
一、remember-me功能实现逻辑
- 用户首次登录认证成功后,调用RememberMeServices的loginSuccess方法,将用户凭证信息序列化成token,以某种形式存储起来
- 用户session失效后再次访问系统,会调用RememberMeServices的autoLogin方法,根据客户端传过来的cookie信息,获取之前存储的token信息,并解析出认证需要的信息,完成自动认证
二.基于简单hash的方式
1.这种方式MD5算法实现remember-me功能,核心思想是在用户认证成功后通过下面的算法生成一个token,token中包含用户名和密码等信息,并将此token缓存到客户端的cookie中。
base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key)) username: 用户名 password: 密码 expirationTime: 过期日期,单位是毫秒,默认两周 key: 一个私有的key值,用来保护token,防止被伪造
通过上面的算法得到的token,如果在有效期内,并且用户名和密码没有变化的情况下就可以实现自动认证功能,过程如下
- 服务器接收到token后,利用base64对token值解码,获取到username、expirationTime、以及一个特定的hash串,hash串中包含了用户的密码信息(因为hash算法的不可逆性,这个密码是不能恢复出来的)
- 服务器判断expirationTime有没有过期,如果过期就抛出异常不再进行自动认证
- 服务器根据解析出来的username,调用UserDetailsService.loadUserByUsername方法获取用户对应的密码、权限等信息
- 将username、获取出来的password、expirationTime、key值经过相同的hash算法得到一个hash串
- 判断上一步计算出来的hash串和我们从cookie中解析出来的hash串是否一致,一致的话生成一个RememberMeAuthenticationToken,不一致抛出异常不在进行自动认证
- 接着调用authenticationManager.authenticate,传入上一步生成的token
- authenticationManager中最终会调用到RememberMeAuthenticationProvider的authenticate方法,因为在之前我们已经判断过现在的cookie中存储的认证信息对应的用户名和密码是正确的,所以这个方法只是简单的判断下RememberMeAuthenticationToken中的key值是否和RememberMeAuthenticationProvider中设定的key一致就可以了
- 如果key值一致则认证成功,并将认证后的Authentication存入SecurityContextHolder供鉴权使用
2.采用这种方式有一个潜在安全问题,就是一个缓存下来的token可以被任何用户使用,一直到设定的时效过期,并且在这个过程中用户本人并不能察觉到,在摘要认证中也有同样的问题。如果非法的使用者做了某种操作使用户发现remember-me token被泄漏了,用户可以通过修改密码来使所有缓存的token失效。另一个安全问题是我们需要把username也放到cookie中,也会造成一定的信息泄露。如果安全级别比较高,应该采用下面讲的第二种方式,将token存入到库中,否则应该禁止使用remember-me功能。
3.在spring boot中通过下面的配置启用
http .csrf() .disable() .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.html") .permitAll() .and() .rememberMe() .and() .logout() .logoutSuccessUrl("/login.html");
spring boot会自动给我们装配一个UserDetailsService,如果我们系统中有超过一个的UserDetailsService,我们必须明确的通过rememberMe().userDetailsService(userDetailsService)方法指定一个。
具体例子可参考spring-security(五)java config-sample之rememberme
4.基于hash的remember-me功能策略类是TokenBasedRememberMeServices
这个类还实现了LogoutHandler接口,当在用户logout时要删除token的需求时,可以将这个类配置到LogoutFilter中。
三、采用持久化机制实现
1.这种实现方式的核心算法是首次登录成功后生成一个PersistentRememberMeToken对象,包含如下信息
- username 用户名
- series 一个16位的随机数,之后会把这个数写入客户端的cookie中,通过这个值能唯一确定一条token记录
- tokenValue 一个16位的随机数,代表着当前的token值
- date 当前系统时间,即用户访问系统认证成功的时间
接着将生成的PersistentRememberMeToken存入到PersistentTokenRepository中,spring默认给我们提供了
[list]
create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)
主键是series
[/list]
然后将series、tokenValue缓存到客户端的cookie中
2.当用户session过期后用户重新访问系统时通过以下过程实现认证
- 从cookie中解析出series、tokenValue
- 根据series从PersistentTokenRepository中获取到PersistentRememberMeToken
- 用获取到的PersistentRememberMeToken中的tokenValue和cookie中获取到的tokenValue进行比较看是否匹配,不匹配的话,很有可能是token泄露了,此时spring会将此用户对应的所有token都清除掉,并抛出异常自动认证结束
- 根据PersistentRememberMeToken中的last_used时间+设置的token有效期和当前系统时间相比判读是否过期,过期抛出异常自动认证结束
- 利用原来的token的series,并重新生成一个tokenValue,再构造一个PersistentRememberMeToken,利用series为key将原来的更新掉,并将last_used更新成当前系统时间
- 再将series、和新生成的tokenValue缓存到客户端的cookie中
- 接着调用UserDetailsService.loadUserByUsername方法获取用户对应的密码、权限等信息
- 用获取到的user信息创建一个RememberMeAuthenticationToken
- 接着调用authenticationManager.authenticate,传入上一步生成的token
- authenticationManager中最终会调用到RememberMeAuthenticationProvider的authenticate方法,因为在之前我们已经判断过现在的cookie中存储的认证信息对应的用户名和密码是正确的,所以这个方法只是简单的判断下RememberMeAuthenticationToken中的key值是否和RememberMeAuthenticationProvider中设定的key一致就可以了
- 如果key值一致则认证成功,并将认证后的Authentication存入SecurityContextHolder供鉴权使用
3.具体实现类PersistentTokenBasedRememberMeServices,这个类也实现了LogoutHandler,当用户执行logout时,这个类会自动将当前用户的所有PersistentRememberMeToken删除
@Override public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { super.logout(request, response, authentication); if (authentication != null) { tokenRepository.removeUserTokens(authentication.getName()); } }
4.由上面的分析可知采用这种形式即可以避免将用户名称返回客户端,并且只要用户点击了logout,就可以将所有缓存的PersistentRememberMeToken都删除,可以避免因为不小心忘记登出而让其他的非法使用者一直利用自己的账号信息的问题。
四、在RememberMeAuthenticationProvider中进行认证时,需要判断key值是否相同,那这个key是怎么设置的,如何和RememberMeServices中的key保持一致呢?
在spring boot的Java config中,我们通过http.rememberme()来配置remember-me功能,下面来看下这个函数
public RememberMeConfigurer<HttpSecurity> rememberMe() throws Exception { return getOrApply(new RememberMeConfigurer<HttpSecurity>()); }
具体的配置在RememberMeConfigurer中
public void init(H http) throws Exception { validateInput(); String key = getKey();----------------------------------------------------(1) RememberMeServices rememberMeServices = getRememberMeServices(http, key);-(2) http.setSharedObject(RememberMeServices.class, rememberMeServices); LogoutConfigurer<H> logoutConfigurer = http.getConfigurer(LogoutConfigurer.class); if (logoutConfigurer != null && this.logoutHandler != null) { logoutConfigurer.addLogoutHandler(this.logoutHandler); } RememberMeAuthenticationProvider authenticationProvider = new RememberMeAuthenticationProvider(key);----------------------------------------(3) authenticationProvider = postProcess(authenticationProvider); http.authenticationProvider(authenticationProvider); initDefaultLoginFilter(http); }
可以看出,在这个配置类里面给我们创建了RememberMeServices和RememberMeAuthenticationProvider并且用的是同一个key值
发表评论
-
spring-security(二十五)鉴权
2018-03-27 11:21 1550前言 本文将详细探讨spring security中的鉴权 ... -
test
2018-03-19 21:20 0什么是服务发现 ... -
spring-security(二十四)CSRF
2018-03-24 09:54 81291.什么是CSRF攻击 下面我们以一个具体的例子来说明这种常见 ... -
spring-security(二十二)基本认证和摘要认证
2018-03-06 16:58 1763前言: 在web应用中,非常流行以基本认证和摘要认证作为备 ... -
spring-security(二十一)核心Filter-UsernamePasswordAuthenticationFilter
2018-03-04 11:05 1199一、UsernamePasswordAuthenticatio ... -
spring-security(二十)核心Filter-SecurityContextPersistenceFilter
2018-02-28 21:40 1066一、SecurityContextPersistenceFil ... -
spring-security(十九)核心Filter-ExceptionTranslationFilter
2018-02-27 16:31 1993前言: 在spring的安全 ... -
spring-security(十八)核心Filter-FilterSecurityInterceptor
2018-02-25 10:59 2266前言: 当用spring secur ... -
spring-security(二十六)整合CAS 实现SSO
2018-04-05 18:09 12081.cas 认证流程 2.spring security ... -
spring-security(十七)Filter顺序及简介
2018-02-22 18:16 7801前言: spring security在 ... -
spring-security(十六)Filter配置原理
2018-02-21 15:18 2340前言: spring security最常见的应用场景还是 ... -
spring-security(十五) Password编码
2018-02-19 15:15 1181前言: 在实际应用中 ... -
spring-security(十四)UserDetailsService
2018-02-19 11:35 1436前言: 作为spring security的核心类,大多数 ... -
spring-security(十三)核心服务类
2018-02-18 16:46 1369前言: 在之前的篇章中我们已经讲述了spring secu ... -
spring-security(十二)鉴权方式概述
2018-02-18 10:42 2494前言: 本文主要讲述在spring security鉴权的 ... -
spring-security(十一)Web应用认证过程
2018-02-17 17:17 1210前言: 本文将探讨当 ... -
spring-security(十)基本认证过程
2018-02-17 13:55 2058前言: 在spring security中认证具体指的是什 ... -
spring-security(九)-核心组件
2018-02-17 10:46 827前言: 本文主要介绍在spring security中的几 ... -
spring-security(八)java config-sample之cas client
2018-02-16 11:26 2031前言: SSO英文全称Single Sign On,单点登 ... -
spring-security(七)java config-sample之concurrency
2018-02-15 10:51 633前言: 在实际应用中,我们可能会限制一个用户同时登录同一个 ...
相关推荐
2.3.1. Remember-Me 认证 2.3.2. 添加HTTP/HTTPS 信道安全 2.3.3. 会话管理 2.3.3.1. 检测超时 2.3.3.2. 同步会话控制 2.3.3.3. 防止Session 固定攻击 2.3.4. 对OpenID 的支持 2.3.4.1. 属性交换 ...
9.3.1什么是Spring Security中的认证? 78 9.3.2直接设置SecurityContextHolder内容 80 9.4 Web应用程序中的身份验证 81 9.4.1 ExceptionTranslationFilter 82 9.4.2 AuthenticationEntryPoint 82 9.4.3认证机制 82 ...
2.3.1. Remember-Me认证 2.3.2. 添加HTTP/HTTPS信道安全 2.3.3. 会话管理 2.3.3.1. 检测超时 2.3.3.2. 同步会话控制 2.3.3.3. 防止Session固定攻击 2.3.4. 对OpenID的支持 2.3.4.1. 属性交换 2.3.5....
该资源是基本Spring Security实战七篇文档中组织的源码,详情...ssecurity-rememberMe项目是Spring Security实战(七)的源码; 本人开发工具是IDEA,每个项目中的代码均可以运行并测试。Eclipse也是一样可以运行的。
进阶-使用Spring Security3.2搭建LDAP认证授权和Remember-me
2.3.1. Remember-Me认证 2.3.2. 添加HTTP/HTTPS信道安全 2.3.3. 会话管理 2.3.3.1. 检测超时 2.3.3.2. 同步会话控制 2.3.3.3. 防止Session固定攻击 2.3.4. 对OpenID的支持 2.3.4.1. 属性交换 2.3.5. 添加你...
基于用户,角色,权限的spring_security完整项目 博文链接:https://abc08010051.iteye.com/blog/1995648
主要介绍了Spring Security 构建rest服务实现rememberme 记住我功能,需要的朋友可以参考下
spring boot +spring security +thymeleaf 实现简单权限+remember-me功能
主要给大家介绍了关于Spring Security学习之rememberMe自动登录的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
用户登录(使用RememberMe) 使用简单(单个)角色 方法级别的安全性(@PreAuthorize) XSS和CSRF测试 下一个 用户认证管理 参考 快速开始 预装 JDK 1.8(或Java 10) Maven的3.5 吉特 跑步 git clone ...
摘要认证的密码加密通用密码加密Remember-Me(记住我)认证:基于散列的令牌方法Remember-Me(记住我)认证:基于持久化的令牌方法OAuth 2.
主要介绍了Spring Security Remember me使用及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
springsecurity3.0.5简单例子 当用firefox访问时产生的临时cookie,在下次访问中还存在的话,获取的session还是原来的session(user验证信息不变),如果把那个临时cookie删除的话,则springsecuriyt生成新的session...
主要介绍了SpringSecurity rememberme功能实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
NULL 博文链接:https://lengyun3566.iteye.com/blog/1141347
Spring Boot Shiro Remember Me Spring Boot Shiro权限控制 Spring Boot Shiro Redis Spring Boot Shiro Ehcache Spring Boot Thymeleaf中使用Shiro标签 Spring Boot Shiro在线会话管理 Spring Boot Shiro整合JWT 三...
Spring Security 学习 使用Spring Boot 2.0 为框架,学习Spring Security。 已完成功能: ...实现RememberMe功能。 使用Redis记录Spring Session。 简单完成各种情况下从Ajax请求跳转到页面的处理。
实现免登陆验证(Remember-Me验证) 提供一系列标签库进行页面元素的安全控制 方法安全 通过AOP模式实现安全代理 Web安全与方法安全均可以使用表达式语言定义访问规则 5、配置SS 配置Web.xml,应用安全过滤器 配置...
适合的版本才是最好的,最新的可能有些不稳定; 之前遇到过 druid 启动器版本的问题; 事实证明追求最新版本会有些许问题,就像majora等linux一样; 稳定才是我们需要的