Token && WebJsonTaken详解
一、Token原理及使用
1、Token的概念:
Token是服务端生成的一个字符串,是客户端生成的一个标识,作为客户端进行请求的一个令牌。当第一次登录后,服务器生成的Token会返回给客户端,之后客户端只需带上这个标识去请求数据就可以了,不需要再次带上用户名和密码。
2、Token作用:
生成Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
3、Token的使用:
在这里我主要分析基于登录的过程中的Token使用,归纳如下:
(1)用户未登录时侯,访问客户端A,客户端A的服务器检测到用户没登录(通过cookie判断没传过来session对应cookie),就去通知浏览器跳转到SSO服务站点,并在跳转的URL参数中带上当前页面的url,以便登录后自动跳转回本页。
(2) SSO服务站点检测到用户没有登录,于是显示登录界面,用户提交登录请求到服务端,服务端验证通过,创建和账号对应的用户登录凭据(token),然后服务端通知浏览器把该token作为SSO服务站点的cookie存储起来,并跳转回客户端A,跳回客户端A的URL参数中会带上这个token。
(3) 浏览器在写SSO服务站点cookie后,跳转回客户端A。客户端A服务端检测到浏览器请求的URL中带了站点登录的token,于是把这个token发到SSO服务站点验证。SSO服务端站点拿token,解密出用户账号,把账号信息中允许客户端A访问的部分返回给客户端A。客户端A根据返回的信息生成用户在本站的会话,把会话对应的cookie写入浏览器,从而完成在本站的登入以及会话保持。之后用户再次访问客户端A时,都会带上这个cookie,从而保持在本站的登录状态。
(4)假设用户再访问客户端B,客户端B服务器检测到用户没登录,于是通知浏览器跳转到SSO服务站点。
(5)浏览器访问SSO服务站点时会带上之前创建的token这个cookie,然后SSO服务站点会根据该token,找到对应用户。然后通知浏览器跳转到客户端B,并在跳转回去的URL参数中带上这个token。
(6)客户端B服务端检测到浏览器请求的URL中带上了站点登录的token,于是又会走上述的步骤,完成用户在本站的自动登录。
以上就是token在前端登录过程中的整个大致经过;
二、JsonWebToken
1、JWT的概述
服务器认证以后,生成一个 JSON 对象,返回给用户,就像下面这种格式。
{
"姓名": "mike",
"角色": "管理员",
"到期时间": "2018年7月1日0点0分"
}
之后所有的用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名;
2、JWT的组成部分
JsonWebToken的主要是由Header(头部)、PayLoad(负载)、Signature(签名)这三部分组成。
Header.Payload.Signature
(1)Header
header是一个json对象,主要由2部分组成,一个是token的类型,一个是使用的算法
{
type:"jwt", //typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。
alg:"HS256" //alg属性表示签名的算法(algorithm),默认是 HMAC SHA256;
}
(2)PayLoad
Payload 部分也是一个 JSON 对象,它是用来存放实际需要传递的数据。JWT 官方规定了7个字段,归纳如下:
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
当然,上述只是官方定义的,我们自己也可以定义自己的私有字段,定义格式如下:
{
iss:"admin",
user:'alley',
}
**注:**JWT默认是不加密的,任何人都可以读到,所以不要把私密信息放入这个部分。
(3)Signature
Signature 是对之前两个组成部分的签名,主要是为了防止数据篡改。
(1)需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。
(2)使用 Header 里面指定的签名算法(默认是 HMAC SHA256),它是按照如下格式产生签名:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.
)分隔,就可以返回给用户。
类似这样:
Header.Payload.Signature
3、JWT的使用
以下是基于EXpress的使用方法:
const jwt = require("jsonwebtoken");
const secret = "secret";//签名
const getCookie = (key)=>{
const cookies = req.headers.cookie;
const arr = cookies.split("; ");
for(var i=0;i<arr.length;i++){
let newArr = arr[i].split("=");
if(newArr[0] == key){
return newArr[1];
}
}
}
//验证token
const verifyTokenMiddle = (req,res,next)=>{
let token = getCookie("token");
jwt.verify(token, scret, function(err, decoded) {
if(err){
return res.json({
state:false,
info:"token验证失败"
})
}
next()
});
}
//创建token
const createToken = (username)=>{
const payload = {
user:username
}
return jwt.sign(payload, secret,{expiresIn:'1h'});
}
module.exports = {
createToken,
verifyTokenMiddle
}