springsecurity 源码解读 之 RememberMeAuthenticationFilter
RememberMeAuthenticationFilter 的作用很简单,就是用于当session 过期后,系统自动通过读取cookie 让系统自动登录。
我们来看看Springsecurity的过滤器链条。

我们发现这个 RememberMeAuthenticationFilter 在 匿名构造器之前,这个是为什么呢?
还是从源码来分析:
if (SecurityContextHolder.getContext().getAuthentication() == null) {
Authentication rememberMeAuth = rememberMeServices.autoLogin(request, response);
if (rememberMeAuth != null) {
代码中有这样的一行,当SecurityContext 中 Authentication 为空时,他就会调用 rememberMeServices 自动登录。
因此刚刚的问题也就好解释了,因为如果RememberMeAuthenticationFilter 没有实现自动登录,那么他的Authentication 还是为空,
这是可以创建一个匿名登录,如果先创建了匿名登录,那么这个 RememberMeAuthenticationFilter 的判断就不会为null,过滤器将失效。
我们看看rememberMeServices 的autoLogin 登录
我们贴出实现的代码:
public final Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
String rememberMeCookie = extractRememberMeCookie(request);
if (rememberMeCookie == null) {
return null;
}
logger.debug("Remember-me cookie detected");
if (rememberMeCookie.length() == 0) {
logger.debug("Cookie was empty");
cancelCookie(request, response);
return null;
}
UserDetails user = null;
try {
String[] cookieTokens = decodeCookie(rememberMeCookie);
user = processAutoLoginCookie(cookieTokens, request, response);
userDetailsChecker.check(user);
logger.debug("Remember-me cookie accepted");
return createSuccessfulAuthentication(request, user);
} catch (CookieTheftException cte) {
cancelCookie(request, response);
throw cte;
} catch (UsernameNotFoundException noUser) {
logger.debug("Remember-me login was valid but corresponding user not found.", noUser);
} catch (InvalidCookieException invalidCookie) {
logger.debug("Invalid remember-me cookie: " + invalidCookie.getMessage());
} catch (AccountStatusException statusInvalid) {
logger.debug("Invalid UserDetails: " + statusInvalid.getMessage());
} catch (RememberMeAuthenticationException e) {
logger.debug(e.getMessage());
}
cancelCookie(request, response);
return null;
}
extractRememberMeCookie这个方法判断 SPRING_SECURITY_REMEMBER_ME_COOKIE 这样的cookie,如果没有就直接返回了null。
processAutoLoginCookie:这个是处理cookie 并从cookie加载用户。 默认springsecurity 使用类 TokenBasedRememberMeServices 来解析 cookie。 实现代码如下:
protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request,
HttpServletResponse response) { if (cookieTokens.length != 3) {
throw new InvalidCookieException("Cookie token did not contain 3" +
" tokens, but contained '" + Arrays.asList(cookieTokens) + "'");
} long tokenExpiryTime; try {
tokenExpiryTime = new Long(cookieTokens[1]).longValue();
}
catch (NumberFormatException nfe) {
throw new InvalidCookieException("Cookie token[1] did not contain a valid number (contained '" +
cookieTokens[1] + "')");
} if (isTokenExpired(tokenExpiryTime)) {
throw new InvalidCookieException("Cookie token[1] has expired (expired on '"
+ new Date(tokenExpiryTime) + "'; current time is '" + new Date() + "')");
} // Check the user exists.
// Defer lookup until after expiry time checked, to possibly avoid expensive database call. UserDetails userDetails = getUserDetailsService().loadUserByUsername(cookieTokens[0]); // Check signature of token matches remaining details.
// Must do this after user lookup, as we need the DAO-derived password.
// If efficiency was a major issue, just add in a UserCache implementation,
// but recall that this method is usually only called once per HttpSession - if the token is valid,
// it will cause SecurityContextHolder population, whilst if invalid, will cause the cookie to be cancelled.
String expectedTokenSignature = makeTokenSignature(tokenExpiryTime, userDetails.getUsername(),
userDetails.getPassword()); if (!equals(expectedTokenSignature,cookieTokens[2])) {
throw new InvalidCookieException("Cookie token[2] contained signature '" + cookieTokens[2]
+ "' but expected '" + expectedTokenSignature + "'");
} return userDetails;
}
protected String makeTokenSignature(long tokenExpiryTime, String username, String password) {
String data = username + ":" + tokenExpiryTime + ":" + password + ":" + getKey();
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("No MD5 algorithm available!");
}
return new String(Hex.encode(digest.digest(data.getBytes())));
}
这个代码就是加载用户,并验证cookie 是否有效。
因此我们在写入cookie 时,产生的cookie 过程如下:
String enPassword=EncryptUtil.hexToBase64(password);
long tokenValiditySeconds = 1209600; // 14 days
long tokenExpiryTime = System.currentTimeMillis() + (tokenValiditySeconds * 1000);
String signatureValue = makeTokenSignature(tokenExpiryTime,username,enPassword);
String tokenValue = username + ":" + tokenExpiryTime + ":" + signatureValue;
String tokenValueBase64 = new String(Base64.encodeBase64(tokenValue.getBytes()));
CookieUtil.addCookie(TokenBasedRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY,
tokenValueBase64,60 * 60 * 24 * 365, true, request, response);
springsecurity 源码解读 之 RememberMeAuthenticationFilter的更多相关文章
- springsecurity 源码解读之 SecurityContext
在springsecurity 中,我们一般可以通过代码: SecurityContext securityContext = SecurityContextHolder.getContext(); ...
- springsecurity 源码解读之 AnonymousAuthenticationFilter
我们知道springsecutity 是通过一系列的 过滤器实现的,我们可以看看这系列的过滤器到底长成什么样子呢? 一堆过滤器,这个过滤器的设计设计上是 责任链设计模式. 这里我们可以看到有一个 An ...
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SDWebImage源码解读 之 NSData+ImageContentType
第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- SDWebImage源码解读 之 SDWebImageCompat
第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
- SDWebImage源码解读之SDWebImageCache(下)
第六篇 前言 我们在SDWebImageCache(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...
随机推荐
- win7 升级Power Shell到4.0
因为用到EntityFrameworkCore ,想使用scaffold 来生成models. 提示我power Shell 2.0不支持命令,然后需要升级PS. PS win7 升级文件下载地址是 ...
- ipad忘记了锁屏密码,已经越狱了
ipad忘记了锁屏密码,已经越狱了, 已经需要连接itunes了...要是恢复的话,好像就不能越狱了耶... 我叫什么好咧 | 浏览 3330 次 问题暂时关闭 推荐于2016-07-23 11: ...
- CSRF 和 XSS 的区别
XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任 XSS: 跨站脚本攻击 原名为Cross Site Scriptin,为避免和网页层级样式表概念混淆, 另名为XSS ...
- Java基础第一天(标识符、变量)
一.标识符 Java对各种变量.类.方法命名时的字符序列. 凡自己可以起名字的地方都叫标识符. 标识符特点: 1.26个英文字母大小写,0~9,$,_ 组成. 2.数字不可以做开头. 3.不可以使用关 ...
- SpringCloud Hystrix熔断之线程池
服务熔断 雪崩效应:是一种因服务提供者的不可用导致服务调用者的不可用,并导致服务雪崩的过程. 服务熔断:当服务提供者无法调用时,会通过断路器向调用方直接返回一个错误响应,而不是长时间的等待,避免服务雪 ...
- FOB注意事项
1. FOB是我们作为贸易公司去联系物流公司将货送到码头,缴纳FOB cost 以后,海关安排码头的人送到船上. 2.在这之前,买方自己订船,然后发给卖方入货通知,卖方安排发货. 3.FOB cost ...
- 20175314 《Java程序设计》第九周学习总结
20175314 <Java程序设计>第九周学习总结 教材学习内容总结 根据课本的介绍下载了MySQL和Navicat for MySQL并成功对后者进行破解 MySQL客户端管理工具(如 ...
- docker image 详解
docker iamge docker 镜像: [root@localhost ~]# docker image --help Usage: docker image COMMAND 管理镜像 Com ...
- 20164319 刘蕴哲 Exp5 MSF基础应用
[实践内容] 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.1一个主动攻击实践(这里我做了两个:ms08_067[成功]和ms17_010[成功 ...
- zyupload四种不同的PHP上传demo
PHP结合zyupload多功能图片上传实例,支持拖拽和裁剪.可以自定义高度和宽度,类型,远程上传地址等. zyupload上传基本配置 1 $("#zyupload").zyUp ...