Je suis en train de tester un scénario, que, d'une part, les utilisateurs anonymes doivent obtenir immédiatement un déconnecter une connexion Websocket et, d'autre part, les utilisateurs authentifiés doivent rester dans la connexion websocket. Le premier cas est facilement vérifiable en utilisant le code down under. Le processus d'authentification ne fonctionne pas.
Pour le stockage de session, je suis à l'aide de l'authentification par Cookie en combinaison avec une base de données: Symfony AOP de Stockage de Session. Ça fonctionne bien, mais quand il s'agit de tester le comportement décrit par l'utilisation de l'authentification, je ne sais pas comment authentifier l'utilisateur dans un test. En tant que client, je suis à l'aide de Cliquet asynchrone client Websocket. Cela ressemble à la suivante:
\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";
});
Je sais que d'un troisième paramètre, je peux passer des informations d'en-tête de la "connexion" de la méthode, mais je ne peux pas trouver un moyen pour que le client est connecté et le cookie est transmis correctement au cours de la ws poignée de main. J'ai pensé à quelque chose comme:
- Authentifier un client par la création d'un jeton d'authentification
- J'ai créer une nouvelle entrée dans la table de session dans la base de données avec un utilisateur
- Je passe le cookie créé en tant que troisième argument de la méthode de connexion,
C'est la théorie que je pensais qui serait à l'œuvre, mais l'utilisateur reste toujours anonyme sur websocket côté. Voici le code de la théorie de la mesure:
// ...
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("testuser@test.com");
$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;
}
}
Comme config_test.yml, j'ai configuré la session de la manière suivante:
session:
storage_id: session.storage.mock_file
handler_id: session.handler.pdo
Pour le côté serveur websocket mise en œuvre, je suis en utilisant la clé à Cliquet, qui est d'être enveloppé par la suite bundle Symfony: Gos Websocket Bundle
Comment authentifier l'utilisateur lors de l'essai de websockets? Sur le serveur websocket, l'utilisateur est toujours quelque chose comme "anon-15468850625756b3b424c94871115670", mais quand j'ai tester manuellement, il est connecté correcte.
Question supplémentaire (secondaire): Comment tester l'abonnement à des sujets? (pubsub) Il n'y a pas des entrées de blog ou quoi que ce soit d'autre à ce sujet sur l'internet.
Mise à jour: personne N'a jamais fonctionnel testé leur websockets? Est-ce sans importance, inutiles ou pourquoi ne peut-on aider sur ce sujet important?