mishal/jwt

JWT - JSON Web Tokens

1.0.0 2015-11-17 13:02 UTC

This package is not auto-updated.

Last update: 2024-09-14 18:58:21 UTC


README

Build Status Downloads Latest release

A Php implementation of JSON Web Token.

安装

使用composer安装

$ composer require mishal/jwt

算法和用法

JWT规范支持NONEHMACRSASSAECDSARSASSA-PSS算法进行加密签名。

支持的算法

  • HMAC 256
  • RSA 256

NONE - 无签名的令牌

<?php
    
use Jwt\Jwt;
use Jwt\Algorithm\NoneAlgorithm;
    
$token = Jwt::encode('string', new NoneAlgorithm());
  
echo $token; // eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJkYXRhIjoic3RyaW5nIn0.

HMAC

  • HS256 - 使用SHA-256散列算法的HMAC

HS256

<?php

use Jwt\Jwt;
use Jwt\Algorithm\HS256Algorithm;

$token = Jwt::encode('string', $alg = new HS256Algorithm('secret'));

echo $token; // eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoic3RyaW5nIn0.RncJbCyf4zd0pu1N02u_rKwEezkmd94r3i5sWLk1ceU

// decode, you must passed allowed algorithm(s) to prevent attackers to control the choice of algorithm
$decoded = Jwt::decode($token, ['algorithm' => $alg]);

echo $decoded['data']; // 'string'

RSA

  • RS256 - 使用SHA-256散列算法的RSA

RS256 - 使用SHA-256散列算法的RSA

<?php

use Jwt\Jwt;
use Jwt\Algorithm\RS256Algorithm;

$privateKey = __DIR__ . '/key.pem';
$publicKey = __DIR__ . '/key.pub';

$token = Jwt::encode('string', $alg = new RS256Algorithm($privateKey, $publicKey));

echo $token; // eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjoic3RyaW5nIn0.RncJbCyf4zd0pu1N02u_rKwEezkmd94r3i5sWLk1ceU

// decode, you must passed allowed algorithm(s) to prevent attackers to control the choice of algorithm
$decoded = Jwt::decode($token, ['algorithm' => $alg]);

echo $decoded['data']; // 'string'

支持保留声明名称

JSON Web Token定义了一些保留的声明名称,并定义了它们的使用方法。JWT支持这些保留的声明名称

  • 'exp' (过期时间) 声明
  • 'nbf' (生效时间) 声明
  • 'iss' (发行者) 声明
  • 'aud' (受众) 声明
  • 'jti' (JWT ID) 声明
  • 'iat' (发行时间) 声明
  • 'sub' (主题) 声明

过期时间声明

exp(过期时间)声明标识JWT必须被拒绝处理的过期时间。处理exp声明要求当前日期/时间必须在exp声明中列出的过期日期/时间之前。实现者可能提供一些小的leeway(宽容度),通常不超过几分钟,以考虑时钟偏差。其值必须是一个包含NumericDate值的数字。使用此声明是可选的。

处理过期声明

<?php

use Jwt\Jwt;
use Jwt\Algorithm\HS256Algorithm;
use Jwt\Exception\ExpiredException;

$payload = [
    Jwt::CLAIM_EXPIRATION => strtotime('1 day'),
    'data' => 'my data'
];

$token = Jwt::encode($payload, $alg = new HS256Algorithm('secret'));

try {
    $token = Jwt::decode($token, ['algorithm' => $alg]);
} catch (ExpiredException $e) {
    // Handle expired token, e.g. logout user or deny access
}

添加宽容度

<?php

use Jwt\Jwt;
use Jwt\Algorithm\HS256Algorithm;
use Jwt\Exception\ExpiredException;

$leeway = 30; // 30 sec

$payload = [
    Jwt::CLAIM_EXPIRATION => strtotime('1 day'),
    'data' => 'my data'
];

$token = Jwt::encode($payload, $alg = new HS256Algorithm('secret'));

try {
    $token = Jwt::decode($token, ['algorithm' => $alg, 'leeway' => $leeway]);
} catch (ExpiredException $e) {
    // Handle expired token, e.g. logout user or deny access
}

生效时间声明

