Session :
特色:
1. 存在于服务端,所以它比较安全
2. session 的传输无限制
3. 当访问增大时,会加大服务器的压力、集群 sql 问题(redis 缓存解决)
应用场景:跟踪会话可用于 存储用户的信息、拦截器、购物车等
小提示:浏览器关闭 SessionID 会被清除,这才导致 session 失效
流程:
用户请求 ——> 验证用户信息成功则创建 session——> 响应会返回 sessionID
——> 用户请求携带 sessionID——> 进行验证是否存在
常用方法:
例: HttpServletRequest.setAttrirequest.getSession().setAttribute("user",data);
- setAttribute () // 设置 session
- getAttribute () // 获取 session
- removeAttribute () // 清除 session
- setMaxInactiveInterval(60*60*24)// 更改 Session 时长
- getMaxInactiveInterval // 获取 Session 时长
- Invalidate () // 销毁会话
Cokies:
特色:
- cokie 存在于客户端:,有安全隐患
- 有传输限制,最多为 4k
- 但是响应速度快
应用场景:
一般用于在客户端记住账号密码、自动登入
失效: 如果不设置时间则随着浏览器关闭而关闭,如果设置再浏览器关闭设定的时间内也可存在
Cookie 代码: 判断记住密码是否勾选,勾选则返回设置的 Cookies
设置 Cookies 代码:
@RequestMapping(value = "/setCookies")
public String getCookies(HttpServletRequest request) {
Cookie cookie=new Cookie("sessionId","CookieTestInfo");
cookie.setMaxAge(60*60);
//cookie.setMaxAge(0);
response.addCookie(cookie);
return " 设置 cookies 信息成功 ";
}
获取 Cookies 代码 (一般不用):
@RequestMapping(value = "/getCookies")
public String getCookies(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if(cookies!=null) {
for (Cookie cookie: cookies) {
if(cookie.getName().equals("sessionId")){
cookie.getValue();
System.out.println("cookieName:"+cookie.getName()+"//cookieValue:"+cookie.getValue());
}
}
return " 获得 cookies 信息成功 ";
}
Token
特色:
安全、跨域、安卓设备、防表单重复登入等等
失效:Session 或者 Token 失效(关闭浏览器)
步骤:
- 客户端使用用户名跟密码请求登录
- 服务端收到请求,去验证用户名与密码
- 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
- 客户端收到 Token 以后可以把它存储起来,比如放在 localStorage 中
- 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
- 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就放行
注意:Session 分别保存加密前、加密后的数据(token), 过滤器对 token 进行解密并和 Session 解密前的 session 进行对比 (可用 redis 缓存)
session 生成方式
浏览器第一次访问服务器,服务器会创建一个 session,然后同时为该 session 生成一个唯一的会话的 key, 也就是 sessionid,然后,将 sessionid 及对应的 session 分别作为 key 和 value 保存到缓存中,也可以持久化到数据库中,然后服务器再把 sessionid,以 cookie 的形式发送给客户端。这样浏览器下次再访问时,会直接带着 cookie 中的 sessionid。然后服务器根据 sessionid 找到对应的 session 进行匹配;
还有一种是浏览器禁用了 cookie 或不支持 cookie,这种可以通过 URL 重写的方式发到服务器;
为什么会有 token 的出现
首先,session 的存储是需要空间的,其次,session 的传递一般都是通过 cookie 来传递的,或者 url 重写的方式;而 token 在服务器是可以不需要存储用户的信息的,而 token 的传递方式也不限于 cookie 传递,当然,token 也是可以保存起来的;
token 的生成方式
浏览器第一次访问服务器,根据传过来的唯一标识 userId,服务端会通过一些算法,如常用的 HMAC-SHA256 算法,然后加一个密钥,生成一个 token,然后通过 BASE64 编码一下之后将这个 token 发送给客户端;客户端将 token 保存起来,下次请求时,带着 token,服务器收到请求后,然后会用相同的算法和密钥去验证 token,如果通过,执行业务操作,不通过,返回不通过信息;
token 和 session 的区别
token 和 session 其实都是为了身份验证,session 一般翻译为会话,而 token 更多的时候是翻译为令牌;
session 服务器会保存一份,可能保存到缓存,文件,数据库;同样,session 和 token 都是有过期时间一说,都需要去管理过期时间;
其实 token 与 session 的问题是一种时间与空间的博弈问题,session 是空间换时间,而 token 是时间换空间。两者的选择要看具体情况而定。
虽然确实都是 “客户端记录,每次访问携带”,但 token 很容易设计为自包含的,也就是说,后端不需要记录什么东西,每次一个无状态请求,每次解密验证,每次当场得出合法 / 非法的结论。这一切判断依据,除了固化在 CS 两端的一些逻辑之外,整个信息是自包含的。这才是真正的无状态。
而 sessionid ,一般都是一段随机字符串,需要到后端去检索 id 的有效性。万一服务器重启导致内存里的 session 没了呢?万一 redis 服务器挂了呢?
方案 A :我发给你一张身份证,但只是一张写着身份证号码的纸片。你每次来办事,我去后台查一下你的 id 是不是有效。
方案 B :我发给你一张加密的身份证,以后你只要出示这张卡片,我就知道你一定是自己人。