To implement JWT certification with php, let's first understand what JWT is.
What is JWTJWT(json web token) is an open JSON-based standard implemented to pass declarations between network applications.
JWT's declarations are typically used to transfer authenticated user identity information between identity providers and service providers in order to obtain resources from the resource server.For example, on user logins.
JWT defines a concise, self-contained method for securely transferring information between communicating parties in the form of JSON objects.JWT can sign using either the HMAC algorithm or the public key pair of RSA.
JWT has two features:
Self-contained: The load contains all the information the user needs, avoiding multiple queries to the database
Compact: Can be sent via URL, POST parameter or HTTP header because of small amount of data and fast transmission speed
JWT Composition
JWT consists of three parts: header, payload, signature. Let's start with an example of the official website.
header section:
The jwt header carries two pieces of information:
Declaration type, here is jwt
Declaring encryption algorithms usually use HMAC SHA256 directly
The complete head is like the following JSON:
{
"alg": "HS256",
"typ": "JWT"
}
The corresponding base64UrlEncode code is:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Description: The field is in json format.The alg field specifies the algorithm that generates the signature, defaulting to HS256 and typ e to JWT
payload section:
Load is the place where effective information is stored.
Declaration registered in the standard (recommended but not mandatory):
iss: jwt issuer
Sub: Users targeted by JWT
aud: the party receiving jwt
exp: jwt expiration time, which must be greater than the issuance time
nbf: Define when this jwt will not be available
Iat: Issuance time of JWT
Jti: The unique identity of jwt, used primarily as a one-time token to avoid replay attacks.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
The corresponding base64UrlEncode code is:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
Description: The field is in json format, indicating the user's identity of the data, you can customize the field yourself, very flexible.Subuser facing, name name, iat issuance time.For example, a customizable example is as follows:
{
"iss": "admin", //The issuer of the JWT
"iat": 1535967430, //Time filed
"exp": 1535974630, //Expiration Time
"nbf": 1535967430, //Do not receive processing the Token before this time
"sub": "www.admin.com", //User-oriented
"jti": "9f10e796726e332cec401c569969e13e" //The Token Unique Identification
}
signature section:
The third part of jwt is a visa information, which consists of three parts:
-
Header (after base64)
-
Payload (after base64)
-
secret
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
123456
)
The corresponding signature is:
keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU
The final json for the JWT is (header.payload.signature):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU
Description: header and payload are spliced after base64UrlEncode encoding.Sign the HS256 algorithm with key (in this case, 123 456).
Process of using JWT
-
First logon: User first logon, enter user name password
-
Password validation: The server takes the user name and password from the database for validation
-
Generate JWT: Server-side validation passes, generating JWT based on information returned from the database and preset rules
-
Return JWT: Return JWT in HTTP RESPONSE of the server
-
Requests with JWT: later client initiates request, HTTP REQUEST
-
The Authorizatio field in HEADER must have a value, which is JWT
-
Server Validation JWT
How PHP implements JWT
Using PHP 7.0.31 here, we create a new file, jwtAuth.php, with the complete class code as follows:
<?php
/**
* PHP Implement jwt
*/
class JwtAuth {
//head
private static $header=array(
'alg'=>'HS256', //Algorithms for generating signature s
'typ'=>'JWT' //type
);
//Key used when generating information digest using HMAC
private static $key='root123456';
/**
* Get jwt token
* @param array $payload jwt Load format as follows is not required
* [
* 'iss'=>'jwt_admin', //The issuer of the JWT
* 'iat'=>time(), //Time filed
* 'exp'=>time()+7200, //Expiration Time
* 'nbf'=>time()+60, //Do not receive processing the Token before this time
* 'sub'=>'www.mano100.cn', //User-oriented
* 'jti'=>md5(uniqid('JWT').time()) //The Token Unique Identification
* ]
* @return bool|string
*/
public static function getToken(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{
return false;
}
}
/**
* Verify token is valid, default validation exp,nbf,iat time
* @param string $Token token to verify
* @return bool|string
*/
public static function verifyToken(string $Token)
{
$tokens = explode('.', $Token);
if (count($tokens) != 3)
return false;
list($base64header, $base64payload, $sign) = $tokens;
//Get jwt algorithm
$base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
if (empty($base64decodeheader['alg']))
return false;
//Signature Verification
if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)
return false;
$payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);
//Sign-out time greater than current server time validation failed
if (isset($payload['iat']) && $payload['iat'] > time())
return false;
//Expiration Time Xiaoyu Current Server Time Validation Failed
if (isset($payload['exp']) && $payload['exp'] < time())
return false;
//Do not receive and process the Token before this nbf time
if (isset($payload['nbf']) && $payload['nbf'] > time())
return false;
return $payload;
}
/**
* base64UrlEncode https://jwt.io/ Encode implementation of base64UrlEncode in
* @param string $input String to be encoded
* @return string
*/
private static function base64UrlEncode(string $input)
{
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}
/**
* base64UrlEncode https://jwt.io/ Decoding implementation of base64UrlEncode in
* @param string $input String to decode
* @return bool|string
*/
private static function base64UrlDecode(string $input)
{
$remainder = strlen($input) % 4;
if ($remainder) {
$addlen = 4 - $remainder;
$input .= str_repeat('=', $addlen);
}
return base64_decode(strtr($input, '-_', '+/'));
}
/**
* HMACSHA256 Signature. HMACSHA256 signature implementation in https://jwt.io/.
* @param string $input For base64UrlEncode (header).'.'. base64UrlEncode (payload)
* @param string $key
* @param string $alg Method of algorithm
* @return mixed
*/
private static function signature(string $input, string $key, string $alg = 'HS256')
{
$alg_config=array(
'HS256'=>'sha256'
);
return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true));
}
}
These are all the contents of the article. If you have friends who need to learn and exchange experience, please join Swoole Exchange Group to learn and exchange. Let's learn together, communicate with each other if you have problems, and make progress together!The premise is that you learn technology.Thanks for reading!
Test it here
//Test whether or not the official website matches begin
$payload=array('sub'=>'1234567890','name'=>'John Doe','iat'=>1516239022);
$jwt=new Jwt;
$token=$jwt->getToken($payload);
echo "<pre>";
echo $token;
//Verify signature on token
$getPayload=$jwt->verifyToken($token);
echo "<br><br>";
var_dump($getPayload);
echo "<br><br>";
//Test whether the official website matches the end
//Use test begin yourself
$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;
//Verify signature on token
$getPayload_test=Jwt::verifyToken($token_test);
echo "<br><br>";
var_dump($getPayload_test);
echo "<br><br>";
//end when used by oneself