//jwt 令牌 import JSON; import crypt.hmac; import crypt.rsa; import crypt.bin; namespace crypt class jwt{ ctor(key,expiresIn){ this.key = key;//@Deprecated this.expiresIn = expiresIn;//@Deprecated }; encode = function(data,key,algorithm){ if(this.expiresIn && data.exp===null){ data.exp = tonumber(..time().addsecond(this.expiresIn)); } return encode(data,key||this.key,algorithm); }; decode = function(token,key,algorithm){ return decode(token,key,algorithm)); }; verify = function(token,key,algorithm){ return decode(token,key||this.key,algorithm); }; sign = this.encode; } namespace jwt{ encode = function(data,key,algorithm){ data.iat = tonumber(data.iat || ..time()); if(algorithm === null) algorithm = "HS256"; var header = ..crypt.bin.encodeUrlBase64(`{"alg":"`+algorithm+`","typ":"JWT"}`); var payload = ..crypt.bin.encodeUrlBase64( ..JSON.stringify(data) ); var sign; if(algorithm == "HS256"){ sign = ..crypt.hmac.sha256(key,header + "." + payload).getValue(); sign = ..crypt.bin.encodeUrlBase64(sign); } elseif(algorithm == "RS256"){ var rsa = ..crypt.rsa(); rsa.importPemKey(key); rsa.createHashBySha256(header + "." + payload); sign = rsa.signToUrlBase64();//注意这里有自动反转字节序 rsa.release(); } elseif(algorithm == "none"){ sign = ""; } return ..string.format("%s.%s.%s",header,payload,sign); }; decode = function(token,key,algorithm){ token = ..string.match(token,"[Bb]earer\s+(\S+)") : token; if(algorithm === null) algorithm = "HS256"; if(key){ var jwt = ..string.split(token,".",3); var header = ..JSON.tryParse(..crypt.bin.decodeUrlBase64(jwt[1])); var alg = header[["alg"]]; if(alg!=algorithm) return; if(alg==="HS256") { var sign = ..crypt.hmac.sha256(key,jwt[1] + "." + jwt[2]).getValue() ; //注意 encodeUrlBase64 会自动反转字节序 if( jwt[3] !== ..crypt.bin.encodeUrlBase64(sign) ){ return; } } elseif(alg==="RS256") { var rsa = ..crypt.rsa(); rsa.importPemKey(key); rsa.createHashBySha256(jwt[1] + "." + jwt[2]); if( ! rsa.verifyFromUrlBase64(jwt[3]) ) return; } elseif(alg==="none") { } else{ error("不支持该算法",2); } } var jwt = ..string.split(token,".",3); if(#jwt==3){ var ret = { header = ..JSON.parse(..crypt.bin.decodeBase64(jwt[1])); payload = ..JSON.parse(..crypt.bin.decodeBase64(jwt[2])); sign = ..crypt.bin.decodeBase64(jwt[3]); } if(ret.payload[["exp"]]){ ret.payload[["exp"]] = ..time(ret.payload[["exp"]]) if( key && ret.payload[["exp"]] <= ..time() ){ return; } } if(ret.payload[["iat"]]){ ret.payload[["iat"]] = ..time(ret.payload[["iat"]]) } if(ret.payload[["nbf"]]){ ret.payload[["nbf"]] = ..time(ret.payload[["iat"]]) } return ret; } }; sign = encode;//@Deprecated verify = decode;//@Deprecated } /**intellisense() crypt.jwt = JSON Web Token 令牌 crypt.jwt.decode( = 解码并返回令牌信息 crypt.jwt.decode(.(token,key,algorithm) = 验证签名,失败返回 null。\n成功则解码并获取令牌记录的 JSON 数据,\n然后对 JSON 进行解析并返回解码后的对象。\n\n参数 @key 指定密钥或 PEM 格式公钥。\n可选用参数 @algorithm 指定签名算法,默认为 "HS256",\n也可指定为 "RS256" 或 "none",算法为 "none" 则 @key 可指定空字符串。\n暂不支持其他算法。 crypt.jwt.decode(.(token) = 不验证签名,直接解码并返回令牌信息 crypt.jwt.encode( = 生成 JWT 令牌。 crypt.jwt.encode(.(data,key,algorithm) = 生成令牌,\n参数 @data 指定要存储到客户端的数据(必须是一个表对象)\n参数 @key 指定密钥或 PEM 格式私钥。\n可选用参数 @algorithm 指定签名算法,默认为 "HS256",\n也可指定为 "RS256" 或 "none",算法为 "none" 则 @key 可指定空字符串。\n暂不支持其他算法。 end intellisense**/