一、简介
使用传统的cookie实现用户登录有缺陷就是很难实现跨域登录,目前流行的使用jwt (json web token)实现跨域登录。使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。
二、基于 Token 的身份验证方法
- 客户端使用用户名和密码请求登录,换token
- 服务端收到请求,验证账号密码正确后,生成token字符串附加到JSON返回客户端。
- 收到token后,将其保存到客户端(localStorage)备用。
- 客户端访问其他需要权限的接口时带上token去请求。(将token读取后附加到请求头上)
- 服务端收到请求,从请求头中解析token字符串,验证无误后,就向客户端返回请求的数据。
三、JWT
JWT是一种实施token验证的标准方法。读作:jot,表示:JSON Web Tokens。
一个JWT字符串由三部分构成:
1)header 部分,是一个固定格式的对象
2)payLoad部分(载体),是有开发者可以自定义的对象,一般将token的过期时间等信息存放在此处
3)signature 签名部分, 是由 header + payload + secret(密钥字符串) 通过指定的加密算法得来
中间用点分隔开,并且都会使用 Base64 编码,所以真正的 Token 看起来像这样:
Header
头部数据。里面包含了使用的算法,这个 JWT 是不是带签名的或者加密的。主要就是说明一下怎么处理这个 JWT token 。
Payload
Payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也可以添加其它需要的内容。
下面是标准字段:
- iss:Issuer,发行者
- sub:Subject,主题
- aud:Audience,观众
- exp:Expiration time,过期时间
- nbf:Not before
- iat:Issued at,发行时间
- jti:JWT ID
例如:
let payload =
{
name: "pjm",
exp: Date.now()
}
Signature
JWT 的最后一部分是 Signature ,这部分内容有三个部分,先是用 Base64 编码的 header.payload ,再用加密算法加密一下,加密的时候要放进去一个 Secret ,这个相当于是一个密码,这个密码秘密地存储在服务端。
let secret = "www.pjm.com"
最后这个在服务端生成并且要发送给客户端的 Token 看起来像这样:
let token = jwt.sign(payload, secret)
console.log(token);
客户端收到这个 Token 以后把它存储下来,下回向服务端发送请求的时候就带着这个 Token 。服务端收到这个 Token ,然后进行验证,通过以后就会返回给客户端想要的资源。
四、签发和验证JWT的功能
安装签发与验证 JWT 的功能包:
npm i jsonwebtoken
4.1签发 JWT
在项目里随便添加一个 .js 文件,比如 jwt.js,在文件里添加下面这些代码:
let jwt = require("jsonwebtoken");
//Token 数据 (签发的 token 里面要包含的一些数据。exp:过期时间:一天)
let payload =
{
name: "pjm",
exp: Date.now() + 1000 * 60 * 60 * 24
}
//密钥 (签发 token 用的密钥,在验证 token 的时候同样需要用到这个密钥。)
let secret = "www.pjm.com"
//签发Token
let token = jwt.sign(payload, secret)
//输出签发的Token
console.log(token);
非常简单,就是用了刚刚为项目安装的 jsonwebtoken 里面提供的 jwt.sign 功能,去签发一个 token。这个 sign 方法需要三个参数:playload、secret以及options(一些其它的选项。)
在终端,用 node jwt 命令执行文件,会输出签发的 token:
4.2验证 JWT
用 jwt.verify 这个方法去验证。这个方法是 Node.js 的 jsonwebtoken 这个包里提供的。
// 校验token字符串
jwt.verify(token, secret, function (err, decoded) {
if (!err) {
//如果校验成功,则返回一个payload对象
console.log("token校验对象");
console.log((decoded));
//再检查时间是否过期
if (decoded.exp > Date.now()) {
console.log(("还在有效期"));
} else {
console.log(("token已失效"));
}
} else {
console.log("token校验失败");
}
})
执行与输出: