更多个人博客:(https://github.com/zenglinan/blog)
如果对你有帮助,欢迎star。
一. session鉴权
原理:
<img width="512" alt="1" src="https://user-images.githubusercontent.com/37680843/65383102-97733280-dd42-11e9-892a-8dafc94f20c0.png">
前端如果注销的话就清除 cookie
, 如果后端需要强制前端重新登陆认证的话就修改 session
session 鉴权的缺陷:
- 基于
cookie
, 容易被劫持 (设置 http-only, 让 script 标签无法获取cookie
, 防止 XSS 攻击, 也可以用 https)
- 应用场景有限, 只有浏览器有
Cookie
- 如果是分布式部署,需要做多机共享
session
机制,实现方法: 可将session
存储到数据库中或者 redis 中
session 鉴权的优点:
- 相比
JWT
, 可以手动清除session
-
session
保存在服务端, 比较安全
二. JWT 鉴权 (jsonWebToken)
原理:
- 浏览器发起登录请求
- 请求通过后,服务器会向浏览器返回
token
- 前端接收到
token
后需要把token
保存到本地 (比如 localStorage、session
Storage) 用户点注销时前端删除保存的token
即可
- 前端在每次请求时将
token
作为请求头中Authorization
的值。至于为什么要用Authorization
作为键名, 习惯习惯.....
- 服务器收到请求,去解析
token
, 验证成功后会返回对应的用户数据
token
说了那么多, 那 token 到底是什么?
token
实际由三段字符串组成 Header.Payload.Signature
, 中间用 . 作为分隔
- Header(一般是用 base64 编码的 json)
- typ:
token
的类型,这里固定为JWT
- alg:使用的 hash 算法,例如:HMAC SHA256 或者 RSA
- Payload(一般是用 base64 编码的 json)
Payload 携带了要传递的主要信息 - Signature(加密的签名)
前面两部分都是 base 64 编码的明文, 只有这部分是加密的签名。
说了这么多, 就我们来模拟一个 token
看看吧
这里我们启动一个 express
服务器, 引入 jsonwebtoken
(可以帮助我们生成 token)
const express = require('express')
const JWT = require('jsonwebtoken')
const app = express()
app.get('/login', (req, res) => {
const { username } = req.query
const name = { username }
const token = JWT.sign(name, 'abdddtasjfbwerkhjdczc') // 生成 token, 参数 1 为传递的主体信息, 参数 2 是一个随机字符串, 用来加密生成签名
res.send(token)
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
启动服务器并访问, 让我们看看浏览器端显示了什么?
仔细一看, 确实有两个 . 而且前面两段还是以 eyJ 开头的, 看起来像是 base64 编码的字符串。我们可以用 Buffer.from()
解析一下
第一段
1569133003(1)
第二段
1569133090(1)
这里面的iat
是jsonwebtoken
帮我们添加的, 表示生成的时间new Date().getTime()
第三段
这一段就解析不了了, 上面说过, 三段里只有这一段不是明文的, 是经过加密的签名。
JWT 鉴权的优点:
不基于 cookie
, 可以跨端使用, 但是浏览器不会自动带上 token
, 需要前端发送请求的时候带上
session
鉴权和 JWT
鉴权有个共同的好处就是: 都有加密的部分, 即使被劫取了, 也只能通过劫取的内容进行访问, 不能做到篡改。
如果要减少被劫持登录的风险, 可以 采用 HTTPS, 对传输过程进行一个 ssl 的加密, 其次, 当访问的 ip 改变时, 要求用户重新登录。
三. OAuth2 鉴权
OAuth2.0 实际上是第三方登录的一种鉴权协议
参考: https://www.barretlee.com/blog/2016/01/10/oauth2-introduce/