agielks/yii2-jwt

基于 Icobucci 版本 4.1 的 JWT

安装次数: 1,273

依赖: 0

建议: 0

安全: 0

星级: 0

关注者: 1

分支: 0

公开问题: 0

类型:yii2-extension

1.0.0 2022-07-13 05:18 UTC

This package is auto-updated.

Last update: 2024-09-19 10:58:36 UTC


README

此扩展为 Yii 框架 2.0(需要 PHP 8.0+)提供了 JWT 集成(基于 https://github.com/lcobucci/jwt)。它包含基本的 HTTP 身份验证支持。

Latest Stable Version Total Downloads Latest Unstable Version License PHP Version Require

目录

  1. 安装
  2. 依赖
  3. 基本用法
    1. 创建令牌
    2. 从字符串解析令牌
    3. 验证令牌
  4. 登录示例

安装

此包可在 Packagist 上找到,您可以使用 Composer 安装它。

composer require agielks/yii2-jwt ~1.0

或将它添加到您的 composer.json 文件的 require 部分。

"agielks/yii2-jwt": "~1.0"

依赖

基本用法

jwt 组件添加到您的配置文件中,

'components' => [
    'jwt' => [
        'class' => \agielks\yii2\jwt\Jwt::class,
        // 'singer' => new \Lcobucci\JWT\Signer\Hmac\Sha256(),
        'signer' => 'HS256',
        // 'key' => \Lcobucci\JWT\Signer\Key\InMemory::plainText('my-key'),
        'key' => 'my-key', ,
    ],
],

重要:如果您不提供签名者和密钥,它将使用不安全的签名者

按照以下方式配置 authenticator 行为。

namespace app\controllers;

class SiteController extends \yii\rest\Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = [
            'class' => \agielks\yii2\jwt\JwtBearerAuth::class,
        ];

        return $behaviors;
    }
}

您还可以使用 CompositeAuth,参考 文档

创建令牌

/* @var $jwt \agielks\yii2\jwt\Jwt */

$now = new DateTimeImmutable();
$jwt = Yii::$app->get('jwt');

$token = $jwt
    ->builder()
    // Configures the issuer (iss claim)
    ->issuedBy('http://example.com')
    // Configures the audience (aud claim)
    ->permittedFor('http://example.org')
    // Configures the id (jti claim)
    ->identifiedBy('62cbfaca6bf7e')
    // Configures the time that the token was issue (iat claim)
    ->issuedAt($now)
    // Configures the time that the token can be used (nbf claim) required for StrictValidAt constraint
    ->canOnlyBeUsedAfter($now)
    // Configures the expiration time of the token (exp claim)
    ->expiresAt($now->modify('+1 hour'))
    // Configures a new claim, called "uid"
    ->withClaim('uid', '62cbfaca6bf7e')
    // Configures a new header, called "foo"
    ->withHeader('foo', 'bar')
    // Builds a new token
    ->getToken($jwt->signer(), $jwt->key());

// Retrieves all headers
$token->headers()->all();

// Retrives typ from headers
$token->headers()->get('typ');

// Print typ from headers
print_r($token->headers()->get('typ'));

// Retrieves all claims
$token->claims()->all();

// Retrieves jti from claims
$token->claims()->get('jti');

// Print jti from claims
print_r($token->claims()->get('jti'));

从字符串解析令牌

/* @var $jwt \agielks\yii2\jwt\Jwt */

$now = new DateTimeImmutable();
$jwt = Yii::$app->get('jwt');

$token = $jwt
    ->builder()
    // ...
    ->expiresAt($now->modify('+1 hour'))
    ->getToken($jwt->signer(), $jwt->key())
    ->toString();

// Parse without validation
$data = $jwt->config()->parser()->parse($token);

// Parse with validation
$data = $jwt->load($token);

// Print all headers
print_r($data->headers()->all());

// Print all claims
print_r($data->claims()->all());

// Validate token
var_dump($data->isExpired($now));
var_dump($data->isExpired($now->modify('+2 hour')));

验证令牌

您可以在组件中进行简单的配置来自定义验证

use \agielks\yii2\jwt\Jwt;
use \Lcobucci\JWT\Signer\Hmac\Sha256;
use \Lcobucci\JWT\Signer\Key\InMemory;
use \Lcobucci\JWT\Validation\Constraint\LooseValidAt;
use \Lcobucci\JWT\Validation\Constraint\SignedWith;
use \Lcobucci\JWT\Validation\Constraint\IdentifiedBy;
use \Lcobucci\Clock\SystemClock;

