我使用ApiPlatform(PHP 8/Symfony 6)创建一个带有JWT身份验证的简单API。身份验证工作正常,我可以生成令牌。当我使用PostMan测试经过身份验证的操作时,没问题,我手动添加了带有令牌的Bearer标头。
现在我想使用自动生成的文档来实现这一点。我已经创建了一个JwtDecorator来添加我的登录路径和安全模式。现在,我可以使用“授权”绿色按钮添加令牌。但之后,当我执行经过身份验证的操作时,令牌不会添加到cUrl查询的头中。我不明白为什么。
安全.yaml
security:
enable_authenticator_manager: true
password_hashers:
App\Entity\User: 'auto'
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login
stateless: true
json_login:
check_path: /login
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/
stateless: true
jwt: ~
access_control:
- { path: ^/$, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI
- { path: ^/docs, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI docs
- { path: ^/login, roles: PUBLIC_ACCESS }
- { path: ^/, roles: PUBLIC_ACCESS }
JwtDecorator.php
<?php
namespace App\OpenApi;
use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\OpenApi\OpenApi;
use ApiPlatform\OpenApi\Model;
final class JwtDecorator implements OpenApiFactoryInterface
{
public function __construct(
private OpenApiFactoryInterface $decorated
) {}
public function __invoke(array $context = []): OpenApi
{
$openApi = ($this->decorated)($context);
$schemas = $openApi->getComponents()->getSchemas();
$schemas['Token'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'token' => [
'type' => 'string',
'readOnly' => true,
],
],
]);
$schemas['Credentials'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'username' => [
'type' => 'string',
'example' => 'test@gmail.com',
],
'password' => [
'type' => 'string',
'example' => '123456',
],
],
]);
$schemas = $openApi->getComponents()->getSecuritySchemes() ?? [];
$schemas['JWT'] = new \ArrayObject([
'type' => 'http',
'scheme' => 'bearer',
'bearerFormat' => 'JWT',
]);
$pathItem = new Model\PathItem(
ref: 'JWT Token',
post: new Model\Operation(
operationId: 'postCredentialsItem',
tags: ['Token'],
responses: [
'200' => [
'description' => 'Get JWT token',
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Token',
],
],
],
],
],
summary: 'Get JWT token to login.',
requestBody: new Model\RequestBody(
description: 'Generate new JWT Token',
content: new \ArrayObject([
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Credentials',
],
],
]),
),
security: [],
),
);
$openApi->getPaths()->addPath('/login', $pathItem);
return $openApi;
}
}
通知类别.php
<?php
namespace App\Entity;
use ...
#[ORM\Entity(repositoryClass: NotificationCategoryRepository::class)]
#[ApiResource(
openapiContext: ['security' => [['Bearer Authentication' => []]]],
security: "is_granted('ROLE_USER')"
)]
class NotificationCategory
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Groups(['read:Notification:get'])]
private ?string $name = null;
#[ORM\OneToMany(mappedBy: 'category', targetEntity: Notification::class)]
private Collection $notifications;
...
}