Merge pull request #6071 from stephlag:1.3.x
* pr/6071: Polish "Secured HornetQ" contribution Add a secured connection factory for Hornetq.
This commit is contained in:
commit
731d326799
|
|
@ -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(HornetQConnectionFactory.class);
|
.createConnectionFactory(SpringBootHornetQConnectionFactory.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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(ServerLocator.class)
|
Constructor<T> constructor = factoryClass.getDeclaredConstructor(HornetQProperties.class,
|
||||||
.newInstance(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(boolean.class,
|
Constructor<T> constructor = factoryClass.getDeclaredConstructor(HornetQProperties.class,
|
||||||
TransportConfiguration[].class);
|
boolean.class, TransportConfiguration[].class);
|
||||||
return constructor.newInstance(false,
|
return BeanUtils.instantiateClass(constructor, this.properties, false,
|
||||||
new TransportConfiguration[] { transportConfiguration });
|
new TransportConfiguration[] { transportConfiguration });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,6 +50,16 @@ public class HornetQProperties {
|
||||||
*/
|
*/
|
||||||
private int port = 5445;
|
private int port = 5445;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login user of the broker.
|
||||||
|
*/
|
||||||
|
private String user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login password of the broker.
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
private final Embedded embedded = new Embedded();
|
private final Embedded embedded = new Embedded();
|
||||||
|
|
||||||
public HornetQMode getMode() {
|
public HornetQMode getMode() {
|
||||||
|
|
@ -76,6 +86,22 @@ public class HornetQProperties {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUser() {
|
||||||
|
return this.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(String user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return this.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
public Embedded getEmbedded() {
|
public Embedded getEmbedded() {
|
||||||
return this.embedded;
|
return this.embedded;
|
||||||
}
|
}
|
||||||
|
|
@ -188,6 +214,7 @@ public class HornetQProperties {
|
||||||
/**
|
/**
|
||||||
* Creates the minimal transport parameters for an embedded transport
|
* Creates the minimal transport parameters for an embedded transport
|
||||||
* configuration.
|
* configuration.
|
||||||
|
*
|
||||||
* @return the transport parameters
|
* @return the transport parameters
|
||||||
* @see TransportConstants#SERVER_ID_PROP_NAME
|
* @see TransportConstants#SERVER_ID_PROP_NAME
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -20,7 +20,6 @@ import javax.jms.ConnectionFactory;
|
||||||
import javax.transaction.TransactionManager;
|
import javax.transaction.TransactionManager;
|
||||||
|
|
||||||
import org.hornetq.jms.client.HornetQConnectionFactory;
|
import org.hornetq.jms.client.HornetQConnectionFactory;
|
||||||
import org.hornetq.jms.client.HornetQXAConnectionFactory;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.ListableBeanFactory;
|
import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
|
@ -47,16 +46,17 @@ class HornetQXAConnectionFactoryConfiguration {
|
||||||
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" })
|
@Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" })
|
||||||
public ConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory,
|
public ConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory,
|
||||||
HornetQProperties properties, XAConnectionFactoryWrapper wrapper)
|
HornetQProperties properties, XAConnectionFactoryWrapper wrapper)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
return wrapper.wrapConnectionFactory(
|
return wrapper.wrapConnectionFactory(
|
||||||
new HornetQConnectionFactoryFactory(beanFactory, properties)
|
new HornetQConnectionFactoryFactory(beanFactory, properties)
|
||||||
.createConnectionFactory(HornetQXAConnectionFactory.class));
|
.createConnectionFactory(
|
||||||
|
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(HornetQConnectionFactory.class);
|
.createConnectionFactory(SpringBootHornetQConnectionFactory.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.autoconfigure.jms.hornetq;
|
||||||
|
|
||||||
|
import javax.jms.Connection;
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
|
||||||
|
import org.hornetq.api.core.TransportConfiguration;
|
||||||
|
import org.hornetq.api.core.client.ServerLocator;
|
||||||
|
import org.hornetq.jms.client.HornetQConnectionFactory;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link HornetQConnectionFactory} that manages the credentials of the connection.
|
||||||
|
*
|
||||||
|
* @author Stéphane Lagraulet
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
class SpringBootHornetQConnectionFactory extends HornetQConnectionFactory {
|
||||||
|
|
||||||
|
private final HornetQProperties properties;
|
||||||
|
|
||||||
|
SpringBootHornetQConnectionFactory(HornetQProperties properties,
|
||||||
|
ServerLocator serverLocator) {
|
||||||
|
super(serverLocator);
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpringBootHornetQConnectionFactory(HornetQProperties properties, boolean ha,
|
||||||
|
TransportConfiguration... initialConnectors) {
|
||||||
|
super(ha, initialConnectors);
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection createConnection() throws JMSException {
|
||||||
|
String user = this.properties.getUser();
|
||||||
|
if (StringUtils.hasText(user)) {
|
||||||
|
return createConnection(user, this.properties.getPassword());
|
||||||
|
}
|
||||||
|
return super.createConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.autoconfigure.jms.hornetq;
|
||||||
|
|
||||||
|
import javax.jms.Connection;
|
||||||
|
import javax.jms.JMSException;
|
||||||
|
|
||||||
|
import org.hornetq.api.core.TransportConfiguration;
|
||||||
|
import org.hornetq.api.core.client.ServerLocator;
|
||||||
|
import org.hornetq.jms.client.HornetQXAConnectionFactory;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link HornetQXAConnectionFactory} that manages the credentials of the connection.
|
||||||
|
*
|
||||||
|
* @author Stéphane Lagraulet
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
class SpringBootHornetQXAConnectionFactory extends HornetQXAConnectionFactory {
|
||||||
|
|
||||||
|
private final HornetQProperties properties;
|
||||||
|
|
||||||
|
SpringBootHornetQXAConnectionFactory(HornetQProperties properties,
|
||||||
|
ServerLocator serverLocator) {
|
||||||
|
super(serverLocator);
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpringBootHornetQXAConnectionFactory(HornetQProperties properties, boolean ha,
|
||||||
|
TransportConfiguration... initialConnectors) {
|
||||||
|
super(ha, initialConnectors);
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection createConnection() throws JMSException {
|
||||||
|
String user = this.properties.getUser();
|
||||||
|
if (StringUtils.hasText(user)) {
|
||||||
|
return createConnection(user, this.properties.getPassword());
|
||||||
|
}
|
||||||
|
return super.createConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue