您的位置:

Token生成算法详解

一、生成Token算法

Token(令牌)生成是一种验证用户身份的方法,通常用于保证API接口的安全性。Token生成算法可以采用多种方式,其中JWT(Json Web Token)是广泛使用的一种。

二、Token生成

Token生成通常分为以下两个步骤:

1、生成一个含有必要信息的JSON对象,如用户id、用户名以及过期时间等。

{
  "userId": "123456",
  "username": "john",
  "exp": 1627074891
}

2、将JSON对象进行签名,生成最终的Token字符串,如下所示:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTYiLCJ1c2VybmFtZSI6ImpvaG4iLCJleHAiOjE2MjcwNzQ4OTF9.kSuq7xyQbUXZQNP3AnXlcZxTtCMVJHJGUJQjcBOpP8M

Token中包含了头部、载荷和签名三部分。其中,头部指定了签名算法,载荷包含了必要信息,签名通过头部和载荷计算而来。

三、生成算法的步骤是

1、将头部和载荷进行Base64编码,并将编码后的字符串用"."连接起来,形成一个未签名的Token字符串。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTYiLCJ1c2VybmFtZSI6ImpvaG4iLCJleHAiOjE2MjcwNzQ4OTF9

2、使用密钥对未签名的Token字符串进行签名。签名算法可以采用HMAC-SHA256等。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

3、将签名结果用"."连接到未签名的Token字符串后面,形成最终的Token字符串。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTYiLCJ1c2VybmFtZSI6ImpvaG4iLCJleHAiOjE2MjcwNzQ4OTF9.kSuq7xyQbUXZQNP3AnXlcZxTtCMVJHJGUJQjcBOpP8M

四、服务端Token生成算法

服务端Token生成算法通常采用JWT。

在实现服务端Token生成算法时,需要定义Token的有效期、密钥以及加密方式等参数,如下所示:

const jwt = require('jsonwebtoken')
const secret = 'my_secret_key'
const expiresIn = '2h'

function generateToken(payload) {
  const token = jwt.sign(payload, secret, { expiresIn })
  return token
}

以上实现了一个简单的Token生成方法,通过传递payload参数即可生成Token字符串。

五、登录Token生成算法

登录Token生成算法是指在用户登录成功后,生成一个Token用于验证用户身份。

登录Token生成算法通常包含以下步骤:

1、验证用户身份,验证成功后生成一个JSON对象,包含用户id、用户名以及过期时间等信息。

const user = {
  userId: '123456',
  username: 'john',
  exp: Math.floor(Date.now() / 1000) + (60 * 60)
}

2、将JSON对象转换成Token字符串,并返回给客户端。

const token = generateToken(user)
res.json({token})

六、随机数生成算法

随机数生成算法通常用于生成密钥、盐以及Token中的nonce等。

Node.js内置了crypto模块,提供了丰富的加密算法以及随机数生成方法,如下所示:

const crypto = require('crypto')
const secret = crypto.randomBytes(16).toString('hex')

以上代码使用了crypto.randomBytes方法生成了一个16字节的随机数,并将其转换成了hex字符串。

七、登录令牌Token生成算法

登录令牌Token生成算法可以用于生成用于用户身份验证的Token。

通常采用JWT方式实现,以服务端生成的令牌为例,其生成方法可如下:

const jwt = require('jsonwebtoken')
const secret = 'my_secret_key'
const expiresIn = '30d'

function generateLoginToken(user) {
  const payload = {
    subject: user.id,
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24 * 30),
    alg: 'HS256'
  }
  const options = {
    expiresIn: expiresIn
  }
  const token = jwt.sign(payload, secret, options)
  return token
}

八、Token生成原理

Token生成原理是采用了JWT规范,由头部、载荷以及签名三部分构成,经过base64编码形成Token字符串。

其中,Payload中保存了用户信息、过期时间等数据,用于验证用户身份。

签名则是通过加密算法将头部和载荷计算出的签名值,用于保证Token在传输过程中不被篡改。

九、Token签名算法

Token签名算法通常采用HMAC-SHA256等加密算法,用于对Token进行加密。

const crypto = require('crypto')

function sign(payload, secret) {
  const header = {
    alg: 'HS256',
    typ: 'JWT'
  }
  const encodingHeader = base64UrlEncode(JSON.stringify(header))
  const encodingPayload = base64UrlEncode(JSON.stringify(payload))
  const signature = crypto.createHmac('sha256', secret).update(encodingHeader + "." + encodingPayload).digest('base64')
  return encodingHeader + '.' + encodingPayload + '.' + signature
}

以上代码演示了如何使用HMAC-SHA256算法对Token进行签名。

十、Token加密算法

Token加密算法通常采用AES等算法,用于保证Token在传输中的安全性。

const crypto = require('crypto')

function encrypt(text, secret) {
  const iv = crypto.randomBytes(16)
  const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(secret), iv)
  let encrypted = cipher.update(text)
  encrypted = Buffer.concat([encrypted, cipher.final()])
  return iv.toString('hex') + ':' + encrypted.toString('hex')
}

function decrypt(text, secret) {
  const parts = text.split(':')
  const iv = Buffer.from(parts[0], 'hex')
  const encryptedText = Buffer.from(parts[1], 'hex')
  const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(secret), iv)
  let decrypted = decipher.update(encryptedText)
  decrypted = Buffer.concat([decrypted, decipher.final()])
  return decrypted.toString()
}

以上代码实现了AES加密算法的加密和解密方法。