phpunit 测试用例中的基本身份验证
Basic Authentication in phpunit test case
我想到了在我的小脚本中使用 Basic Auth 的绝妙想法,因为我认为它会比使用 jwt 更快……我错了。我现在无法测试我的端点,因为我经常收到 401。
下面的源代码也可以在这里找到:https://github.com/tarach/blog-api/tree/feature/posts-resource-test
public function testShouldCreatePost(): void
{
$client = static::createClient();
$headers = [
'Content-Type' => 'application/json',
'Authorization' => 'Basic ' . base64_encode('test:qwe123'),
];
dump($headers);
$client->request('POST', '/api/posts', [
'headers' => $headers,
'json' => [],
]);
dump([
'response' => [
'status' => $client->getResponse()->getStatusCode(),
'body' => $client->getResponse()->getContent(),
],
]);
}
security.yaml
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
App\Infrastructure\Symfony\User\EnvironmentUser:
algorithm: plaintext
providers:
environment_user_provider:
id: App\Infrastructure\Symfony\User\EnvironmentUserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/api
stateless: true
anonymous: true
provider: environment_user_provider
http_basic:
realm: Protected
access_control:
- { path: ^/api/posts, methods: ["GET"], roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/docs, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
EnvironmentUserProvider 使用两个环境。变量 USER_NAME 和 USER_PASSWORD。
通过 Postman 它可以正常工作:
解决方案:
public function testShouldCreatePost(): void
{
// Method A)
$client = static::createClient([], [
'PHP_AUTH_USER' => 'test',
'PHP_AUTH_PW' => 'qwe123',
]);
// Method B)
$client->setServerParameter('HTTP_AUTHORIZATION', 'Basic ' . base64_encode('test:qwe123'));
$content = json_encode([
'title' => 'Some title',
'body' => '<strong>Some Body</strong>'
]);
$client->request(
'POST',
'/api/posts',
[],
[],
[
'CONTENT_TYPE' => 'application/json',
],
$content
);
$this->assertEquals(201, $client->getResponse()->getStatusCode());
}
如果您使用最新的 Symfony 版本(5.1 或更高版本),您可以使用客户端上的简洁助手:
$client = static::createClient();
$userRepository = static::$container->get(UserRepository::class);
// retrieve the test user
$testUser = $userRepository->findOneByEmail('john.doe@example.com');
// simulate $testUser being logged in
$client->loginUser($testUser);
// test e.g. the profile page
$client->request('GET', '/profile');
示例取自 Logging in Users in Tests.
的文档
如果您使用基本身份验证,您可以像这样为身份验证对话框传递凭据:
$client = static::createClient([], [
'PHP_AUTH_USER' => 'username',
'PHP_AUTH_PW' => 'pa$$word',
]);
如 How to Simulate HTTP Authentication in a Functional Test.
的旧文档中所示
如果您想提交示例中的 headers,事情会有点棘手,因为您需要传入内部表示,如 BrowserKit Browser.[=17 中所示=]
在您的情况下,headers 可能应该像这样更改:
$headers = [
'CONTENT_TYPE' => 'application/json',
'HTTP_AUTHORIZATION' => 'Basic ' . base64_encode('test:qwe123'),
];
您可以看到 Symfony 在 HttpFoundation ServerBag.
的代码中使用了哪种内部表示
我想到了在我的小脚本中使用 Basic Auth 的绝妙想法,因为我认为它会比使用 jwt 更快……我错了。我现在无法测试我的端点,因为我经常收到 401。
下面的源代码也可以在这里找到:https://github.com/tarach/blog-api/tree/feature/posts-resource-test
public function testShouldCreatePost(): void
{
$client = static::createClient();
$headers = [
'Content-Type' => 'application/json',
'Authorization' => 'Basic ' . base64_encode('test:qwe123'),
];
dump($headers);
$client->request('POST', '/api/posts', [
'headers' => $headers,
'json' => [],
]);
dump([
'response' => [
'status' => $client->getResponse()->getStatusCode(),
'body' => $client->getResponse()->getContent(),
],
]);
}
security.yaml
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
App\Infrastructure\Symfony\User\EnvironmentUser:
algorithm: plaintext
providers:
environment_user_provider:
id: App\Infrastructure\Symfony\User\EnvironmentUserProvider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/api
stateless: true
anonymous: true
provider: environment_user_provider
http_basic:
realm: Protected
access_control:
- { path: ^/api/posts, methods: ["GET"], roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/docs, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
EnvironmentUserProvider 使用两个环境。变量 USER_NAME 和 USER_PASSWORD。
通过 Postman 它可以正常工作:
解决方案:
public function testShouldCreatePost(): void
{
// Method A)
$client = static::createClient([], [
'PHP_AUTH_USER' => 'test',
'PHP_AUTH_PW' => 'qwe123',
]);
// Method B)
$client->setServerParameter('HTTP_AUTHORIZATION', 'Basic ' . base64_encode('test:qwe123'));
$content = json_encode([
'title' => 'Some title',
'body' => '<strong>Some Body</strong>'
]);
$client->request(
'POST',
'/api/posts',
[],
[],
[
'CONTENT_TYPE' => 'application/json',
],
$content
);
$this->assertEquals(201, $client->getResponse()->getStatusCode());
}
如果您使用最新的 Symfony 版本(5.1 或更高版本),您可以使用客户端上的简洁助手:
$client = static::createClient();
$userRepository = static::$container->get(UserRepository::class);
// retrieve the test user
$testUser = $userRepository->findOneByEmail('john.doe@example.com');
// simulate $testUser being logged in
$client->loginUser($testUser);
// test e.g. the profile page
$client->request('GET', '/profile');
示例取自 Logging in Users in Tests.
的文档如果您使用基本身份验证,您可以像这样为身份验证对话框传递凭据:
$client = static::createClient([], [
'PHP_AUTH_USER' => 'username',
'PHP_AUTH_PW' => 'pa$$word',
]);
如 How to Simulate HTTP Authentication in a Functional Test.
的旧文档中所示如果您想提交示例中的 headers,事情会有点棘手,因为您需要传入内部表示,如 BrowserKit Browser.[=17 中所示=]
在您的情况下,headers 可能应该像这样更改:
$headers = [
'CONTENT_TYPE' => 'application/json',
'HTTP_AUTHORIZATION' => 'Basic ' . base64_encode('test:qwe123'),
];
您可以看到 Symfony 在 HttpFoundation ServerBag.
的代码中使用了哪种内部表示