terehinis/jwt-refresh-token-bundle

在Symfony中实现基于Json Web Tokens的刷新令牌系统

安装次数: 1,682

依赖关系: 0

建议者: 0

安全性: 0

星标: 0

关注者: 1

分支: 159

类型:symfony-bundle

v0.4.2 2018-06-28 13:31 UTC

This package is auto-updated.

Last update: 2024-09-23 21:44:21 UTC


README

Scrutinizer Code Quality Build Status Code Coverage Latest Stable Version Total Downloads License StyleCI

此包的目的是以简单的方式管理JWT(Json Web Tokens)的刷新令牌。此包使用LexikJWTAuthenticationBundle。目前仅支持Doctrine ORM。

先决条件

此包需要Symfony 3.3+或4.0+。

如果您想使用此包与旧版本的Symfony,请使用0.2.x版本。

提示:虽然包没有强制要求这样做,但强烈建议使用HTTPS。

安装

步骤1:下载包

terehinis/jwt-refresh-token-bundle添加到您的composer.json文件中

$ composer require "terehinis/jwt-refresh-token-bundle"

或编辑composer.json

// ...
"terehinis/jwt-refresh-token-bundle": "~0.1",
// ...

步骤2:启用包

然后,通过在您的Symfony应用程序的app/AppKernel.php文件中添加以下行来启用包

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...
            new terehinis\JWTRefreshTokenBundle\terehinisJWTRefreshTokenBundle(),
        );
    }

    // ...
}

步骤3:配置您的刷新令牌路由

打开您的主路由配置文件(通常为app/config/routing.yml),并将其中的以下四行复制到文件的开始部分。

# app/config/routing.yml
terehinis_jwt_refresh_token:
    path:     /api/token/refresh
    defaults: { _controller: terehinis.jwtrefreshtoken:refresh }
# ...

步骤4:允许匿名访问刷新令牌

在security.yml文件中添加以下行

# app/config/security.yml
    firewalls:
        refresh:
            pattern:  ^/api/token/refresh
            stateless: true
            anonymous: true
    # ...

    access_control:
        # ...
        - { path: ^/api/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        # ...
# ...

步骤5:更新您的模式

使用以下命令创建一个新表来处理您的刷新令牌

php app/console doctrine:schema:update --force

用法

配置TTL

您可以定义刷新令牌的TTL。默认值是1个月。您可以通过在config.yml文件中添加此行来更改此值

terehinis_jwt_refresh_token:
    ttl: 2592000

配置用户身份字段

您可以更改用户身份字段。请确保您的模型用户有此字段的getter。默认值是username。您可以通过在config.yml文件中添加此行来更改此值

terehinis_jwt_refresh_token:
    user_identity_field: email

配置TTL更新

您可以在刷新时扩展刷新令牌的TTL。默认值是false。您可以通过在config.yml文件中添加此行来更改此值

terehinis_jwt_refresh_token:
    ttl_update: true

这将在每次请求刷新时重置令牌TTL。

配置防火墙名称

您可以定义防火墙名称。默认值是api。您可以通过在config.yml文件中添加此行来更改此值

terehinis_jwt_refresh_token:
    firewall: api

配置UserProvider

您可以定义自己的UserProvider。默认情况下,我们使用我们的自定义UserProvider。您可以通过在config.yml文件中添加此行来更改此值

terehinis_jwt_refresh_token:
    user_provider: user_provider_service_id

例如,如果您正在使用FOSUserBundle,则user_provider_service_id必须设置为fos_user.user_provider.username_email

使用另一个实体来刷新令牌

您可以定义自己的刷新令牌实体。在您的包中创建扩展terehinis\JWTRefreshTokenBundle\Entity\RefreshToken的实体类

namespace MyBundle;

use terehinis\JWTRefreshTokenBundle\Entity\AbstractRefreshToken;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Doctrine\ORM\Mapping as ORM;

/**
 * This class override terehinis\JWTRefreshTokenBundle\Entity\RefreshToken to have another table name.
 *
 * @ORM\Table("jwt_refresh_token")
 * @ORM\Entity(repositoryClass="terehinis\JWTRefreshTokenBundle\Entity\RefreshTokenRepository")
 * @UniqueEntity("refreshToken")
 */
class JwtRefreshToken extends AbstractRefreshToken
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * {@inheritdoc}
     */
    public function getId()
    {
        $this->id;
    }
}

然后通过在config.yml文件中添加此行来声明此实体

terehinis_jwt_refresh_token:
    refresh_token_entity: MyBundle\JwtRefreshToken

使用另一个实体管理器

您可以告诉JWTRefreshTokenBundle使用默认实体管理器(doctrine.orm.entity_manager)之外的另一个实体管理器。

