Polish "Secured HornetQ" contribution

Closes gh-6071
This commit is contained in:
Stephane Nicoll 2016-06-16 19:09:35 +02:00
parent 1aa8f49001
commit 8b79c667a7
9 changed files with 114 additions and 80 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -39,7 +39,7 @@ class HornetQConnectionFactoryConfiguration {
public HornetQConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory, public HornetQConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory,
HornetQProperties properties) { HornetQProperties properties) {
return new HornetQConnectionFactoryFactory(beanFactory, properties) return new HornetQConnectionFactoryFactory(beanFactory, properties)
.createConnectionFactory(HornetQSecuredConnectionFactory.class); .createConnectionFactory(SpringBootHornetQConnectionFactory.class);
} }
} }

View File

@ -28,6 +28,7 @@ import org.hornetq.core.remoting.impl.netty.NettyConnectorFactory;
import org.hornetq.core.remoting.impl.netty.TransportConstants; import org.hornetq.core.remoting.impl.netty.TransportConstants;
import org.hornetq.jms.client.HornetQConnectionFactory; import org.hornetq.jms.client.HornetQConnectionFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@ -111,8 +112,9 @@ class HornetQConnectionFactoryFactory {
this.properties.getEmbedded().generateTransportParameters()); this.properties.getEmbedded().generateTransportParameters());
ServerLocator serviceLocator = HornetQClient ServerLocator serviceLocator = HornetQClient
.createServerLocatorWithoutHA(transportConfiguration); .createServerLocatorWithoutHA(transportConfiguration);
return factoryClass.getConstructor(HornetQProperties.class, ServerLocator.class) Constructor<T> constructor = factoryClass.getDeclaredConstructor(HornetQProperties.class,
.newInstance(this.properties, serviceLocator); ServerLocator.class);
return BeanUtils.instantiateClass(constructor, this.properties, serviceLocator);
} }
catch (NoClassDefFoundError ex) { catch (NoClassDefFoundError ex) {
throw new IllegalStateException("Unable to create InVM " throw new IllegalStateException("Unable to create InVM "
@ -128,9 +130,9 @@ class HornetQConnectionFactoryFactory {
params.put(TransportConstants.PORT_PROP_NAME, this.properties.getPort()); params.put(TransportConstants.PORT_PROP_NAME, this.properties.getPort());
TransportConfiguration transportConfiguration = new TransportConfiguration( TransportConfiguration transportConfiguration = new TransportConfiguration(
NettyConnectorFactory.class.getName(), params); NettyConnectorFactory.class.getName(), params);
Constructor<T> constructor = factoryClass.getConstructor(HornetQProperties.class, Constructor<T> constructor = factoryClass.getDeclaredConstructor(HornetQProperties.class,
boolean.class, TransportConfiguration[].class); boolean.class, TransportConfiguration[].class);
return constructor.newInstance(this.properties, false, return BeanUtils.instantiateClass(constructor, this.properties, false,
new TransportConfiguration[] { transportConfiguration }); new TransportConfiguration[] { transportConfiguration });
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -51,12 +51,12 @@ public class HornetQProperties {
private int port = 5445; private int port = 5445;
/** /**
* User for a secured connection. * Login user of the broker.
*/ */
private String user; private String user;
/** /**
* Password for a secured connection. * Login password of the broker.
*/ */
private String password; private String password;
@ -86,10 +86,6 @@ public class HornetQProperties {
this.port = port; this.port = port;
} }
public Embedded getEmbedded() {
return this.embedded;
}
public String getUser() { public String getUser() {
return this.user; return this.user;
} }
@ -106,6 +102,10 @@ public class HornetQProperties {
this.password = password; this.password = password;
} }
public Embedded getEmbedded() {
return this.embedded;
}
/** /**
* Configuration for an embedded HornetQ server. * Configuration for an embedded HornetQ server.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -50,13 +50,13 @@ class HornetQXAConnectionFactoryConfiguration {
return wrapper.wrapConnectionFactory( return wrapper.wrapConnectionFactory(
new HornetQConnectionFactoryFactory(beanFactory, properties) new HornetQConnectionFactoryFactory(beanFactory, properties)
.createConnectionFactory( .createConnectionFactory(
HornetQXASecuredConnectionFactory.class)); SpringBootHornetQXAConnectionFactory.class));
} }
@Bean @Bean
public HornetQConnectionFactory nonXaJmsConnectionFactory( public HornetQConnectionFactory nonXaJmsConnectionFactory(
ListableBeanFactory beanFactory, HornetQProperties properties) { ListableBeanFactory beanFactory, HornetQProperties properties) {
return new HornetQConnectionFactoryFactory(beanFactory, properties) return new HornetQConnectionFactoryFactory(beanFactory, properties)
.createConnectionFactory(HornetQSecuredConnectionFactory.class); .createConnectionFactory(SpringBootHornetQConnectionFactory.class);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,32 +23,36 @@ import org.hornetq.api.core.TransportConfiguration;
import org.hornetq.api.core.client.ServerLocator; import org.hornetq.api.core.client.ServerLocator;
import org.hornetq.jms.client.HornetQConnectionFactory; import org.hornetq.jms.client.HornetQConnectionFactory;
import org.springframework.util.StringUtils;
/** /**
* Secured HornetQ implementation of a JMS ConnectionFactory. * A {@link HornetQConnectionFactory} that manages the credentials of the connection.
* *
* @author Stéphane Lagraulet * @author Stéphane Lagraulet
* * @author Stephane Nicoll
* @since 1.4.0
*
*/ */
public class HornetQSecuredConnectionFactory extends HornetQConnectionFactory { class SpringBootHornetQConnectionFactory extends HornetQConnectionFactory {
private HornetQProperties properties; private final HornetQProperties properties;
public HornetQSecuredConnectionFactory(HornetQProperties properties, SpringBootHornetQConnectionFactory(HornetQProperties properties,
final ServerLocator serverLocator) { ServerLocator serverLocator) {
super(serverLocator); super(serverLocator);
this.properties = properties; this.properties = properties;
} }
public HornetQSecuredConnectionFactory(HornetQProperties properties, final boolean ha, SpringBootHornetQConnectionFactory(HornetQProperties properties, boolean ha,
final TransportConfiguration... initialConnectors) { TransportConfiguration... initialConnectors) {
super(ha, initialConnectors); super(ha, initialConnectors);
this.properties = properties; this.properties = properties;
} }
public Connection createConnection() throws JMSException { public Connection createConnection() throws JMSException {
return createConnection(this.properties.getUser(), this.properties.getPassword()); String user = this.properties.getUser();
if (StringUtils.hasText(user)) {
return createConnection(user, this.properties.getPassword());
}
return super.createConnection();
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,32 +23,36 @@ import org.hornetq.api.core.TransportConfiguration;
import org.hornetq.api.core.client.ServerLocator; import org.hornetq.api.core.client.ServerLocator;
import org.hornetq.jms.client.HornetQXAConnectionFactory; import org.hornetq.jms.client.HornetQXAConnectionFactory;
import org.springframework.util.StringUtils;
/** /**
* Secured HornetQ XA implementation of a JMS ConnectionFactory. * A {@link HornetQXAConnectionFactory} that manages the credentials of the connection.
* *
* @author Stéphane Lagraulet * @author Stéphane Lagraulet
* * @author Stephane Nicoll
* @since 1.4.0
*
*/ */
public class HornetQXASecuredConnectionFactory extends HornetQXAConnectionFactory { class SpringBootHornetQXAConnectionFactory extends HornetQXAConnectionFactory {
private HornetQProperties properties; private final HornetQProperties properties;
public HornetQXASecuredConnectionFactory(HornetQProperties properties, SpringBootHornetQXAConnectionFactory(HornetQProperties properties,
ServerLocator serverLocator) { ServerLocator serverLocator) {
super(serverLocator); super(serverLocator);
this.properties = properties; this.properties = properties;
} }
public HornetQXASecuredConnectionFactory(HornetQProperties properties, boolean ha, SpringBootHornetQXAConnectionFactory(HornetQProperties properties, boolean ha,
TransportConfiguration... initialConnectors) { TransportConfiguration... initialConnectors) {
super(ha, initialConnectors); super(ha, initialConnectors);
this.properties = properties; this.properties = properties;
} }
public Connection createConnection() throws JMSException { public Connection createConnection() throws JMSException {
return createConnection(this.properties.getUser(), this.properties.getPassword()); String user = this.properties.getUser();
if (StringUtils.hasText(user)) {
return createConnection(user, this.properties.getPassword());
}
return super.createConnection();
} }
} }

View File

@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.UUID; import java.util.UUID;
import javax.jms.Connection;
import javax.jms.Destination; import javax.jms.Destination;
import javax.jms.JMSException; import javax.jms.JMSException;
import javax.jms.Message; import javax.jms.Message;
@ -55,6 +56,9 @@ import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.jms.support.destination.DynamicDestinationResolver; import org.springframework.jms.support.destination.DynamicDestinationResolver;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
/** /**
* Tests for {@link HornetQAutoConfiguration}. * Tests for {@link HornetQAutoConfiguration}.
@ -94,6 +98,22 @@ public class HornetQAutoConfigurationTests {
assertNettyConnectionFactory(connectionFactory, "192.168.1.144", 9876); assertNettyConnectionFactory(connectionFactory, "192.168.1.144", 9876);
} }
@Test
public void nativeConnectionFactoryCredentials() throws JMSException {
load(EmptyConfiguration.class, "spring.hornetq.mode:native",
"spring.hornetq.user:user", "spring.hornetq.password:secret");
HornetQConnectionFactory connectionFactory = this.context
.getBean(HornetQConnectionFactory.class);
// Validate the secured variant is invoked
HornetQConnectionFactory testCf = spy(connectionFactory);
Connection connection = mock(Connection.class);
doReturn(connection).when(testCf).createConnection("user", "secret");
Connection actual = testCf.createConnection();
assertThat(actual).isSameAs(connection);
}
@Test @Test
public void embeddedConnectionFactory() { public void embeddedConnectionFactory() {
load(EmptyConfiguration.class, "spring.hornetq.mode:embedded"); load(EmptyConfiguration.class, "spring.hornetq.mode:embedded");

View File

@ -848,7 +848,9 @@ content into your application; rather pick only the properties that you need.
spring.hornetq.embedded.topics= # Comma-separated list of topics to create on startup. spring.hornetq.embedded.topics= # Comma-separated list of topics to create on startup.
spring.hornetq.host=localhost # HornetQ broker host. spring.hornetq.host=localhost # HornetQ broker host.
spring.hornetq.mode= # HornetQ deployment mode, auto-detected by default. Can be explicitly set to "native" or "embedded". spring.hornetq.mode= # HornetQ deployment mode, auto-detected by default. Can be explicitly set to "native" or "embedded".
spring.hornetq.password= # Login password of the broker.
spring.hornetq.port=5445 # HornetQ broker port. spring.hornetq.port=5445 # HornetQ broker port.
spring.hornetq.user= # Login user of the broker.
# JMS ({sc-spring-boot-autoconfigure}/jms/JmsProperties.{sc-ext}[JmsProperties]) # JMS ({sc-spring-boot-autoconfigure}/jms/JmsProperties.{sc-ext}[JmsProperties])
spring.jms.jndi-name= # Connection factory JNDI name. When set, takes precedence to others connection factory auto-configurations. spring.jms.jndi-name= # Connection factory JNDI name. When set, takes precedence to others connection factory auto-configurations.

View File

@ -3953,6 +3953,8 @@ HornetQ configuration is controlled by external configuration properties in
spring.hornetq.mode=native spring.hornetq.mode=native
spring.hornetq.host=192.168.1.210 spring.hornetq.host=192.168.1.210
spring.hornetq.port=9876 spring.hornetq.port=9876
spring.hornetq.user=admin
spring.hornetq.password=secret
---- ----
When embedding the broker, you can choose if you want to enable persistence, and the list When embedding the broker, you can choose if you want to enable persistence, and the list