不同身份认证方案:
服务端渲染推荐使用Session认证机制
前后端分离推荐使用JWT认证机制
Session认证机制
Cookie:
Cookie是存储在用户浏览器中一段不超过4kb的字符串,它由一个名称(Name),y一个值(Value)和几个用于控制Cookie有效期,安全性,使用范围的可选属性组成
不同域名下的Cookie各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的Cookie一同发送到服务器。
Cookie的几大特性:
自动发送
域名独立
过期时限
4kb限制
浏览器可以设置不接受Cookie,也可以设置不向服务器发送Cookie,window.navigator.cookieEnabled属性返回一个布尔值,表示浏览器是否打开cookie功能
两个域名只要域名相同和端口相同就可以共享Cookie,也就是说http://example.com设置的Cookie可以被https://example.com读取
Cookie在身份认证中的作用:
客户端第一次请求服务器时,服务器通过响应头Set-Cookie的形式,向客户端发送一个身份认证的Cookie,客户端会自动将Cookie保存在浏览器中,随后,当客户端浏览器每次请求服务器时浏览器会自动将身份认证相关的Cookie,通过请求头的形式发送给服务器Cookie:foo=bar,服务器即可验证客户端身份
Cookie的属性
Expires,Max-Age:
Expires属性指定一个具体的到齐时间,到了指定时间后,浏览器就不再保留这个Cookie,它的值时UTC格式,可以使用Date.prototype.toUTCString()进行格式转换
1 | Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; |
如果不设置该属性,或者设置为null,Cookie只在当前会话有效,浏览器窗口一旦关闭,当前Session结束,该Cookie被删除,另外,浏览器根据本地时间,觉得Cookie是否过期,由于本地时间不精确,没有办法保证Cookie一旦会在服务器指定时间过期
Max-Age属性指定从现在开始Cookie存在的描述,即过了这个时间后,浏览器就不再保留这个Cookie,如果同时指定Expires和Max-Age,那么Max-Age的值优先生效
Domain,Path
Domain属性指定浏览器发出Http请求时,哪些域名要附带这个Cookie,如果没有指定该属性,浏览器会默认将其设为当前URL的一级域名,比如www.example.com会设为example.com,而且以后如果访问example.com的任何子域名,HTTP请求也会带上这个Cookie,如果服务器在Set-Cookie字段指定的域名不属于当前域名,浏览器会拒绝这个Cookie
Path属性指定指定浏览器发出HTTP请求时哪些路径要附带这个Cookie,只要浏览器发现,Path属性是HTTP请求路径的开头一部分,就会在头信息里面带上这个Cookie,比如PATH属性时/,那么请求/docs路径也会包含该Cookie,当然,前提是域名必须一致
Secure,HttpOnly
Secure属性指定浏览器在加密协议HTTPS下,才能将这个Cookie发送到服务器,另一方面,如果当前协议是HTTP,浏览器会自动忽略服务器发来的Secure属性,该属性只是一个开关,不需要指定值,如果通信时HTTS协议,开关自动打开
HttpOnly属性指定该Cookie无法通过JavaScript脚本拿到,主要是Document.cookie属性,XMLHttpRequest对象和Request API都拿不到该属性,这样就防止了该Cookie被脚本读到,只有浏览器发出HTTP请求时才会带上该Cookie
Cookie具有不安全性
由于Cookie是存储在浏览器中的,因此浏览器也提供了读写Cookie的API,因此Cookie很容易被伪造,不具有安全性,因此Cookie不能存放重要隐私数据
Session工作原理:
- 客户端把用户ID和密码等登陆信息放入报文的实体部分,通常是以POST请求发送给服务器,而这时使用HTTPS通信来进行HTML表单画面的显示和用户输入数据的发送
- 服务器会发放用以识别用户的Session ID,通过验证从客户端送过来的登录信息进行身份认证,人后把用户认证状态与Session ID绑定后记录在服务器端,向客户端返回响应时,会在首部字段Set-Cookie内写入Sessin ID,为避免SessionId被盗,可在Cookie中加入httponly属性
- 客户端接收到从服务器发来的Session ID后,会将其作为Cookie保存哎本地,下次向服务器发送请求时,浏览器自动发送Cookie,服务器通过验证接收到的Session ID识别用户和其认证状态
Session认证需要配合Cookie实现,由于Cookie默认不支持跨域访问,所以当涉及前端跨域请求后端接口时需要做额外配置。因此当前端请求后端接口不涉及跨域请求时推荐使用Session身份认证机制,否则使用JWT认证
流程:
- 浏览器登录发送账号密码,服务端查询用户库,校验用户
- 服务端把用户登录状态存为Session,生成一个sessionId
- 通过登录把接口返回,把sessionId set到cookie上
- 此后浏览器再请求业务接口,sessionId随cookie带上
- 服务端查sessionId检验session
- 成功后正常做业务处理,返回结果
1 | const express=require('express'); |
JWT认证机制:
工作原理
jwt组成部分:
头部.有效荷载.签名
Header.PayLoad.Signature
头部由两部分组成:令牌类型即JWT,以及正在使用的签名算法,例如HMAC SHA256或RSA
例如:
1 | { |
这个JSON被Base64Url编码形成JWT第一部分
有效载荷:
包含声明,声明式关于实体(通常是用户)和附加数据的陈述,
身份认证中:
当用户使用凭据成功登录后,将返回一个JSON Web Token,由于token是凭据,因此要小心出现安全问题,通常,不应该将令牌保留超过所需的时间,也不应该将敏感数据存储在浏览器存储中,token在Authorization标头中发送,则跨域资源共享不会成为问题,因为它不使用cookie
客户端收到服务器返回的JWT后,通常会将它存储在localStorage或者sessionStorage中,此后客户端每次与服务端通信,都要带上这个JWT的字符串,进行身份认证,推荐把JWT放在Http请求头的Authorization字段中
Authorization:Bearer
为什么使用JWT:
应用程序可以使用访问access token去访问受保护的资源,比如一个接口
在Express中使用JWT,express-jwt会自动把JWT的payload部分赋值于req.user,方便逻辑部分调用
1 | const express=require('express'); |