mnavarrocarter/auth-bundle

此包已被弃用且不再维护。未建议替代包。

安装: 1

依赖: 0

建议者: 0

安全: 0

星星: 0

关注者: 1

分支: 1

开放问题: 0

类型:symfony-bundle

1.0.0 2018-07-13 14:58 UTC

This package is auto-updated.

Last update: 2019-08-18 18:29:24 UTC


README

简介

此包为您的Symfony项目提供JWT认证。

安装

只需运行composer require mnavarrocarter/auth-bundle

在此之前,请确保您的项目中已安装Symfony的安全组件(包),使用:composer require security(仅Flex)

配置

为了让此包与您的应用程序正常工作,您需要在security.yaml中定义一系列规则。最重要的是在两个防火墙authmain中定义的规则。

auth防火墙是用户使用用户名和电子邮件进行认证的地方,并返回一个令牌给他。令牌是在mnc_auth.login_handler.default服务中创建的。您可以替换并创建自己的。只需以原始的一个为例。

在main防火墙中,认证方法是令牌本身。这是由mnc_auth.guard_authenticator.default服务处理的。如果您想自定义此类的行为(成功和失败响应或SymfonyToken创建),最佳方式是扩展MNC\Bundle\AuthBundle\Security\Guard\JwtGuardAuthenticator并覆盖您感兴趣的任何方法。然后将其定义为服务并将其放在您的认证器中。

security:
    firewalls:
        
        # ... other firewalls
        
        auth:
            pattern:  ^/auth
            stateless: false
            anonymous: true
            form_login:
                check_path: /auth/token
                # This habdler creates the token and returns it in a response
                # You can also create your own.
                # See: 
                success_handler: mnc_auth.login_handler.default
                # The failure handler just returns an error response
                failure_handler: mnc_auth.login_handler.default
                # This only changes the default params
                username_parameter: email
                password_parameter: password
        
        main:
            pattern: ^/
            anonymous: false
            # Important if you want to do token session invalidation
            stateless: false
            guard:
                # This authenticator does all the work when a request carries a token.
                authenticators:
                    - mnc_auth.guard_authenticator.default

此外,您还需要在您的routes.yaml中添加此路由

auth_token:
    path: /auth/token

工作原理

使用神奇的lcobucci/jwt库,此包使用您的内核秘密作为密钥,以Hmac Sha 512对JWT进行编码。声明包括:

  • sub(主题):来自UserInterface::getUsername()的值
  • exp(过期):令牌创建时间+3600秒
  • jti(json令牌id):令牌的自自动生成的id

然而,您可以超越这些默认设置实现自定义行为。继续阅读以了解如何。

TokenService

令牌创建和验证集中在TokenService中。此服务有两个必需依赖项和一个可选依赖项。

第一个依赖项是一个实现TokenBuilderInterface的类。它包含令牌创建和验证的指令。您可以创建自己的实现,该实现使用不同的签名算法并设置不同的声明和验证规则。然后,您可以通过修改配置来让TokenService使用您的实现。

第二个依赖项是一个实现TokenIdentifierGenerator接口的类,用于为JWT生成id。默认的一个使用PHP的uniqid函数,但您可以使用其他方法实现自己的。然后,您可以通过修改配置来让TokenService使用您的实现。

第三个依赖项是TokenStoreInterface。此包不提供该接口的实现。这取决于您。默认情况下,如果没有定义,TokenService不会使用它。有关如何使用TokenStoreInterface的更多信息,请参阅下面的使用TokenStoreInterface

如果您想使用 RSA 签名令牌,您必须根据 TokenBuilderInterface 协议实现自己的令牌构建器。

修改默认的 TokenBuilder

如果默认令牌构建器的哈希算法(Hmac Sha 512)符合您的要求,但您想更改密钥或令牌有效期,您可以通过修改节点 mnc_auth.default_builder 中的配置来实现。有关更多信息,请参阅默认配置参考

使用 TokenStoreInterface

目前,此捆绑包可以正常工作,并满足认证的基本需求。然而,还有一些更复杂的场景可能需要额外的功能。例如,您是否希望能够检测到一台机器使用另一台机器请求的令牌?这意味着有人可能已经共享了他们的令牌或盗窃了它。如果您想撤销令牌怎么办?JWT 是非持久性的,这意味着它们不会存储在数据库中。因此,您没有方法“知道”令牌。

这就是 TokenStoreInterface 的作用。该接口定义了令牌 ID 持久化的最小合同。您可以将它与 cookie 或用户关联起来,并轻松地允许用户撤销其他会话中的令牌。可能性基本上取决于您。

此捆绑包没有默认的 TokenStore 服务,因为这是一个实现细节。我们不知道您使用的是什么持久化引擎。然而,您可以查看这个示例,该示例在 DoctrineRepository 中实现了 TokenStoreInterface,并使不属于相同会话 ID 的令牌无效。

<?php

namespace App\Repository;

use App\Entity\Token;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use MNC\Bundle\AuthBundle\Token\Store\TokenStoreInterface;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

/**
 * @method Token|null find($id, $lockMode = null, $lockVersion = null)
 * @method Token|null findOneBy(array $criteria, array $orderBy = null)
 * @method Token[]    findAll()
 * @method Token[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class TokenRepository extends ServiceEntityRepository implements TokenStoreInterface
{
    /**
     * @var RequestStack
     */
    private $requestStack;

    public function __construct(RegistryInterface $registry, RequestStack $requestStack)
    {
        parent::__construct($registry, Token::class);
        $this->requestStack = $requestStack;
    }

    public function store($tokenId): void
    {
        if ($this->getSession()->has('toid')) {
            $toid = $this->getSession()->get('toid');
        } else {
            $toid  = md5($this->getSession()->getId());
            $this->getSession()->set('toid', $toid);
        }

        $token = $this->findOneBy(['sessionId' => $toid]);

        if (null === $token) {
            $token = new Token($tokenId, $toid);
        } else {
            $token->updateTokenId($tokenId);
        }

        $manager = $this->getEntityManager();
        $manager->persist($token);
        $manager->flush();
    }

    public function revoke($tokenId): void
    {
        $token = $this->find($tokenId);
        if (null !== $token) {
            $token->revoke();
            $manager = $this->getEntityManager();
            $manager->persist($token);
            $manager->flush();
        }
    }

    public function isTokenValid($tokenId): bool
    {
        $token = $this->find($tokenId);
        if (null !== $token) {
            return $token->getSessionId() === $this->getSession()->get('toid');
        }
        return false;
    }

    public function isTokenRevoked($tokenId): bool
    {
        $token = $this->find($tokenId);
        if (null !== $token) {
            return $token->isRevoked();
        }
        return true;
    }

    public function getRequest(): Request
    {
        return $this->requestStack->getMasterRequest();
    }

    public function getSession(): SessionInterface
    {
        return $this->getRequest()->getSession();
    }
}

默认配置参考

mnc_auth:
    token_service:
        # You can define a custom token builder changing this value
        token_builder: mnc_auth.token_builder.default
        # You can define a custom token id generator changing this value
        token_id_generator: mnc_auth.identifier_generator.default
        # You can define your implementation of token store here.
        token_store: ~
    default_builder:
        # This allows you to modify the secret for the default token builder
        secret: '%kernel.secret%'
        # This allows you to modify the expiration time for the default token builder.
        ttl: 3600
    # Token extractors configuration.
    token_extractors:
        cookie:
            key_name: token
        query_param:
            key_name: token
        header:
            header_name: Authorization
            prefix: Bearer