基于 Token 的身份验证问题
首先声明,此文章并非原创,只是在学习的过程中做一个记录,下次需要的时候方便寻找查阅。直接转载肯定没有看的仔细透彻,所以便手动写一遍。原文地址:
https://blog.csdn.net/z69183787/article/details/79160368
传统身份的验证方法
HTTP是一种无状态的协议,也就是说它不知道是谁在访问应用。这里我么把应用看作是客户端,客户端使用用户名和密码通过了身份验证,不过下回客户端发送请求的时候还得再验证一下。
解决的办法就是,当用户请求登陆的时候,如果没有问题,我们在服务端生成一条记录,这个记录可以说明一下登陆的用户是谁,然后把这条记录的ID号发给客户端,客户端收到以后把这个ID号存储在cookie中,下次这个用户再向服务端发送请求的时候,可以带着这个cookie,这样服务端会验证一下这个cookie里的信息,看看能不能在服务端中找到对应的记录,如果可以说明用户已经通过验证
基于 Token 的身份验证方法
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
1.客户端使用用户名密码请求登陆;
2.服务端收到请求,去验证用户名和密码;
3.验证成功后,服务端会签发一个 Token ,再把这个 Token 发给客户端;
4.客户端收到 Token 后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里;
5.客户端每次向服务端请求资源的时候需要带着服务端签发的 Token;
6.服务端收到请求,然后去验证客户端请求里面带着的 Token ,如果验证成功,就向客户端返回请求的数据。
JWT
实施 Token 验证的方法挺多的,还有一些标准的方法,比如 JWT,读作 jot,表示 Jsone Web Tokens。JWT标准的 Token 有三部分:
- header
- payload
- signature
中间用点分隔开,并且都会使用Base64编码,所以真正的 Token 看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
Header
header 部分主要是两部分内容,一个是 Token 的类型,另一个是使用的算法,比如下面的类型就是JWT,使用的算法就是 HS256
{
"typ": "JWT",
"alg": "HS256"
}
上面的内容要用 Base64 编码一下,所以就变成这样
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也可以添加其他需要的内同。下面是标准字段:
- iss: Issuer,发行者
- sub:Subject,主题
- aud:Audience,观众
- exp:Expiration time,过期时间
- nbf:Not before
- iat:Issue at,发行时间
- jti:JWT ID
比如下面这个 Payload ,用到了 iss 发行人,还有 exp 过期时间。另外还有两个自定义的字段,一个是 name ,还有一个是 admin 。
{
"iss": "ninghao.net",
"exp": "1438955445",
"name": "wanghao",
"admin": true
}
使用 Base64 编码以后就变成了这个样子:
eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ
Signature
JWT的最后一部分是Signature,这部分内容有三个部分,先是用Base64编码的 header.payload ,再用加密算法加密一下,加密的时候要放进去一个 secret,这个相当于是一个密码,这个密码秘密的储存在服务端。
- header
- payload
- secrect
var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);
HMACSHA256(encodedString, 'secret');
处理完成以后看起来像这样:
SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
最后这个在服务端生成并且要发送给客户端的 Token 看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
客户端收到这个 Token 以后把它存储下来,下回向服务端发送请求的时候就带着这个 Token 。服务端收到这个 Token ,然后进行验证,通过以后就会返回给客户端想要的资源。
相关链接
- http://jwt.io/
- https://github.com/firebase/php-jwt
- https://scotch.io/tutorials/the-anatomy-of-a-json-web-token
- https://github.com/auth0/jwt-decode
相关课程
1.《JWT:JSON Web Token》
2.《Node.js:基于 Token 的身份验证》
3.《WordPress 开发:身份验证(JWT)》
4.《微信小程序:应用后台__身份验证 #3》