'components' => [
    'jwt' => [
        'class' => Jwt::class,
        'signer' => new Sha256(),
        'key'   => InMemory::plainText('my-key'),
        'constraints' => [
            new LooseValidAt(SystemClock::fromSystemTimezone()),
            new SignedWith(
                new Sha256(),
                InMemory::plainText('my-key')
            ),
            new IdentifiedBy('my-identity'),
        ],
    ],
],

登录示例

基本方案

  1. 客户端发送凭证。例如,登录 + 密码
  2. 应用程序验证凭证
  3. 如果凭证有效,客户端将收到令牌
  4. 客户端将令牌存储以供未来请求使用

逐步使用方法

  1. 安装组件
composer require agielks/yii2-jwt ~1.0
  1. 更新您的组件配置
'components' => [
    // other components here...
    'jwt' => [
        'class' => \agielks\yii2\jwt\Jwt::class,
        // 'singer' => new \Lcobucci\JWT\Signer\Hmac\Sha256(),
        'signer' => 'HS256',
        // 'key' => \Lcobucci\JWT\Signer\Key\InMemory::plainText('my-key'),
        'key' => 'my-key', ,
    ],
    // ...
],
  1. 更改方法 User::findIdentityByAccessToken()
/**
 * {@inheritdoc}
 * @param \Lcobucci\JWT\Token $token
 */
public static function findIdentityByAccessToken($token, $type = null)
{
   return static::findOne(['id' => $token->claims()->get('uid')]);
}

如果您想使用 auth_key 作为密钥,请更新方法如下

/**
 * {@inheritdoc}
 * @param \Lcobucci\JWT\Token $token
 */
public static function findIdentityByAccessToken($token, $type = null)
{
   return static::findOne(['auth_key' => $token->claims()->get('auth_key')]);
}
  1. 创建控制器
use agielks\yii2\jwt\JwtBearerAuth;
// Use your own login form
use common\models\LoginForm;
use DateTimeImmutable;
use Yii;
use yii\base\InvalidConfigException;
use yii\filters\Cors;
use yii\rest\Controller;
use yii\web\Response;

/**
 * Class SiteController
 */
class SiteController extends Controller
{
    /**
     * {@inheritdoc}
     */
    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_JSON;
        $behaviors['corsFilter'] = ['class' => Cors::class];
        $behaviors['authenticator'] = [
            'class' => JwtBearerAuth::class,
            'optional' => [
                'login',
            ],
        ];

        return $behaviors;
    }

    /**
     * {@inheritdoc}
     */
    protected function verbs()
    {
        return [
            'login' => ['OPTIONS', 'POST'],
        ];
    }

    /**
     * @return array|LoginForm
     * @throws InvalidConfigException
     */
    public function actionLogin()
    {
        $model = new LoginForm();

        if ($model->load(Yii::$app->getRequest()->getBodyParams(), '') && $model->login()) {
            /* @var $jwt \agielks\yii2\jwt\Jwt */

            $now = new DateTimeImmutable();
            $jwt = Yii::$app->get('jwt');
            $user = $model->getUser();

            return $jwt
                ->builder()
                // Configures the issuer (iss claim)
                ->issuedBy('http://example.com')
                // Configures the audience (aud claim)
                ->permittedFor('http://example.org')
                // Configures the id (jti claim)
                ->identifiedBy($user->id)
                // Configures the time that the token was issue (iat claim)
                ->issuedAt($now)
                // Configures the time that the token can be used (nbf claim)
                ->canOnlyBeUsedAfter($now)
                // Configures the expiration time of the token (exp claim)
                ->expiresAt($now->modify('+1 hour'))
                // Configures a new claim, called "uid"
                ->withClaim('uid', $user->id)
                // Configures a new claim, called "auth_key"
                ->withClaim('auth_key', $user->auth_key)
                // Returns a signed token to be used
                ->getToken($jwt->signer(), $jwt->key())
                // Convert token to string
                ->toString();
        }

        $model->validate();
        return $model;
    }

    /**
     * Test authentication
     */
    public function actionTest()
    {
        return ['auth' => 'success'];
    }
}