本文最后更新于 2025年11月16日 晚上
协议与框架的安全认证流程及适用场景
JWT令牌认证实现详解
构成:JWT由三部分组成,以点(.)分隔:
1.头部
1 2 3 4
| { "alg":"签名算法" "typ":"jwt" }
|
2.payload(负载)
1 2 3 4 5 6 7 8 9 10
| { "sub": "1234567890", "name": "张三", "admin": true, "iat": 1516239022, "exp": 1516242622 }
|
3.signature(签名)
用于验证消息在传输过程中是否被篡改,对于使用私钥签名的令牌,还可以验证jwt的发送方是否为正确发送方
验证流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ┌─────────┐ ┌────────────┐ │ │ │ │ │ 客户端 │ │ 服务器 │ │ │ │ │ └────┬────┘ └──────┬─────┘ │ │ │ 1. 发送用户名和密码 │ │ ─────────────────────────────────────────────────────────> │ │ │ │ 2. 验证凭据,生成JWT令牌 │ │ <───────────────────────────────────────────────────────── │ │ │ │ 3. 存储JWT令牌 │ │ │ │ 4. 请求资源,在Header中携带JWT │ │ ─────────────────────────────────────────────────────────> │ │ │ │ 5. 验证JWT,提取用户信息 │ │ │ │ 6. 根据用户权限决定是否允许访问 │ │ <───────────────────────────────────────────────────────── │ │ │
|
应用场景
用于登录授权认证或者信息交换验证,用公私钥对确保验证内容不会被篡改
OAuth2.0
思想:允许用户批准第三方访问某一网站的资源,在这个过程中无需将账号密码提供给第三方应用,用令牌来替代
优势:令牌与密码的作用一样,但是比密码好管理,通过令牌授予的权限存在一定的有效期,到期会自动失效,用户在收回权限时无需修改密码,让口令失效即可
OAuth2.0的四种授权方式
OAuth2.0的标准文件是RFC 6749,该文件解释说明了OAuth的核心在于向第三方颁发令牌
授权码
原理:
第一步
A网站会提供一个链接,用户点击后会向B网站请求授权
1 2 3 4 5
| https: response_type=code& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read
|
其中response_type是返回授权码,请求时默认为字段code
client_id代表用户id,redirect_uri代表授权成功或失败后会跳转的地址,scope代表授予的权限
第二步
跳转后B网站会询问是否授权,同意后会跳回redirect_uri并带上授权码
第三步
A网站拿到授权码后即可在后端对B网站请求令牌
1 2 3 4 5 6
| https: client_id=CLIENT_ID& client_secret=CLIENT_SECRET& grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_uri=CALLBACK_URL
|
client_id和client_secret用于B网站确认用户的身份,grant_type用于表示授权方式是授权码,然后code是请求到的授权码
第四步
B网站收到请求后,就会颁发令牌。具体做法是向redirect_uri指定的网址,发送一段 JSON 数据
1 2 3 4 5 6 7 8 9 10
| { "access_token":"ACCESS_TOKEN", "token_type":"bearer", "expires_in":2592000, "refresh_token":"REFRESH_TOKEN", "scope":"read", "uid":100101, "info":{...} }
|
access_token就是令牌
隐藏式
有些web是纯前端应用,因此这种方式允许前端直接向B网站发起令牌请求,没有授权码
1 2 3 4 5
| https: response_type=token& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read
|
跳转到B网站允许授权后,就会直接返回token
密码式
就是用账号密码请求,与账号密码登录没有区别
1 2 3 4 5
| https: grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID
|
凭证式
1 2 3 4
| https: grant_type=client_credentials& client_id=CLIENT_ID& client_secret=CLIENT_SECRET
|
上面 URL 中,grant_type参数等于client_credentials表示采用凭证式,client_id和client_secret用来让 B 确认 A 的身份。
第二步,B 网站验证通过以后,直接返回令牌。
这个令牌的使用一般只能在命令行