/*
* Copyright (c) 2011-2015 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.ext.stomp.impl;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.NetSocket;
import io.vertx.ext.auth.AuthProvider;
import io.vertx.ext.auth.shiro.ShiroAuth;
import io.vertx.ext.auth.shiro.ShiroAuthOptions;
import io.vertx.ext.auth.shiro.ShiroAuthRealmType;
import io.vertx.ext.stomp.*;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.RunTestOnContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests STOMP server with security.
*
* @author <a href="http://escoffier.me">Clement Escoffier</a>
*/
@RunWith(VertxUnitRunner.class)
public class SecuredServerConnectionTest {
private Vertx vertx;
private StompServer server;
@Rule
public RunTestOnContext rule = new RunTestOnContext();
@Before
public void setUp(TestContext context) {
vertx = rule.vertx();
JsonObject config = new JsonObject().put("properties_path", "classpath:test-auth.properties");
AuthProvider provider = ShiroAuth.create(vertx, new ShiroAuthOptions().setType(ShiroAuthRealmType.PROPERTIES).setConfig(config));
server = StompServer.create(vertx, new StompServerOptions().setSecured(true))
.handler(StompServerHandler.create(vertx).authProvider(provider))
.listen(context.asyncAssertSuccess());
}
@After
public void tearDown(TestContext context) {
server.close(context.asyncAssertSuccess());
// Do not close the vert.x instance when using the RunTestOnContext rule.
}
@Test
public void testAuthenticatedConnection(TestContext context) {
Async async = context.async();
vertx.createNetClient().connect(server.actualPort(), "0.0.0.0", result -> {
if (result.failed()) {
context.fail("Connection failed");
return;
}
NetSocket socket = result.result();
socket.handler(buffer -> {
context.assertTrue(buffer.toString().contains("CONNECTED"));
context.assertTrue(buffer.toString().contains("version:1.2"));
async.complete();
});
socket.write("CONNECT\n" + "accept-version:1.2\nlogin:admin\npasscode:admin\n" + "\n" + FrameParser.NULL);
});
}
@Test
public void testFailedAuthentication(TestContext context) {
Async async = context.async();
vertx.createNetClient().connect(server.actualPort(), "0.0.0.0", result -> {
if (result.failed()) {
context.fail("Connection failed");
return;
}
NetSocket socket = result.result();
socket.handler(buffer -> {
context.assertTrue(buffer.toString().contains("ERROR"));
context.assertTrue(buffer.toString().contains("Authentication failed"));
async.complete();
});
socket.write("CONNECT\n" + "accept-version:1.2\nlogin:admin\npasscode:nope\n" + "\n" + FrameParser.NULL);
});
}
@Test(timeout = 5000)
public void testFailedAuthenticationBecauseOfMissingHeaders(TestContext context) {
Async async = context.async();
vertx.createNetClient().connect(server.actualPort(), "0.0.0.0", result -> {
if (result.failed()) {
context.fail("Connection failed");
return;
}
NetSocket socket = result.result();
socket.handler(buffer -> {
context.assertTrue(buffer.toString().contains("ERROR"));
context.assertTrue(buffer.toString().contains("Authentication failed"));
async.complete();
});
socket.write("CONNECT\n" + "accept-version:1.2\nlogin:admin\n" + "\n" + FrameParser.NULL);
});
}
@Test
public void testAuthenticatedConnectionWithStompFrame(TestContext context) {
Async async = context.async();
vertx.createNetClient().connect(server.actualPort(), "0.0.0.0", result -> {
if (result.failed()) {
context.fail("Connection failed");
return;
}
NetSocket socket = result.result();
socket.handler(buffer -> {
context.assertTrue(buffer.toString().contains("CONNECTED"));
context.assertTrue(buffer.toString().contains("version:1.2"));
async.complete();
});
socket.write("STOMP\n" + "accept-version:1.2\nlogin:admin\npasscode:admin\n" + "\n" + FrameParser.NULL);
});
}
@Test
public void testFailedAuthenticationWithClient(TestContext context) {
Async async = context.async();
StompClient client = StompClient.create(vertx, new StompClientOptions()
.setPort(server.actualPort()).setHost("0.0.0.0").setLogin("admin").setPasscode("nope"))
.errorFrameHandler(frame -> {
async.complete();
});
client.connect(connection -> {
context.fail("Authentication issue expected");
});
}
}