JWT基础概念
JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。基于token的身份验证可以替代传统的cookie+session身份验证方法。
代码来自网络,亲测有效,所以记录一下
JWT由三个部分组成:
header.payload.signature
header部分
该字段为json格式,alg字段指生成signature的算法,默认值为
HS256
,typ默认值为JWT
{"alg":"HS256","typ":"JWT"}
payload
该字段为json格式,表明用户身份的数据,可以根据业务需求自行定义
{"username":"admin",//该JWT的签发者"exp":1535974630,//过期时间,系统当前时间*}
signature部分:
签名算法,一般为HS256,其他的算法怎么整,具体长啥样儿我也不知道,没有找到,郁闷
jwt生成详解:
以加密方式为
HS256
为例
header进行base64UrlEncode加密后的字符串–字符串1
base64UrlEncode(header)
payload的内容进行base64UrlEncode加密后的字符串–字符串2
base64UrlEncode(payload)
字符串1+'.'+字符串2
拼接成一个新的字符串–字符串3
base64UrlEncode(header)+’.’+base64UrlEncode(payload)
通过header中的指定的算法来对字符串3 和一个密钥secret进行
HMacSHA256()
进行加密得到一个新的字符串就是jwt的主要内容
//java //HMACSHA256签名 https://jwt.io/introduction 中HMACSHAHMacSHA256(base64UrlEncode(header)+'.'+base64UrlEncode(payload)+ secret)
实现
python代码实现
主要是用pyjwt这个包来实现加解密
# pip3 install pyjwtimport jwt
import datetime
from jwt import exceptions
JWT_SALT ='ashlkdjfhoawhe;kfjnasdlkfjlasdhfoiuahsdvlajksnd'defcreate_token(payload, timeout=20):"""
:param payload: 例如:{'user_id':1,'username':'sinmu'}用户信息
:param timeout: token的过期时间,默认20s
:return:
"""
headers ={'typ':'jwt','alg':'HS256'}
payload['exp']= datetime.datetime.utcnow()+ datetime.timedelta(seconds=timeout)
tmp = jwt.encode(payload=payload, key=JWT_SALT, algorithm="HS256", headers=headers)
result = tmp.encode('utf-8')return result
defparse_payload(token):"""
对token进行和发行校验并获取payload
:param token:
:return:
"""
result ={'status':False,'data':None,'error':None}try:
verified_payload = jwt.decode(token, JWT_SALT, algorithms="HS256")
result['status']=True
result['data']= verified_payload
except exceptions.ExpiredSignatureError:
result['error']='token已失效'except jwt.DecodeError:
result['error']='token认证失败'except jwt.InvalidTokenError:
result['error']='非法的token'return result
if __name__ =='__main__':
token = create_token({'uid':1,'username':'sinmu'},3).decode('utf-8')
res = parse_payload(token)print(res)
Java实现jwt
import io.jsonwebtoken.*;import java.util.Date;publicclassJwtUtils{privatelong expire=7200;private String secret="dwhidhkwhdkdiwhd232323dwdadwdw2a";private String header="Authorization";// 生成jwtpublic String generateToken(String username){
Date nowDate =newDate();
Date expireDate =newDate(nowDate.getTime()+1000* expire);return Jwts.builder().setHeaderParam("typ","JWT").setSubject(username).setIssuedAt(nowDate).setExpiration(expireDate)// 两小时过期.signWith(SignatureAlgorithm.HS512, secret).compact();}// 解析jwtpublic Claims getClaimByToken(String jwt){try{return Jwts.parser().setSigningKey(secret).parseClaimsJws(jwt).getBody();}catch(Exception e){return null;}}// jwt是否过期publicbooleanisTokenExpired(Claims claims){return claims.getExpiration().before(newDate());}}
PHP实现JWT
<?php/**
* PHP实现jwt
*/classJwt{//头部privatestatic$header=array('alg'=>'HS256',//生成signature的算法'typ'=>'JWT'//类型);//使用HMAC生成信息摘要时所使用的密钥privatestatic$key='123456';/**
* 获取jwt token
* @param array $payload jwt载荷 格式如下非必须
* [
* 'iss'=>'jwt_admin', //该JWT的签发者
* 'iat'=>time(), //签发时间
* 'exp'=>time()+7200, //过期时间
* 'nbf'=>time()+60, //该时间之前不接收处理该Token
* 'sub'=>'www.admin.com', //面向的用户
* 'jti'=>md5(uniqid('JWT').time()) //该Token唯一标识
* ]
* @return bool|string
*/publicstaticfunctiongetToken(array$payload){if(is_array($payload)){$base64header=self::base64UrlEncode(json_encode(self::$header,JSON_UNESCAPED_UNICODE));$base64payload=self::base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE));$token=$base64header.'.'.$base64payload.'.'.self::signature($base64header.'.'.$base64payload,self::$key,self::$header['alg']);return$token;}else{returnfalse;}}/**
* 验证token是否有效,默认验证exp,nbf,iat时间
* @param string $Token 需要验证的token
* @return bool|string
*/publicstaticfunctionverifyToken(string $Token){$tokens=explode('.',$Token);if(count($tokens)!=3)returnfalse;list($base64header,$base64payload,$sign)=$tokens;//获取jwt算法$base64decodeheader=json_decode(self::base64UrlDecode($base64header),JSON_OBJECT_AS_ARRAY);if(empty($base64decodeheader['alg']))returnfalse;//签名验证if(self::signature($base64header.'.'.$base64payload, self::$key,$base64decodeheader['alg'])!==$sign)returnfalse;$payload=json_decode(self::base64UrlDecode($base64payload),JSON_OBJECT_AS_ARRAY);//签发时间大于当前服务器时间验证失败if(isset($payload['iat'])&&$payload['iat']>time())returnfalse;//过期时间小宇当前服务器时间验证失败if(isset($payload['exp'])&&$payload['exp']<time())returnfalse;//该nbf时间之前不接收处理该Tokenif(isset($payload['nbf'])&&$payload['nbf']>time())returnfalse;return$payload;}/**
* base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现
* @param string $input 需要编码的字符串
* @return string
*/privatestaticfunctionbase64UrlEncode(string $input){returnstr_replace('=','',strtr(base64_encode($input),'+/','-_'));}/**
* base64UrlEncode https://jwt.io/ 中base64UrlEncode解码实现
* @param string $input 需要解码的字符串
* @return bool|string
*/privatestaticfunctionbase64UrlDecode(string $input){$remainder=strlen($input)%4;if($remainder){$addlen=4-$remainder;$input.=str_repeat('=',$addlen);}returnbase64_decode(strtr($input,'-_','+/'));}/**
* HMACSHA256签名 https://jwt.io/ 中HMACSHA256签名实现
* @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
* @param string $key
* @param string $alg 算法方式
* @return mixed
*/privatestaticfunctionsignature(string $input, string $key, string $alg='HS256'){$alg_config=array('HS256'=>'sha256');# HS256=> HASH_HMAC(SHA256,string,secret,true)return self::base64UrlEncode(hash_hmac($alg_config[$alg],$input,$key,true));}}//测试和官网是否匹配begin$payload=array('uid'=>1,'name'=>'sinmu','iat'=>1516239022);$jwt=newJwt;$token=$jwt->getToken($payload);echo"<pre>";echo$token;//对token进行验证签名$getPayload=$jwt->verifyToken($token);echo"<br><br>";var_dump($getPayload);echo"<br><br>";//测试和官网是否匹配end//自己使用测试begin$payload_test=array('iss'=>'admin','iat'=>time(),'exp'=>time()+7200,'nbf'=>time(),'sub'=>'www.admin.com','jti'=>md5(uniqid('JWT').time()));;$token_test=Jwt::getToken($payload_test);echo"<pre>";echo$token_test;//对token进行验证签名$getPayload_test=Jwt::verifyToken($token_test);echo"<br><br>";var_dump($getPayload_test);echo"<br><br>";//自己使用时候end
版权归原作者 SinMu-L 所有, 如有侵权,请联系我们删除。