一 、 问题原因:
http是无状态协议,用户每次访问,服务器都是新建会话,不能确定哪些请求是同一个用户发出的。
怎么确定请求来自同一个客户?
二、 session:
2.1 session是一种保存上下文信息的机制,且保存在服务端中,主要以cookie或者URL重写实现的
系统创造一个JSESSIONID的变量传输到cookie中, JSESSIONID保存在内存中,不写入硬盘
如果禁用浏览器cookie,服务器会改用URL重写传递Sessioid, Url中会存在sessionid=xxx字符串
JSESSIONID 不能跨窗口
2.2 服务端session
步骤:
1、用户向服务器发送用户名和密码。
2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
3、服务器向用户返回一个 session_id,写入用户的 Cookie。
4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。
session在服务端,以散列表形式保存在内存中
2.3 session存在问题:
集群/多服务器 环境下,session不能共享
解决思路:
session复制到各个服务器 – 成本高,难维护,登录延迟
session集中存储 – 单独服务器管理,一般使用redis集中管理
使用JWT,服务器端不保存session
3 多服务下登录问题,SSO方案
大企业会有不同的系统,进入每个系统需要登录,获取session,访问对应资源
如何实现一次登录,可以进入不同系统
单点登录思路: 一个ticket进行串接各系统用户信息
外部session存储方案已经非常成熟了(比如Redis)
3.1 SSO
CAS实现单点登录
不同域名下 cookie无法跨域名共享,所以需要一个专门登录的域名(ouath.com)提供所有系统的sessionId
步骤:
- 当b.com 打开,发现未登录, 跳转到 ouath.com
- ouath.com 页面下输入账号密码登录
- ouath.com登录成功, cookie保存在ouath.com域名下
- sessionid放redis, 存放<ticket,sessionid>, 携带ticket重定向到b.com
- b.com重新打开,有一个ticket值
- b.com使用ticket到redis查询到sessionid, 并同步session,获取cookie,页面原地重定向
- b.com打开了页面,而且存了cookie
集中session管理优点:兼容旧版系统
三、JWT
JSON WEB Token(JWT,读作 [/dʒɒt/])
1、JWT原理:
用户登录后,生成一个对象,为了保证没有被篡改, 使用secret生成签名
token 包括 3部分
token = Header . Payload . Signature
1.1 Header(头部)
是一个JSON对象,描述了JWT元数据
{
"alg": "HS256", // 签名算法 默认是 HMAC SHA256
"typ": "JWT" // 类型
}
然后将该对象Base64URL编码成字符串
1.2 Payload(负载)
是一个JSON对象,存放要传递的数据,包括7个官方字段,可选用
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
另外还可以自定义私有字段
由于JWT默认是不加密的,所有人可解码,不可以放秘密信息
该对象Base64URL编码成字符串
1.3 Signature (签名)
对前两个字串签名,防止被篡改.
服务端需要有一个密钥(sercret),使用Header里面的的签名算法, 生成签名
HMACSHA256(base64UrlEncode(header) + "." + HMACSHA256(base64UrlEncode(payload), secret)
最后使用点号分割三个部分,返回给用户
1.4 Base64URL编码
某些场合下会放到URL下, +
/
=
符号需要特使转义
2、 JWT使用流程
客户端接收到JWT,可以存在cookie,也可以存在localStorage中
每次与服务器通信,带上JWT, 在头部信息Authorization字段中
Authorization: Bearer <token>
跨域的时候可以把token放到post请求体中
3、JWT特点
3.1 默认不加密,不加密时不可把重要信息写在payload中
3.2 可以用于认证,也可以用于交换信息,减少了数据库查询次数
3.3 最大缺点, 服务器不报错session状态,不能废止或修改某个token, 在到期之前会有效,除非服务器使用token 黑名单记录token
3.4 JWT 包含认证信息,为减少盗用,有效期要设置比较短, 重要权限,需要再次认证
3.5 为减少盗用, 使用HTTPS协议传输
3.6 相比于Cookie, 占用空间更加大
3.7 安全性:
把重要信息存在localStorage是不安全的
如果您的站点包含来自域外源的第三方 JavaScript 代码,例如一些第三方脚本库的CDN源:
bootstrap 源
jQuery
广告脚本
谷歌分析链接
跟踪脚本
这些代码可以读取localStorage
存储在 HttpOnly Cookie
如果HTTP响应标头中包含HttpOnly标志(可选),客户端脚本将无法访问cookie;如果浏览器不支持HttpOnly,并且后端服务器尝试设置HttpOnly cookie,浏览器也会忽略HttpOnly标志,从而创建传统的,脚本可访问的cookie。那么该cookie(通常是会话cookie)容易受到XSS攻击
Cookie 的 HttpOnly 标签是防御 XSS 的解决方案之一,因为 HttpOnly 在简单的条件下阻止客户端(JavaScript)访问 Cookie。如果再将 secure 标志设置为 true,则只会在安全或加密的网络中使用 Cookie,从而增加其安全性。在使用这个方案的时候需要注意 JWT 的大小。如果 JWT 超过了 4KB 就不适合使用 Cookie 存储 JWT的方案。