原文链接:前后端接口鉴权全解
人不知;鬼不觉也写得比拟长了,一次看不完倡议收藏夹!本文次要解释与申请状态相干的术语(cookie、session、token)和几种常见登录的实现形式,心愿大家看完本文后能够有比拟清晰的了解,有感到蛊惑的中央请在评论区提出。
Cookie
家喻户晓,http 是无状态协定,浏览器和服务器不可能凭协定的实现分别申请的上下文。
于是 cookie 退场,既然协定自身不能分辨链接,那就在申请头部手动带着上下文信息吧。
举个例子,以前去游览的时候,到了景区可能会须要寄存行李,被大包小包压着,游览也不开心啦。在寄存行李后,服务员会给你一个牌子,下面写着你的行李放在哪个格子,来到时,你就能凭这个牌子和下面的数字胜利取回行李。
cookie 做的正是这么一件事,旅客就像客户端,寄存处就像服务器,凭着写着数字的牌子,寄存处(服务器)就能分辨出不同旅客(客户端)。
你会不会想到,如果牌子被偷了怎么办,cookie 也会被偷吗?的确会,这就是一个很常被提到的网络安全问题——CSRF。能够在这篇文章理解对于 CSRF 的成因和应答办法。
cookie 诞生初仿佛是用于电商寄存用户购物车一类的数据,但当初前端领有两个 storage(local、session),两种数据库(websql、IndexedDB),基本不愁信息寄存问题,所以当初基本上 100% 都是在连贯上证实客户端的身份。例如登录之后,服务器给你一个标记,就存在 cookie 里,之后再连贯时,都会主动带上 cookie,服务器便分清谁是谁。另外,cookie 还能够用于跟踪一个用户,这就产生了隐衷问题,于是也就有了“禁用 cookie”这个选项(然而当初这个时代禁用 cookie 是挺麻烦的事件)。
设置形式
事实世界的例子明确了,在计算机中怎么能力设置 cookie 呢?一般来说,平安起见,cookie 都是依附 set-cookie
头设置,且不容许 JavaScript 设置。
Set-Cookie: <cookie-name>=<cookie-value>Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>Set-Cookie: <cookie-name>=<cookie-value>; SecureSet-Cookie: <cookie-name>=<cookie-value>; HttpOnlySet-Cookie: <cookie-name>=<cookie-value>; SameSite=StrictSet-Cookie: <cookie-name>=<cookie-value>; SameSite=LaxSet-Cookie: <cookie-name>=<cookie-value>; SameSite=None; Secure// Multiple attributes are also possible, for example:Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
其中 <cookie-name>=<cookie-value>
这样的 kv 对,内容随你定,另外还有 HttpOnly、SameSite 等配置,一条 Set-Cookie
只配置一项 cookie。
- Expires 设置 cookie 的过期工夫(工夫戳),这个工夫是客户端工夫。
- Max-Age 设置 cookie 的保留时长(秒数),同时存在 Expires 和 Max-Age 的话,Max-Age 优先
- Domain 设置失效的域名,默认就是以后域名,不蕴含子域名
- Path 设置失效门路,
/
全匹配 - Secure 设置 cookie 只在 https 下发送,避免中间人攻打
- HttpOnly 设置禁止 JavaScript 拜访 cookie,避免XSS
- SameSite 设置跨域时不携带 cookie,避免CSRF
Secure 和 HttpOnly 是强烈建议开启的。SameSite 选项须要依据理论状况探讨,因为 SameSite 可能会导致即便你用 CORS 解决了逾越问题,仍然会因为申请没自带 cookie 引起一系列问题,一开始还认为是 axios 配置问题,绕了一大圈,然而基本没关系。
其实因为 Chrome 在某一次更新后把没设置 SameSite
默认为 Lax
,你不在服务器手动把 SameSite
设置为 None
就不会主动带 cookie 了。
发送形式
参考 MDN,cookie 的发送格局如下(其中 PHPSESSID 相干内容上面会提到):
Cookie: <cookie-list>Cookie: name=valueCookie: name=value; name2=value2; name3=value3Cookie: PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1
在发送 cookie 时,并不会传下面提到的配置到服务器,因为服务器在设置后就不须要关怀这些信息了,只有古代浏览器运作失常,收到的 cookie 就是没问题的。
Session
从 cookie 说到 session,是因为 session 才是真正的“信息”,如下面提到的,cookie 是容器,外面装着 PHPSESSID=298zf09hf012fh2;
,这就是一个 session ID。
不晓得 session 和 session id 会不会让你看得有点头晕?
当初 session 的存在就是要为客户端和服务器连贯提供的信息,所以我将 session 了解为信息,而 session id 是获取信息的钥匙,通常是一串惟一的哈希码。
接下来剖析两个 node.js express 的中间件,了解两种 session 的实现形式。
session 信息能够贮存在客户端,如 cookie-session,也能够贮存在服务器,如 express-session。应用 session ID 就是把 session 放在服务器里,用 cookie 里的 id 寻找服务器的信息。
客户端贮存
对于 cookie-session 库,比拟容易了解,其实就是把所有信息加密后塞到 cookie 里。其中波及到 cookies 库。在设置 session 时其实就是调用 cookies.set,把信息写到 set-cookie 里,再返回浏览器。换言之,取值和赋值的实质都是操作 cookie。
浏览器在接管到 set-cookie 头后,会把信息写到 cookie 里。在下次发送申请时,信息又通过 cookie 原样带回来,所以服务器什么货色都不必存,只负责获取和解决 cookie 里的信息,这种实现办法不须要 session ID。
这是一段应用 cookie-session 中间件为申请增加 cookie 的代码:
const express = require('express')var cookieSession = require('cookie-session')const app = express()app.use( cookieSession({ name: 'session', keys: [ /* secret keys */ 'key', ], // Cookie Options maxAge: 24 * 60 * 60 * 1000, // 24 hours }))app.get('/', function(req, res) { req.session.test = 'hey' res.json({ wow: 'crazy', })})app.listen(3001)
在通过 app.use(cookieSession())
应用中间件之前,申请是不会设置 cookie 的,增加后再拜访(并且在设置 req.session 后,若不增加 session 信息就没必要写、也没内容写到 cookie 里),就能看到服务器响应头部新增了上面两行,别离写入 session 和 session.sig:
Set-Cookie: session=eyJ0ZXN0IjoiaGV5In0=; path=/; expires=Tue, 23 Feb 2021 01:07:05 GMT; httponlySet-Cookie: session.sig=QBoXofGvnXbVoA8dDmfD-GMMM6E; path=/; expires=Tue, 23 Feb 2021 01:07:05 GMT; httponly
而后你就能在 DevTools 的 Application 标签看到 cookie 胜利写入。session 的值 eyJ0ZXN0IjoiaGV5In0=
通过 base64 解码(不理解 base64 的话能够看这里)即可失去 {"test":"hey"}
,这就是所谓的“将 session 信息放到客户端”,因为 base64 编码并不是加密,这就跟明文传输没啥区别,所以请不要在客户端 session 里放用户明码之类的机密信息。
即便古代浏览器和服务器做了一些约定,例如应用 https、跨域限度、还有下面提到 cookie 的 httponly 和 sameSite 配置等,保障了 cookie 平安。然而想想,传输平安保障了,如果有人偷看你电脑里的 cookie,明码又恰好存在 cookie,那就能无声无息地偷走明码。相同的,只放其余信息或是仅仅证实“已登录”标记的话,只有退出一次,这个 cookie 就生效了,算是升高了潜在危险。
说回第二个值 session.sig,它是一个 27 字节的 SHA1 签名,用以校验 session 是否被篡改,是 cookie 平安的又一层保障。
服务器贮存
既然要贮存在服务器,那么 express-session 就须要一个容器 store,它能够是内存、redis、mongoDB 等等等等,内存应该是最快的,然而重启程序就没了,redis 能够作为备选,用数据库存 session 的场景感觉不多。
express-session 的源码没 cookie-session 那么扼要易懂,外面有一个有点绕的问题,req.session
到底是怎么插入的?
不关注实现能够跳过这段,有趣味的话能够跟着思路看看 express-session 的源码。
咱们能够从 .session =
这个关键词开始找,找到:
store.generate
否决这个,容易看出这个是初始化应用的Store.prototype.createSession
这个是依据 req 和 sess 参数在 req 中设置 session 属性,没错,就是你了
于是全局搜寻 createSession
,锁定 index 里的 inflate
(就是填充的意思)函数。
最初寻找 inflate
的调用点,是应用 sessionID 为参数的 store.get
的回调函数,所有说得通啦——
在监测到客户端送来的 cookie 之后,能够从 cookie 获取 sessionID,再应用 id 在 store 中获取 session 信息,挂到 req.session
,通过这个中间件,你就能顺利地应用 req 中的 session。
那赋值怎么办呢?这就和下面贮存在客户端不同了,下面要批改客户端 cookie 信息,然而对于贮存在服务器的状况,你批改了 session 那就是“实实在在地批改”了嘛,不必其余花里胡哨的办法,内存中的信息就是批改了,下次获取内存里的对应信息也是批改后的信息。(仅限于内存的实现形式,应用数据库时仍须要额定的写入)
在申请没有 session id 的状况下,通过 store.generate
创立新的 session,在你写 session 的时候,cookie 能够不扭转,只有依据原来的 cookie 拜访内存里的 session 信息就能够了。
var express = require('express')var parseurl = require('parseurl')var session = require('express-session')var app = express()app.use( session({ secret: 'keyboard cat', resave: false, saveUninitialized: true, }))app.use(function(req, res, next) { if (!req.session.views) { req.session.views = {} } // get the url pathname var pathname = parseurl(req).pathname // count the views req.session.views[pathname] = (req.session.views[pathname] || 0) + 1 next()})app.get('/foo', function(req, res, next) { res.json({ session: req.session, })})app.get('/bar', function(req, res, next) { res.send('you viewed this page ' + req.session.views['/bar'] + ' times')})app.listen(3001)
两种贮存形式的比照
首先还是计算机世界最重要的哲学问题:工夫和空间的抉择。
贮存在客户端的状况,解放了服务器寄存 session 的内存,然而每次都带上一堆 base64 解决的 session 信息,如果量大的话传输就会很迟缓。
贮存在服务器相同,用服务器的内存援救了带宽。
另外,在退出登录的实现和后果,也是有区别的。
贮存在服务器的状况就很简略,如果 req.session.isLogin = true
是登录,那么 req.session.isLogin = false
就是退出。
然而状态寄存在客户端要做到真正的“即时退出登录”就很艰难了。你能够在 session 信息里加上过期日期,也能够间接依附 cookie 的过期日期,过期之后,就当是退出了。
然而如果你不想等到 session 过期,当初就想退出登录!怎么办?认真想想你会发现,仅仅依附客户端贮存的 session 信息真的没有方法做到。
即便你通过 req.session = null
删掉客户端 cookie,那也只是删掉了,然而如果有人已经把 cookie 复制进去了,那他手上的 cookie 直到 session 信息里的过期工夫前,都是无效的。
说“即时退出登录”有点题目党的象征,其实我想表白的是,你没方法立刻破除一个 session,这可能会造成一些隐患。
Token
session 说完了,那么呈现频率超高的关键字 token 又是什么?
无妨谷歌搜一下 token 这个词,能够看到冒出来几个(年纪大的人)比拟相熟的图片:明码器。过来网上银行不是只有短信认证就能转账,还要通过一个明码器,下面显示着一个变动的明码,在转账时你须要输出明码器中的代码能力转账,这就是 token 事实世界中的例子。凭借一串码或是一个数字证实本人身份,这事件不就和下面提到的行李问题还是一样的吗……
其实实质上 token 的性能就是和 session id 截然不同。你把 session id 说成 session token 也没什么问题(Wikipedia 里就写了这个别名)。
其中的区别在于,session id 个别存在 cookie 里,主动带上;token 个别是要你被动放在申请中,例如设置申请头的 Authorization
为 bearer:<access_token>
。
然而下面说的都是个别状况,基本没有明确规定!
剧透一下,上面要讲的 JWT(JSON Web Token)!他是一个 token!然而外面放着 session 信息!放在客户端,并且能够随你抉择放在 cookie 或是手动增加在 Authorization!然而他就叫 token!
集体感觉你不能通过寄存的地位判断是 token 或是 session id,也不能通过内容判断是 token 或是 session 信息,session、session id 以及 token 都是很意识流的货色,只有你明确他是什么、怎么用就好了,怎么称说不太重要。
另外在搜寻材料时也看到有些文章说 session 和 token 的区别就是新旧技术的区别,如同有点情理。
在 session 的 Wikipedia 页面上 HTTP session token 这一栏,举例都是 JSESSIONID (JSP)、PHPSESSID (PHP)、CGISESSID (CGI)、ASPSESSIONID (ASP) 等比拟传统的技术,就像 SESSIONID 是他们的代名词个别;而在钻研当初各种平台的 API 接口和 OAuth2.0 登录时,都是应用 access token 这样的字眼,这个区别着实有点意思。
了解 session 和 token 的分割之后,能够在哪里能看到“活的” token 呢?
关上 GitHub 进入设置,找到 Settings / Developer settings,能够看到 Personal access tokens 选项,生成新的 token 后,你就能够带着它通过 GitHub API,证实“你就是你”。
在 OAuth 零碎中也应用了 Access token 这个关键词,写过微信登录的敌人应该都能感触到 token 是个什么啦。
Token 在权限证实上真的很重要,不可透露,谁拿到 token,谁就是“客人”。所以要做一个 Token 零碎,刷新或删除 Token 是必须要的,这样在尽快补救 token 透露的问题。
在了解了三个关键字和两种贮存形式之后,上面咱们正式开始说“用户登录”相干的常识和两种登录标准——JWT 和 OAuth2.0。
接着你可能会频繁见到 Authentication 和 Authorization 这两个单词,它们都是 Auth 结尾,但可不是一个意思,简略来说前者是验证,后者是受权。在编写登录零碎时,要先验证用户身份,设置登录状态,给用户发送 token 就是受权。
JWT
全称 JSON Web Token(RFC 7519),是的,JWT 就是一个 token。为了不便了解,提前通知大家,JWT 用的是下面客户端贮存的形式,所以这部分可能会常常用到下面提到的名称。
构造
虽说 JWT 就是客户端贮存 session 信息的一种,然而 JWT 有着本人的构造:Header.Payload.Signature
(分为三个局部,用 .
隔开)
Header
{ "alg": "HS256", "typ": "JWT"}
typ 阐明 token 类型是 JWT,alg 代表签名算法,HMAC、SHA256、RSA 等。而后将其 base64 编码。
Payload
{ "sub": "1234567890", "name": "John Doe", "admin": true}
Payload 是搁置 session 信息的地位,最初也要将这些信息进行 base64 编码,后果就和下面客户端贮存的 session 信息差不多。
不过 JWT 有一些约定好的属性,被称为 Registered claims,包含:
- iss (issuer):签发人
- exp (expiration time):过期工夫
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):失效工夫
- iat (Issued At):签发工夫
- jti (JWT ID):编号
Signature
最初一部分是签名,和下面提到的 session.sig
一样是用于避免篡改,不过 JWT 把签名和内容组合到一起罢了。
JWT 签名的生成算法是这样的:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
应用 Header 里 alg 的算法和本人设定的密钥 secret 编码 base64UrlEncode(header) + "." + base64UrlEncode(payload)
最初将三局部通过 .
组合在一起,你能够通过 jwt.io Debugger 形象地看到 JWT 的组成原理:
如何应用
在验证用户,顺利登录后,会给用户返回 JWT。因为 JWT 的信息没有加密,所以别往里面放明码,具体起因在客户端贮存的 cookie 中提到。
用户拜访须要受权的连贯时,能够把 token 放在 cookie,也能够在申请头带上 Authorization: Bearer <token>
。(手动放在申请头不受 CORS 限度,不怕 CSRF)
这样能够用于自家登录,也能够用于第三方登录。单点登录也是 JWT 的罕用畛域。
JWT 也因为信息贮存在客户端造成无奈让本人生效的问题,这算是 JWT 的一个毛病。
HTTP authentication
HTTP authentication 是一种标准化的校验形式,不会应用 cookie 和 session 相干技术。申请头带有 Authorization: Basic <credentials>
格局的受权字段。
其中 credentials 就是 Base64 编码的用户名 + :
+ 明码(或 token),当前看到 Basic authentication,意识到就是每次申请都带上用户名明码就好了。
Basic authentication 大略比拟适宜 serverless,毕竟他没有运行着的内存,无奈记录 session,间接每次都带上验证就完事了。
OAuth 2.0
OAuth 2.0(RFC 6749)也是用 token 受权的一种协定,它的特点是你能够在无限范畴内应用别家接口,也能够借此应用别家的登录零碎登录自家利用,也就是第三方利用登录。(留神啦留神啦,OAuth 2.0 受权流程说不定面试会考哦!)
既然是第三方登录,那除了利用自身,必然存在第三方登录服务器。在 OAuth 2.0 中波及三个角色:用户、利用提供方、登录平台,互相调用关系如下:
+--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -->| Authorization | | Client | | Server | | |<-(D)----- Access Token -------| | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---| | +--------+ +---------------+
很多大公司都提供 OAuth 2.0 第三方登录,这里就拿小聋哥的微信举例吧——
筹备
一般来说,利用提供方须要先在登录平台申请好 AppID 和 AppSecret。(微信应用这个名称,其余平台也差不多,一个 ID 和一个 Secret)
获取 code
什么是受权长期票据(code)? 答:第三方通过 code 进行获取access_token
的时候须要用到,code 的超时工夫为 10 分钟,一个 code 只能胜利换取一次access_token
即生效。code 的临时性和一次保障了微信受权登录的安全性。第三方可通过应用 https 和 state 参数,进一步增强本身受权登录的安全性。
在这一步中,用户先在登录平台进行身份校验。
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
参数 | 是否必须 | 阐明 |
---|---|---|
appid | 是 | 利用惟一标识 |
redirect_uri | 是 | 请应用 urlEncode 对链接进行解决 |
response_type | 是 | 填 code |
scope | 是 | 利用受权作用域,领有多个作用域用逗号(,)分隔,网页利用目前仅填写 snsapi_login |
state | 否 | 用于放弃申请和回调的状态,受权申请后原样带回给第三方。该参数可用于避免 csrf 攻打(跨站申请伪造攻打) |
留神一下 scope 是 OAuth2.0 权限管制的特点,定义了这个 code 换取的 token 能够用于什么接口。
正确配置参数后,关上这个页面看到的是受权页面,在用户受权胜利后,登录平台会带着 code 跳转到利用提供方指定的 redirect_uri
:
redirect_uri?code=CODE&state=STATE
受权失败时,跳转到
redirect_uri?state=STATE
也就是失败时没 code。
获取 token
在跳转到重定向 URI 之后,利用提供方的后盾须要应用微信给你的code获取 token,同时,你也能够用传回来的 state 进行起源校验。
要获取 token,传入正确参数拜访这个接口:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数 | 是否必须 | 阐明 |
---|---|---|
appid | 是 | 利用惟一标识,在微信开放平台提交利用审核通过后取得 |
secret | 是 | 利用密钥 AppSecret,在微信开放平台提交利用审核通过后取得 |
code | 是 | 填写第一步获取的 code 参数 |
grant_type | 是 | 填 authorization_code,是其中一种受权模式,微信当初只反对这一种 |
正确的返回:
{ "access_token": "ACCESS_TOKEN", "expires_in": 7200, "refresh_token": "REFRESH_TOKEN", "openid": "OPENID", "scope": "SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"}
失去 token 之后你就能够依据之前申请 code 填写的 scope 调用接口了。
应用 token 调用微信接口
受权作用域(scope) | 接口 | 接口阐明 |
---|---|---|
snsapi_base | /sns/oauth2/access_token | 通过 code 换取 access_token 、refresh_token 和已受权 scope |
snsapi_base | /sns/oauth2/refresh_token | 刷新或续期 access_token 应用 |
snsapi_base | /sns/auth | 查看 access_token 有效性 |
snsapi_userinfo | /sns/userinfo | 获取用户个人信息 |
例如获取个人信息就是 GET
https://api.weixin.qq.com/sns...
留神啦,在微信 OAuth 2.0,access_token
应用 query 传输,而不是下面提到的 Authorization。
应用 Authorization 的例子,如 GitHub 的受权,后面的步骤基本一致,在获取 token 后,这样申请接口:
curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com
说回微信的 userinfo 接口,返回的数据格式如下:
{ "openid": "OPENID", "nickname": "NICKNAME", "sex": 1, "province":"PROVINCE", "city":"CITY", "country":"COUNTRY", "headimgurl":"https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"}
后续应用
在应用 token 获取用户个人信息后,你能够接着用 userinfo 接口返回的 openid,联合 session 技术实现在本人服务器登录。
// 登录req.session.id = openidif (req.session.id) { // 已登录} else { // 未登录}// 退出req.session.id = null// 革除 session
总结一下 OAuth2.0 的流程和重点:
- 为你的利用申请 ID 和 Secret
- 筹备好重定向接口
- 正确传参获取 code <- 重要
- code 传入你的重定向接口
- 在重定向接口中应用 code 获取 token <- 重要
- 传入 token 应用微信接口
OAuth2.0 着重于第三方登录和权限限度。而且 OAuth2.0 不止微信应用的这一种受权形式,其余形式能够看阮老师的OAuth 2.0 的四种形式。
其余办法
JWT 和 OAuth2.0 都是成体系的鉴权办法,不代表登录零碎就肯定要这么简单。
简略登录零碎其实就以下面两种 session 贮存形式为根底就能做到。
- 应用服务器贮存 session 为根底,能够用相似
req.session.isLogin = true
的办法标记该 session 的状态为已登录。 - 应用客户端贮存 session 为根底,设置 session 的过期日期和登录人就根本能用了。
{ "exp": 1614088104313, "usr": "admin"}
(就是和 JWT 原理根本一样,不过没有一套体系)
- 甚至你能够应用下面的常识本人写一个 express 的登录零碎:
- 初始化一个 store,内存、redis、数据库都能够
- 在用户身份验证胜利后,随机生成一串哈希码作为 token
- 用 set-cookie 写到客户端
- 再在服务器写入登录状态,以内存为例就是在 store 中增加哈希码作为属性
- 下次申请带着 cookie 的话查看 cookie 带来的 token 是否曾经写入 store 中即可
let store = {}// 登录胜利后store[HASH] = truecookie.set('token', HASH)// 须要鉴权的申请钟const hash = cookie.get('token')if (store[hash]) { // 已登录} else { // 未登录}// 退出const hash = cookie.get('token')delete store[hash]
总结
以下列出本文重点:
- cookie 是贮存 session/session id/token 的容器
- cookie 设置个别通过
set-cookie
申请头设置 - session 信息能够寄存在浏览器,也能够寄存在服务器
- session 寄存在服务器时,以 session id 为钥匙获取信息
- token/session/session id 三者的界线是含糊的
- 个别新技术应用 token,传统技术应用 session id
- cookie/token/session/session id 都是用于鉴权的实用技术
- JWT 是浏览器贮存 session 的一种
- JWT 罕用于单点登录(SSO)
- OAuth2.0 的 token 不是由利用端颁发,存在另外的受权服务器
- OAuth2.0 罕用于第三方利用登录
参考
- MDN Cookie
- wikipedia HTTP_cookie
- wikipedia Session
- cookie-session
- express-session
- OAuth access-token
- MDN HTTP authentication
- JWT introduction
- 阮一峰 JSON Web Token 入门教程
- 微信 OAuth2.0 登录