只需在config.yml文件中添加此行即可

terehinis_jwt_refresh_token:
    entity_manager: my.specific.entity_manager.id

生成令牌

当您通过/api/login_check使用用户/密码凭据进行身份验证时,LexikJWTAuthenticationBundle现在会返回JWT令牌和刷新令牌数据。

{
  "token": "eyxxxGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJleHAiOjE0NDI0MDM3NTgsImVtYWlsIjoid2VibWFzdGVyQGdlc2RpbmV0LmNvbSIsImlhdCI6IjE0NDI0MDM3MzgifQ.bo5pre_v0moCXVOZOj-s85gVnBLzdSdsltPn3XrkmJaE8eaBo_zcU2pnjs4dUc9hhwNZK8PL6SmSNcQuTUj4OMK7sUDfXr62a05Ds-UgQP8B2Kpc-ZOmSts_vhgo6xJNCy8Oub9-pRA_78WzUUxt294w0IArrNlgQAGewk65RSMThOif9G6L7HzBM4ajFZ-kMDypz2zVQea1kry-m-XXKNDbERCSHnMeV3rANN48SX645_WEvwaHy0agChR4hTnThzLof2bShA7j7HmnSPpODxQszS5ZBHdMgTvYhlcWJmwYswCWCTPl3lsqVq_UOFI5_4arpSNlUwZsichqxXVAHX5idZqCWtoaqAbvNQe2IpinYajoXw-MlYKvcN2TLUF_8sy529olLUagf4FCpCO6JFxovv0E7ll9tUOVvx9LlannqV8976q5XCOoXszKonZSH7DhsBlW5Emjv7PailbARZ-hfl4YlamyY2QbnxAswYycfoxqJxbbIKYGA8dlebdvMyC7m9VATnasTuKeEKS3mP5iyDgWALBHNYXm1FM-12zHBdN3PbOgxmy_OBGvk05thYFEf2WVmyedtFHy4TGlI0-otUTAf2swQAXWhKtkLWzokWWF7l5iNzam1kkEgql5EOztXHDZpmdKVHWBVNvN3J5ivPjjJBm6sGusf-radcw",
  "refresh_token": "xxx00a7a9e970f9bbe076e05743e00648908c38366c551a8cdf524ba424fc3e520988f6320a54989bbe85931ffe1bfcc63e33fd8b45d58564039943bfbd8dxxx"
}

此刷新令牌持久保存在RefreshToken实体中。之后,当您的JWT有效令牌过期时,如果您想要获取新的令牌,您可以通过两种方式进行

  • 再次发送您的用户凭证到/api/login_check。这将生成一个新的JWT和一个新的刷新令牌。

  • 使用我们的刷新令牌更新有效的JWT。向/api/token/refresh URL发送带有刷新令牌的有效负载的POST请求。这样,您可以在不要求用户提供用户凭证的情况下始终获取有效的JWT。但是,您必须注意**刷新令牌是否仍然有效**。您的刷新令牌不会改变,但有效日期和时间将增加。

curl -X POST -d refresh_token="xxxx4b54b0076d2fcc5a51a6e60c0fb83b0bc90b47e2c886accb70850795fb311973c9d101fa0111f12eec739db063ec09d7dd79331e3148f5fc6e9cb362xxxx" 'http://xxxx/token/refresh'

此调用返回一个新有效的JWT令牌,更新刷新令牌的有效日期和时间。

有用命令

我们为您提供两个命令来管理令牌。

撤销所有无效令牌

如果您想要撤销所有无效(日期和时间已过期)的刷新令牌,您可以执行以下操作

php app/console terehinis:jwt:clear

可选参数是日期和时间,它将删除小于此日期和时间的所有令牌

php app/console terehinis:jwt:clear 2015-08-08

我们建议使用cronjob定期执行此命令以删除无效的刷新令牌。

撤销令牌

如果您想要撤销单个令牌,可以使用此命令

php app/console terehinis:jwt:revoke TOKEN

事件

如果您想在令牌刷新时执行某些操作,您可以监听terehinis.refresh_token事件。

例如

<?php

namespace AppBundle\EventListener;

use terehinis\JWTRefreshTokenBundle\Event\RefreshEvent;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class LogListener implements EventSubscriberInterface
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function log(RefreshEvent $event)
    {
        $refreshToken = $event->getRefreshToken()->getRefreshToken();
        $user = $event->getPreAuthenticatedToken()->getUser()->getUsername();
        
        $this->logger->debug(sprintf('User "%s" has refreshed it\'s JWT token with refresh token "%s".', $user, $refreshToken));
    }
    
    public static function getSubscribedEvents()
    {
        return array(
            'terehinis.refresh_token' => 'log',
        );
    }
}