nbf(不早于)声明标识JWT必须被拒绝处理的日期/时间。处理nbf声明要求当前日期/时间必须在或等于nbf声明中列出的不早于日期/时间。实现者可能提供一些小的leeway(宽容度),通常不超过几分钟,以考虑时钟偏差。其值必须是一个包含NumericDate值的数字。使用此声明是可选的。

处理不早于声明

<?php

use Jwt\Jwt;
use Jwt\Algorithm\HS256Algorithm;
use Jwt\Exception\BeforeValidException;

$payload = [
    Jwt::CLAIM_NOT_BEFORE => strtotime('1 day'),
    'data' => 'my data'
];

$token = Jwt::encode($payload, $alg = new HS256Algorithm('secret'));

try {
    $token = Jwt::decode($token, ['algorithm' => $alg]);
} catch (BeforeValidException $e) {
    // Handle invalid token, e.g. logout user or deny access
}

发行者声明

iss(发行者)声明标识发行JWT的主体。处理此声明通常由应用程序指定。iss值是一个包含StringOrURI值的敏感字符串。使用此声明是可选的。

处理发行者声明

请参阅有效负载验证部分。

受众声明

aud(受众)声明标识JWT预期接收的对象。每个预期处理JWT的主体必须通过受众声明中的值来标识自己。如果处理声明的主体没有使用值在aud声明中标识自己,则必须拒绝JWT。在一般情况下,aud值是一个包含StringOrURI值的敏感字符串数组。在JWT有一个受众的特殊情况下,aud值可以是一个包含StringOrURI值的单个敏感字符串。受众值的解释通常由应用程序指定。使用此声明是可选的。

处理受众声明

请参阅有效负载验证部分。

JWT ID声明

JWT ID(JWT标识符)声明提供了JWT的唯一标识符。标识符值必须以确保相同值不会意外分配给不同数据对象的方式进行分配;如果应用程序使用多个发行者,还必须在不同发行者生成的值之间防止冲突。JWT ID声明可用于防止JWT被重放。JWT ID值是一个大小写敏感的字符串。此声明的使用是可选的。

处理JWT ID声明

请参阅有效负载验证部分。

发行时间声明

iat(发行时间)声明标识了JWT被发行的时间。此声明可用于确定JWT的年龄。其值必须是一个包含NumericDate值的数字。此声明的使用是可选的。

处理发行时间声明

请参阅有效负载验证部分。

主题声明

sub(主题)声明标识了JWT的主题主体。JWT中的声明通常是关于主体的声明。主题值必须是本地唯一(在发行者上下文中)或全局唯一的。此声明的处理通常是应用特定的。sub值是一个包含StringOrURI值的大小写敏感的字符串。此声明的使用是可选的。

处理主题声明

请参阅有效负载验证部分。

有效载荷验证

使用verify选项解码令牌时,可以验证有效载荷数据。ExpirationNot Before声明始终被检查。

<?php

use Jwt\Jwt;
use Jwt\Algorithm\HS256Algorithm;
use Jwt\Exception\VerificationException;

$payload = [
    // expiration claim
    Jwt::CLAIM_EXPIRATION => strtotime('1 day'),
    // issuer claim
    Jwt::CLAIM_ISSUER => 'my-web-app',
    // custom claims
    'user' => 'administrator'
];

$token = Jwt::encode($payload, $alg = new HS256Algorithm('secret'));

// Decode with verification of the payload
// Expiration, and Not before claims are verified automatically

// we will verify the token when decoding
$verify = [
    Jwt::CLAIM_ISSUER => 'my-web-app',
    // we can use closures for value verification
    'user' => function ($value) {
        if ($value === 'administrator') {
            return true;
        }
        return false;
    }
];

try {
    $decoded = Jwt::decode($token, ['algorithm' => $alg, 'verify' => $verify]);
} catch (VerificationException $e) {
    // something is wrong with the token
    // do something!
    switch ($e->getCode()) {
        case VerificationException::CLAIM_IS_MISSING:
            // claim is missing
            break;
        case VerificationException::CLAIM_VALUE_IS_INVALID:
            // invalid claim value
            break;
    }
}

测试

使用phpunit运行测试

$ phpunit

致谢

Jwt受到ruby的jwt和php的firebase/jwt的启发。