NodeJS中的token

JWT

1、Token

  • 什么是Token?web

    Token指访问资源的凭据,是一种身份认证的方式,它是解决跨域认证的最流行的一种方式。算法

  • 为何用Token?数据库

    之前较为流行的是经过session去作身份认证,session是经过服务器中保存会话数据来作身份认证,这种方式会致使在高并发中服务器压力过大的状况,还有就是,若是是服务器集群,那么就须要这些服务器session共享。express

    Token不在服务器中保存会话数据,而是保存在客户端。每次请求的headers中存入Token,在服务器中判断Token的有效性,是否能够访问资源。npm

  • 传统Token和JWT的区别json

    • 传统Tokenapi

      用户发起登陆请求,登陆成功以后返回Token,而且存于数据库,用户访问资源的时候须要携带Token,服务端获取Token以后和数据库中的对比。跨域

    • JWTbash

      用户发起登陆请求,登陆成功以后返回Token,可是不存于数据库,用户访问资源的时候须要携带Token,服务端获取Token以后去校验Token的合法性。服务器

2、JWT实现过程

  • JWT分为三个部分header、payload、verify signature

  • header

    内部包含有签名算法、Token类型,而后经过base64url算法转成字符串

    //明文例子:
    {
        "alg":"HS256",
        "typ":"JWT"
    }
    复制代码
  • payload

    内部包含JWT标准数据和自定义数据,而后经过base64url算法转成字符串

    JWT标准数据常见的有:

    • iss:提供方。
    • sub:主题,通常是用户ID。
    • exp:过时时间。
    • iat:建立时间。
    • jti:token的惟一标识。

    可选择性使用以上标准数据

    //明文例子:
    {
      "id": 3,
      "name": "Bmongo",
      "age": 18,
      "iat": 1588139323,
      "exp": 1588139333
    }
    复制代码

    注意:因为JWT是默认不加密的,因此在这边不要存敏感信息

  • verify signature

    这部分是对前两部分的签名,防止数据的篡改

    secret是服务器端保存的密钥,只有服务器端知道,再使用header中所指定的签名算法对上面的俩部分进行签名,按照如下公式生成签名

    HMACSHA256(
        base64UrlEncode(header) + "." +
        base64UrlEncode(payload),
        secret
    )
    复制代码

    算出签名以后,把三部分经过.分隔开返回给用户就好了

    JWT例子:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTAsIm5hbWUiOiLlvKDkuIkiLCJhZ2UiOjE2LCJpYXQiOjE1ODgxMzkzMjMsImV4cCI6MTU4ODEzOTMzM30.WzZp_aNgiw4iTsX7buxMhZe0z0e94Ve6ImEZ8L8L78c
    复制代码
  • 客户端请求

    每次客户端的请求都须要带上这个token,通常是把token写入到请求的headers中

3、Node.js中使用

Node.js中使用JWT

1.开始使用

经过npm包jsonwebtoken来完成token的生成和验证

npm install --save jsonwebtoken
复制代码
2.生成、验证Token
const jwt = require("jsonwebtoken")
//撒盐,加密时候混淆
const secret = '113Bmongojsdalkfnxcvmas'

//生成token
//info也就是payload是须要存入token的信息
function createToken(info) {
	let token = jwt.sign(info, secret, {
        //Token有效时间 单位s
		expiresIn:60 * 60 * 10
	})
	return token
}

//验证Token
function verifyToken(token) {
	return new Promise((resolve, reject) => {
		jwt.verify(token, secret, (error, result) => {
            if(error){
                reject(error)
            } else {
                resolve(result)
            }
		})
	})
}
复制代码
3.使用
const express = require("express")
const app = express()
const jwt = require("jsonwebtoken")
//撒盐,加密时候混淆
const secret = '113Bmongojsdalkfnxcvmas'
const user = {
	id:10,
	name:"Bmongo",
	age:16,
}

//生成token
//info也就是payload是须要存入token的信息
function createToken(info) {
	let token = jwt.sign(info, secret, {
        //Token有效时间 单位s
		expiresIn:60 * 60 * 10
	})
	return token
}

//验证Token
function verifyToken(token) {
	return new Promise((resolve, reject) => {
		jwt.verify(token, secret, (error, result) => {
            if(error){
                reject(error)
            } else {
                resolve(result)
            }
		})
	})
}

//设置容许跨域
app.use(function(req, res, next) {
    //指定容许其余域名访问 *全部
	res.setHeader("Access-Control-Allow-Origin", "*");
    //容许客户端请求头中带有的
	res.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
    //容许请求的类型
	res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
	res.setHeader("X-Powered-By",' 3.2.1')
    //让options请求快速返回
	if(req.method=="OPTIONS") res.send(200);
	else  next();
});

//白名单
const whiteList = ['/login']

app.use((req,res,next) => {
	if(!whiteList.includes(req.url)) {
		verifyToken(req.headers.authorization).then(res => {
			next()
		}).catch(e => {
			res.status(401).send('invalid token')
		})
	} else {
		next()
	}
})

app.post('/login',(req,res) => {
	let token = createToken(user)
	res.json({token})
})

app.get("/api/info", (req,res) => {
	res.send({
		result:1,
		data:{
            "name":"Bmongo",
            "id":1
        }
	})
})
复制代码
相关文章
相关标签/搜索