什么是Token?

在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般我们所说的的token大多是指用于身份验证的token

Token的特点

  • 随机性
  • 不可预测性
  • 时效性
  • 无状态、可扩展

基于Token的身份验证方法

  • 客户端使用用户名和密码请求登录
  • 服务端收到请求,验证登录是否成功
  • 验证成功后,服务端会返回一个Token给客户端,反之,返回身份验证失败的信息
  • 客户端收到Token后把Token用一种方式(cookie/localstorage/sessionstorage/其他)存储起来
  • 客户端每次发起请求时都选哦将Token发给服务端
  • 服务端收到请求后,验证Token的合法性,合法就返回客户端所需数据,反之,返回验证失败的信息

JWT(Json Web Tokens)

生成Token的解决方案有许多,常用的一种就是 ​Json Web Tokens​ .

JWT标准的Tokens由三部分组成

  1. header
  2. payload
  3. signature

中间使用 " . " 分隔开,并且都会使用Base64编码方式编码,如下

eyJhbGc6IkpXVCJ9.eyJpc3MiOiJCIsImVzg5NTU0NDUiLCJuYW1lnVlfQ.SwyHTf8AqKYMAJc


header

header 部分主要是两部分内容,一个是 Token 的类型,另一个是使用的算法,比如下面类型就是 JWT,使用的算法是 Hash256。

{
"typ": "JWT",
"alg": "HS256"
}


payload

Payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也可以添加其它需要的内容。下面是标准字段:

  • iss:Issuer,发行者
  • sub:Subject,主题
  • aud:Audience,观众
  • exp:Expiration time,过期时间
  • nbf:Not before
  • iat:Issued at,发行时间
  • jti:JWT ID

比如下面

{
"iss": "ninghao.net",
"exp": "1438955445",
"name": "wanghao",
"admin": true
}d


signature

JWT 的最后一部分是 Signature ,这部分内容有三个部分,先是拼接 Base64 编码的 header.payload ,再用不可逆的Hamc加密算法加密,加密时使用一个密钥,这个密钥服务端保存,生成signature。

最后组合token,如下

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.
SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

客户端收到这个 Token 以后把它存储下来,下回向服务端发送请求的时候就带着这个 Token 。服务端收到这个 Token ,然后进行验证,通过以后就会返回给客户端想要的资源。

Nodejs实现

token.js
var crypto=require("crypto");
var token={
createToken:function(obj,timeout){
console.log(parseInt(timeout)||0);
var obj2={
data:obj,//payload
created:parseInt(Date.now()/1000),//token生成的时间的,单位秒
exp:parseInt(timeout)||10//token有效期
};

//payload信息
var base64Str=Buffer.from(JSON.stringify(obj2),"utf8").toString("base64");

//添加签名,防篡改
var secret="hel.h-five.com";
var hash=crypto.createHmac('sha256',secret);
hash.update(base64Str);
var signature=hash.digest('base64');


return base64Str+"."+signature;
},
decodeToken:function(token){

var decArr=token.split(".");
if(decArr.length<2){
//token不合法
return false;
}

var payload={};
//将payload json字符串 解析为对象
try{
payload=JSON.parse(Buffer.from(decArr[0],"base64").toString("utf8"));
}catch(e){
return false;
}

//检验签名
var secret="hel.h-five.com";
var hash=crypto.createHmac('sha256',secret);
hash.update(decArr[0]);
var checkSignature=hash.digest('base64');

return {
payload:payload,
signature:decArr[1],
checkSignature:checkSignature
}
},
checkToken:function(token){
var resDecode=this.decodeToken(token);
if(!resDecode){

return false;
}