mnavarrocarter / auth-bundle
Requires
- php: ^7.1.3
- lcobucci/jwt: ^3.2
- symfony/config: ^4.0
- symfony/dependency-injection: ^4.0
- symfony/http-foundation: ^4.0
- symfony/security: ^4.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.12
- symfony/phpunit-bridge: ^4.0
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
中定义一系列规则。最重要的是在两个防火墙auth
和main
中定义的规则。
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