美文网首页
NodeJS中使用token

NodeJS中使用token

作者: BingJS | 来源:发表于2022-06-23 15:24 被阅读0次

JWT(Json Web Token)

1. Token

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

为什么用Token?
以前较为流行的是通过session去做身份认证,session是通过服务器中保存会话数据来做身份认证,这种方式会导致在高并发中服务器压力过大的情况,还有就是,如果是服务器集群,那么就需要这些服务器session共享。
Token不在服务器中保存会话数据,而是保存在客户端。每次请求的headers中存入Token,在服务器中判断Token的有效性,是否可以访问资源。

传统Token和JWT的区别

  1. 传统Token
    用户发起登录请求,登录成功之后返回Token,并且存于数据库,用户访问资源的时候需要携带Token,服务端获取Token之后和数据库中的对比。
  2. JWT
    用户发起登录请求,登录成功之后返回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
)

算出签名之后,把三部分通过.分隔开返回给用户就行了
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTAsIm5hbWUiOiLlvKDkuIkiLCJhZ2UiOjE2LCJpYXQiOjE1ODgxMzkzMjMsImV4cCI6MTU4ODEzOTMzM30.WzZp_aNgiw4iTsX7buxMhZe0z0e94Ve6ImEZ8L8L78c

客户端请求

每次客户端的请求都需要带上这个token,一般是把token写入到请求的headers中

3. Node.js中使用

开始使用

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

npm install --save jsonwebtoken

生成、验证Token

const jwt = require("jsonwebtoken")
//撒盐,加密时候混淆
const secret = '123bingjspoiuytrewqlkjhgfdsa'

//生成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)
            }
        })
    })
}

使用

const express = require("express")
const app = express()
const jwt = require("jsonwebtoken")
//撒盐,加密时候混淆
const secret = '123bingjspoiuytrewqlkjhgfdsa'
const user = {
    id:10,
    name:"Bing",
    age:18,
}

//生成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}
    })
})

相关文章

网友评论

      本文标题:NodeJS中使用token

      本文链接:https://www.haomeiwen.com/subject/fdpuvrtx.html