Я пытаюсь протестировать сценарий, который, с одной стороны, анонимным пользователям следует немедленно отключить от соединения с Websocket, а с другой стороны, аутентифицированные пользователи должны оставаться в соединении с веб-сервером. Первый случай легко проверить, используя код внизу. Процесс аутентификации не работает.
Для хранения сеансов я использую аутентификацию Cookie в сочетании с базой данных: Symfony PDO Session Storage. Все работает нормально, но когда дело доходит до тестирования описанного поведения с использованием аутентификации, я не знаю, как аутентифицировать пользователя в тесте. Как клиент, я использую Pawl асинхронный клиент Websocket. Это выглядит следующим образом:
\Ratchet\Client\connect('ws://127.0.0.1:8080')->then(function($conn) {
$conn->on('message', function($msg) use ($conn) {
echo "Received: {$msg}\n";
});
$conn->send('Hello World!');
}, function ($e) {
echo "Could not connect: {$e->getMessage()}\n";
});
Я знаю, что в качестве третьего параметра я могу передать информацию заголовка методу "connect", но я не могу найти способ, которым клиент подключен, и cookie передается правильно во время рукопожатия ws. Я подумал о чем-то вроде:
- Аутентификация клиента путем создания токена аутентификации
- Я создаю новую запись в таблице сеансов в базе данных с сериализованным пользователем
- Я передаю созданный файл cookie как третий аргумент метода подключения
Это теория, которую я думал, что это сработает, но пользователь всегда остается анонимным на стороне websocket. Вот код к теории до сих пор:
// ...
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class WebsocketTest extends WebTestCase
{
static $closed;
protected function setUp()
{
self::$closed = null;
}
public function testWebsocketConnection()
{
$loop = Factory::create();
$connector = new Connector($loop);
// This user exists in database user tbl
$symfClient = $this->createSession("[email protected]");
$connector('ws://127.0.0.1:80', [], ['Origin' => 'http://127.0.0.1', 'Cookie' =>
$symfClient->getContainer()->get('session')->getName() . '='
. $symfClient->getContainer()->get('session')->getId()])
->then(function(WebSocket $conn) use($loop){
$conn->on('close', function($code = null, $reason = null) use($loop) {
self::$closed = true;
$loop->stop();
});
self::$closed = false;
}, function(\Exception $e) use ($loop) {
$this->fail("Websocket connection failed");
$loop->stop();
});
$loop->run();
// Check, that user stayed logged
$this->assertFalse(self::$closed);
}
private function createSession($email)
{
$client = static::createClient();
$container = $client->getContainer();
$session = $container->get('session');
$session->set('logged', true);
$userManager = $container->get('fos_user.user_manager');
$em = $container->get('doctrine.orm.entity_manager');
$loginManager = $container->get('fos_user.security.login_manager');
$firewallName = 'main';
$user = $userManager->findUserByEmail($email);
$loginManager->loginUser($firewallName, $user);
// save the login token into the session and put it in a cookie
$container->get('session')->set('_security_' . $firewallName,
serialize($container->get('security.token_storage')->getToken()));
$container->get('session')->save();
$client->getCookieJar()->set(new Cookie($session->getName(), $session->getId()));
// Create session in database
$pdo = new PDOSessionStorage();
$pdo->setSessId($session->getId());
$pdo->setSessTime(time());
$pdo->setSessData(serialize($container->get('security.token_storage')->getToken()));
$pdo->setSessLifetime(1440);
$em->persist($pdo);
$em->flush();
return $client;
}
}
Как config_test.yml, я настроил сеанс следующим образом:
session:
storage_id: session.storage.mock_file
handler_id: session.handler.pdo
Для реализации websocket на стороне сервера я использую Ratchet, который обертывается следующим пакетом Symfony: Gos Websocket Bundle
Как аутентифицировать пользователя при тестировании веб-узлов? На сервере websocket пользователь всегда что-то вроде "anon-15468850625756b3b424c94871115670", но когда я тестирую его вручную, он получает правильное соединение.
Дополнительный вопрос (вторичный): как проверить подписку на темы? (PubSub) В Интернете нет записей в блоге или что-то еще.
Обновление: никто никогда не тестировал свои веб-сайты? Является ли это несущественным, бесполезным или почему никто не может помочь в этой важной теме?