JWTisaformoftoken.Itmainlyconsistsofthreeparts:header(header),payload(load),andsignature(signature).Thesethreepartsareconnectedby".".AcompleteJWTvalueis${header}.${payload}.${signature},例如下面使用"."进行连接的字符串:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMTEiLCJpYXQiOjE2MTQzMjU5NzksImV4cCI6MTYxNDMyNTk4MH0.iMjzC_jN3iwSpIyawy3kNRNlL1mBSEiXtOJqhIZmsl8headerheader最开始是一个JSON对象,该JSON包含alg和typ这两个属性,对JSON使用base64url(使用base64转码后Theencodingalgorithmforprocessingspecialcharacterswillbeintroducedindetaillater)Thestringobtainedafterencodingisthevalueoftheheader.{"alg":"HS256","typ":"JWT"}alg:signaturealgorithmtype,whichneedstobeusedwhengeneratingthesignaturepartinJWT,defaultHS256typ:currenttokentypepayloadpayloadisthesameasheader,anditisalsoaJSONatthebeginningObject,thestringencodedwithbase64urlisthefinalvalue.Thereare7officiallydefinedattributesstoredinthepayload,andwecanwritesomeadditionalinformation,suchasuserinformation,etc.iss:issuersub:subjectaud:audienceexp:expirationtimenbf:effectivetimeiat:issuancetimejti:numbersignaturesignaturewillusethesignaturealgorithmdefinedbythealgattributeintheheadertoencryptthestringcombinedwiththeheaderandpayload,andtheencryptionprocessThepseudocodeisasfollows:HMACSHA256(`${base64UrlEncode(header)}.${base64UrlEncode(payload)}`,secret)Thestringobtainedafterencryptionisthesignature.base64urlbase64编码后,字符串中会有+、/、=三个特殊字符,JWT可能通过url查询传输,url查询不能包含+、/,urlsafebase64规定+和/替换为-和_分别,和=会造成url查询的歧义,所以=需要删掉,这就是整个编码过程,代码如下/***节点环境*@desc编码过程*@param{any}data待编码内容*@return{string}编码值*/functionbase64UrlEncode(data){conststr=JSON.stringify(data);constbase64Data=Buffer.from(str).toString('base64');//+->-///->_//=->constbase64UrlData=base64Data.replace(/\+/g,'-').replace(/\//g,'_').replace(/\=/g,'');returnbase64UrlData;}服务在解析JWT内容时,需要对base64url编码的内容进行解码。首先是将-和_转换为+和/。base64转码后得到的字符串长度可以被4整除,base64编码的内容最后只会有=。我们看下解码过程:/***节点环境*@desc解码过程*@param{any}base64UrlData待解码内容*@return{string}解码后内容*/functionbase64UrlDecode(base64UrlData){//-->+//_->///使用=补码constbase64LackData=base64UrlData.replace(/\-/g,'+').replace(/\_/g,'/');constnum=4-base64LackData.length%4;constbase64Data=`${base64LackData}${'===='.slice(0,num)}`conststr=Buffer.from(base64Data,'base64').toString();让数据;尝试{data=JSON.parse(str);}catch(err){数据=str;}returndata;}JWT使用node中的jsonwebtoken插件快速开发JWT。本插件主要提供sign和verify两个功能,分别用于JWT的生成和验证。下面是JWT生成和验证函数的简单实现:)}`,secret)*@param{json}payload*@param{string}secret*@param{json}options*/constcrypto=require('crypto');functionsign(payload,secret){constheader={alg:'HS256',//这里只是走下流程,直接用HS256签名typ:'JWT',};constbase64Header=base64UrlEncode(header);constbase64Payload=base64UrlEncode(有效负载);constwaitCryptoStr=`${base64Header}.${base64Payload}`;constsignature=crypto.createHmac('sha256',secret).update(waitCryptoStr).digest('hex');return`${base64Header}.${base64Payload}.${signature}`;}/***@descJWT验证*jwt内容是否被篡改*jwt老化验证,exp和nbf*@param{string}jwt*@param{string}secret*/constcrypto=require('crypto');functionverify(jwt,secret){//jwt内容是否被篡改const[base64Header,base64Payload,oldSinature]=jwt.split('.');constnewSinature=crypto.createHmac('sha256',secret).update(`${base64Header}.${base64Payload}`).digest('hex');如果(newSinature!==oldSinature)返回false;constnow=Date.now();const{nbf=now,exp=now+1}=base64UrlDecode(base64Payload);//jwt有效性校验,大于等于有效时间,小于过期时间returnnow>=nbf&&now
