JWT原理 和 tp5使用例子

1.理论 和 简介

1.1  简介

一种客户端 和 服务端的认证机制,让后台知道请求是来自于受信的客户端。

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT是由三段信息构成的,将这三段信息文本用  . 链接一起就构成了Jwt字符串。就像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

这三段分别是:

  1. header   头部   ,默认是加密方式是  HS256
  2. playload   载荷  ,放官方字段  ,过期时间 ,私有字段等
  3. signature   签名

头部和载荷都是  通过base64 加密编码而成 , 目的是方便网络传输,减少出错

众所周知base64 是可以解密的,所以一些 诸如密码或银行账户的 敏感的信息尽量不要放在  playload 中传输 

由于现在很多项目都是前后端分离,restful api模式 , 可以说 restful api认证是jwt的一个很好的应用场景

1.2 安全相关

  1. 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。
  2. 保护好secret私钥,该私钥非常重要。
  3. 如果可以,请使用https协议

1.3 JWT 应用流程

1.4 项目github地址

https://github.com/pandamf0079/tptoken

2. 官网 和 资源下载方式

官网: JSON Web Token Introduction - jwt.io

官网中有各种语言的 github demo连接 ,现在我们使用的是

firebase/php-jwt

3. tp5中使用jwt例子

默认使用HS256 加密的方式 ,首先使用composer安装好依赖

composer require firebase/php-jwt
composer require firebase/php-jwt:"v6.0"
  • 通过用户名和密码来授权中心获得token
  • 将token保存在cookie中,返回到客户端
  • 下次请求携带cookie发送到服务器,服务器解析出用户信息

服务端模型:

namespace app\index\model;

use think\Model;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT as JWTUtil;
use Firebase\JWT\Key;
class User extends Model
{

	protected $jwt_secret_key = '123Abc#$';
	protected $jwt_expire_time = 10;
	
	public   function findUser($username,$pass){
		if($username=='dapeng' && $pass=='123456'){
			return ['user_id'=>10,'username'=>'dapeng','sex'=>1];
		}
	}
	
	public  function createToken($user=[],$exptime=0,$alg='HS256'){
		$key = $this->jwt_secret_key;
		$time = time();
		$expire = $exptime==0?$time+$this->jwt_expire_time:$time+$exptime;
		$payload = [
			$user,
			"iss"=>"PengCompany",
			"aud"=>"dapeng",
			"iat"=>$time,
			"nbf"=>$time,
			"exp"=>$expire
		];
		
		$jwt = JWTUtil::encode($payload,$key,$alg);
		return $jwt; 
	}
	
	
	public function verifyToken($token){
		$key = $this->jwt_secret_key;
		try{
			$jwtAuth = json_encode(JWTUtil::decode($token,new Key($key, 'HS256')));
			$authInfo = json_decode($jwtAuth,true);
			return ['msg'=>'token正常','status'=>1,'data'=>$authInfo[0]];
		}catch(ExpiredException $e){
			return ['msg'=>'token expire','status'=>2,'data'=>[]];
		}catch(\Exception $e){
			return ['msg'=>'token error','status'=>3,'data'=>[$e->getMessage()]];
		}
		
	}
}

需要注意的是过期时间exp 是时间戳,设置在payload里

控制器方法:

public function login(Request $request){
		/*['user_id'=>10,'username'=>'dapeng','sex'=>1]*/
		$username = $request->param('user');
		$pass = $request->param('pass');
		if($username!='' && $pass!=''){
			//数据库查询
			$userModel = new User();
			$users = $userModel->findUser($username,$pass);
			$token = $userModel->createToken($users,3600);
			Cookie::set('jwt',$token,3600);
			$this->success('登录成功','/ucenter');
			//return $token;
			
		}else{
			$this->error('用户名密码不能为空');
		}
	}
	
	
	public function getinfo(Request $request){
		
		$header = Request::instance()->header();
		if ($header['authorization'] == 'null'){
			echo json_encode([
                'status' => 1002,
                'msg' => 'token不存在,拒绝访问'
            ]);
            exit;
		}else{
			
			$userModel = new User();
			echo json_encode($userModel->verifyToken($header['authorization']));
			exit();
		}
		
	}

接收头部 authorization 的token  并认证

客户端:

<script>
$(document).ready(function(){
	var token = getCookie('jwt');
	//alert(token);
	$.ajax({
		url:'http://www.pengcms.com/getinfo',
		type:'POST',
		headers:{
			'Authorization':token
		},
		dataType: "json",
		success:function(res) {
			//console.log(res);
			var sex ='';
		  	$("#id1").html(res.data.user_id);
			$("#id2").html(res.data.username);
			if(res.data.sex==1){
				sex = '男';
			}else{
				sex = '女';
			}
			$("#id3").html(sex);
		}
	});
			
})

function getCookie(name)
{
	var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
	if(arr=document.cookie.match(reg))
		return unescape(arr[2]);
	else
		return null;
}

取cookie ,发送到服务端认证。

4. tp5中使用jwt例子 (使用RS256  openssl)

使用openssl工具:

openssl>  genrsa -out rsa_private_key.pem 1024
openssl>  rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

和上面不同的是模型层不一样

	public  function createToken($user=[],$exptime=0,$alg='RS256'){
		$private_key = file_get_contents("./keys/rsa_private_key.pem");
		if(openssl_pkey_get_private($private_key)){
			$time = time();
			$expire = $exptime==0?$time+$this->jwt_expire_time:$time+$exptime;
			$payload = [
				$user,
				"iss"=>"PengCompany",//签发组织
				"aud"=>"dapeng",//签发作者
				"iat"=>$time,
				"nbf"=>$time,
				"exp"=>$expire
			];
			//设置过期时间
			//JWTUtil::$leeway = 10;
			$jwt = JWTUtil::encode($payload,$private_key,$alg);
			return $jwt;
			 
		}else{
			return false;
		}
	
	}
	
	
	public function verifyToken($token){
		$public_key = file_get_contents("./keys/rsa_public_key.pem");
		try{
			$jwtAuth = json_encode(JWTUtil::decode($token,new Key($public_key, 'RS256')));
			$authInfo = json_decode($jwtAuth,true);
			return ['msg'=>'token正常','status'=>1,'data'=>$authInfo[0]];
		}catch(ExpiredException $e){
			return ['msg'=>'token expire','status'=>2,'data'=>[]];
		}catch(\Exception $e){
			return ['msg'=>'token error','status'=>3,'data'=>[$e->getMessage()]];
		}
		
	}

5.参考

git地址:https://github.com/firebase/php-jwt

原理:什么是 JWT -- JSON WEB TOKEN - 简书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿John

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值