Thikphp 5.1 JSON Web Token Cross-domain Authentication Solution

Keywords: JSON Attribute PHP

For more information on JSON Web Token

The client receives the JWT returned by the server and stores it in Cookie or localStorage.
Thereafter, the client will bring JWT in the interaction with the server. If you store it in a Cookie, it can be sent automatically, but not across domains, so it's usually put in the Header of an HTTP request.
In the Authorization field. Authorization: Bearer can also place JWT in the data body of POST requests when crossing domains

The data structure of JWT is divided into three parts: JWT header, payload and signature; each part is divided into three substrings by "." delimiter.

1 JWT Header
The JWT header is a JSON object that describes JWT metadata, usually as shown below.
{
"alg": "HS256",
"typ": "JWT"
}
In the above code, the alg attribute denotes the algorithm used for signature, defaulting to HMAC SHA256 (written as HS256); the type attribute denotes the type of token, and the JWT token is universally written as JWT.
Finally, the above JSON object is converted to string preservation using the Base64 URL algorithm

2 Payload
The payload part is the main content part of JWT and also a JSON object, which contains the data to be transferred. JWT specifies seven default fields for selection.
iss: issuer
exp: due date
Subject:
aud: User
nbf: Not available until now
iat: release time
jti: JWT ID is used to identify the JWT
In addition to the default fields above, we can customize private fields as follows:
{
"sub": "1234567890",
"name": "chongchong",
"admin": true
}

3 signature hash
The signature hash part is the signature of the above two parts of the data, and generates the hash through the specified algorithm to ensure that the data will not be tampered with.
First, you need to specify a secret. The password is only stored in the server and cannot be disclosed to the user. Then, the signature is generated using the signature algorithm specified in the header (HMAC SHA256 by default) according to the following formula.
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)
After calculating the signature hash, the three parts of the JWT header, payload and signature hash are combined into a string, and each part is separated by "..." to form the whole JWT object.

text
First download the official website with composer: https://jwt.io/
Directory: app/common/auth/JwtAuth.php

namespace app\common\auth;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\ValidationData;
class JwtAuth 
{
	/**
	* jwt token
	*/
	private $token;

	/**
	* jwt detoken
	*/
	private $decodetoken;

	/**
	* iss claim The issuer of the JWT parameter
	*/
	private $iss = 'xxx';

	/**
	* aud claim The party whose parameter receives the JWT
	*/
	private $aud ='xxx';

	/**
	* jti claim Parameter Number
	*/
	private $jti = 'xxx';

	/**
	* uid Parameter user ID,
	*/
	private $uid;

	private $exp;

	/**
	* secrect key secret key
	*/
	private $secrect = 'xxxxxxx';

	
	/**
	* Define jwtAuth handle
	*/
	private static $instance;


	/** 
	 * Get the JwtAuth handle
	 * @date   2019-04-15
	 */
	public static function getInstance() {
		if(is_null(self::$instance)) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/** 
	 * Privatization constructor
	 * @date   2019-04-15
	 */
	private function __construct() {
	}

	/** 
	 * Privatized clone function
	 * @date   2019-04-15
	 */
	private function __clone() {
	}

	/** 
	 * Get token
	 * @date   2019-04-16
	 */
	public function getToken()
	{
		return (string)$this->token;
	}


	/** 
	 * Setting token
	 * @date   2019-04-16
	 */
	public function setToken($token)
	{
		$this->token = $token;
		return $this;
	}

	/** 
	 * Setting User ID
	 * @date  2019-04-16
	 */
	public function setUid($uid) 
	{
		$this->uid = $uid;
		return $this;
	}

	/** 
	 * Get the user ID
	 * @date  2019-04-16
	 */
	public function getUid() 
	{
		return $this->uid;
	}	


	/** 
	 * Get Token expiry date
	 * @date  2019-04-17
	 */
	public function getTokenExp() 
	{		
		return $this->jwtDecode()->getClaim('exp');
	}

	/** 
	 * Coding token
	 * @param  The validity period is the same day + 7 days in the morning.
	 * @date   2019-04-16
	 */
	public function jwtEncode() 
	{
		$time = time();
		// Expiration date of validity
        $exp_sec = strtotime("+1 week",strtotime(date("Y-m-d 23:59:59")));
		$this->token = (new Builder())->setHeader('alg','HS256')
				->setIssuer($this->iss)
				->setAudience($this->aud)
				->setIssuedAt($time)
				->setExpiration($exp_sec) // token validity period
				->set('uid',$this->uid)
				->set('openid',$this->openid)
				->setId($this->jti, true)
				->sign(new Sha256(), $this->secrect)		
				->getToken();
		return $this;
	}


	/** 
	 * Decoding token
	 * @date   2019-04-16
	 */
	public function jwtDecode()
	{	 
		if(!$this->decodetoken) 
		{
			$this->decodetoken = (new Parser())->parse((string)$this->token);				
			$this->uid = $this->decodetoken->getClaim('uid');
			$this->openid = $this->decodetoken->getClaim('openid');
		}

		return $this->decodetoken;		
	}


	/** 
	 * Validation of parameters
	 * @date   2019-04-16
	 */
	public function validation()
	{

		$data = new ValidationData();

		$data->setIssuer($this->iss);

		$data->setAudience($this->aud);

		$data->setId($this->jti);	

		return $this->jwtDecode()->validate($data);
	}

	/** 
	 * Signature verification
	 * @date   2019-04-16
	 */
	public function verify()
	{
		return $this->jwtDecode()->verify(new Sha256(),$this->secrect);
	}
	
}

Cooperate with middleware

namespace app\http\middleware;
use think\facade\Cache;
use app\common\err\ApiErrCode;
use app\common\exception\ApiException;
use app\common\auth\JwtAuth;
class AuthJwt 
{
	public function handle($request, \Closure $next)
    {
       $token = $request->param('token');
       // Verify Token
        if($token) {
       	    $JwtAuth = JwtAuth::getInstance();
       	    $JwtAuth->setToken($token); // Pass the current Token 
       	    // Check Token parameters and keys
       	    if($JwtAuth->validation() && $JwtAuth->verify()) {
              $uid = $JwtAuth->getUid();
              $request->uid = $uid;  // Get the current user ID
       	      return $next($request);
       	    }else{
       	    	// Token invalid/invalid
       	    	throw new ApiException(ApiErrCode::ERROR_TOKEN);      	    	
       	    }       	    
        }else{
        	throw new ApiException(ApiErrCode::ERROR_PARAM);
        }     
        //return $next($request);
    }
	
}


Posted by zulfer on Wed, 24 Jul 2019 04:14:55 -0700