JMS over SSL: Client starting STARTTLS but channel doesn't support SSL
ybxiang.china Oct 5, 2012 3:02 AMDear jboss guys,
My client has a problem about JMS over SSL: Client starting STARTTLS but channel doesn't support SSL.
Please help me.
Thank you in advance.
1. standalone.xml
I copied standalone-full.xml to standalone.xml, then modifed it.
Please refer to the attachment for details.
I post management and JMS related configuration here:
<management> | |
<security-realms> | |
<security-realm name="ManagementRealm"> | |
<authentication> | |
<local default-user="$local"/> | |
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/> | |
</authentication> | |
</security-realm> | |
<security-realm name="ApplicationRealm"> | |
<server-identities> | |
<ssl> | |
<keystore path="server.keystore" relative-to="jboss.server.config.dir" keystore-password="ybxiang_keystore_password"/> | |
</ssl> | |
</server-identities> | |
<authentication> | |
<jaas name="nms-jaas-security-domain"/> | |
</authentication> | |
</security-realm> | |
</security-realms> | |
<management-interfaces> | |
<native-interface security-realm="ManagementRealm"> | |
<socket-binding native="management-native"/> | |
</native-interface> | |
<http-interface security-realm="ManagementRealm"> | |
<socket-binding http="management-http"/> | |
</http-interface> | |
</management-interfaces> | |
</management> |
...
<subsystem xmlns="urn:jboss:domain:messaging:1.3"> | ||||||
<hornetq-server> | ||||||
<persistence-enabled>true</persistence-enabled> | ||||||
<journal-file-size>102400</journal-file-size> | ||||||
<journal-min-files>2</journal-min-files> | ||||||
<connectors> | ||||||
<netty-connector name="netty-ssl-connector" socket-binding="messaging"> | ||||||
<param key="ssl-enabled" value="true"/> | ||||||
<param key="key-store-path" value="server.keystore"/> | ||||||
<param key="key-store-password" value="ybxiang_keystore_password"/> | ||||||
</netty-connector> | ||||||
<netty-connector name="netty-throughput" socket-binding="messaging-throughput"> | ||||||
<param key="batch-delay" value="50"/> | ||||||
</netty-connector> | ||||||
<in-vm-connector name="in-vm" server-id="0"/> | ||||||
</connectors> | ||||||
<acceptors> | ||||||
<netty-acceptor name="netty-ssl-acceptor" socket-binding="messaging"> | ||||||
<param key="ssl-enabled" value="true"/> | ||||||
<param key="key-store-path" value="server.keystore"/> | ||||||
<param key="key-store-password" value="ybxiang_keystore_password"/> | ||||||
<param key="trust-store-path" value="client.truststore"/> | ||||||
<param key="trust-store-password" value="ybxiang_truststore_password"/> | ||||||
</netty-acceptor> | ||||||
<netty-acceptor name="netty-throughput" socket-binding="messaging-throughput"> | ||||||
<param key="batch-delay" value="50"/> | ||||||
<param key="direct-deliver" value="false"/> | ||||||
</netty-acceptor> | ||||||
<in-vm-acceptor name="in-vm" server-id="0"/> | ||||||
</acceptors> | ||||||
<security-settings> | ||||||
<security-setting match="#"> | ||||||
<permission type="send" roles="guest"/> | ||||||
<permission type="consume" roles="guest"/> | ||||||
<permission type="createNonDurableQueue" roles="guest"/> | ||||||
<permission type="deleteNonDurableQueue" roles="guest"/> | ||||||
</security-setting> | ||||||
</security-settings> | ||||||
<address-settings> | ||||||
<!--default for catch all--> | ||||||
<address-setting match="#"> | ||||||
<dead-letter-address>jms.queue.DLQ</dead-letter-address> | ||||||
<expiry-address>jms.queue.ExpiryQueue</expiry-address> | ||||||
<redelivery-delay>0</redelivery-delay> | ||||||
<max-size-bytes>10485760</max-size-bytes> | ||||||
<address-full-policy>BLOCK</address-full-policy> | ||||||
<message-counter-history-day-limit>10</message-counter-history-day-limit> | ||||||
</address-setting> | ||||||
</address-settings> | ||||||
<jms-connection-factories> | ||||||
<connection-factory name="InVmConnectionFactory"> | ||||||
<connectors> | ||||||
<connector-ref connector-name="in-vm"/> | ||||||
</connectors> | ||||||
<entries> | ||||||
<entry name="java:/ConnectionFactory"/> | ||||||
</entries> | ||||||
</connection-factory> | ||||||
<connection-factory name="RemoteConnectionFactory"> | ||||||
<connectors> | ||||||
<connector-ref connector-name="netty-ssl-connector"/> | ||||||
</connectors> | ||||||
<entries> | ||||||
<entry name="java:jboss/exported/jms/RemoteConnectionFactory"/> | ||||||
</entries> | ||||||
</connection-factory> | ||||||
<pooled-connection-factory name="hornetq-ra"> | ||||||
<transaction mode="xa"/> | ||||||
<connectors> | ||||||
<connector-ref connector-name="in-vm"/> | ||||||
</connectors> | ||||||
<entries> | ||||||
<entry name="java:/JmsXA"/> | ||||||
</entries> | ||||||
</pooled-connection-factory> | ||||||
</jms-connection-factories> | ||||||
<jms-destinations> | ||||||
<jms-queue name="testQueue"> | ||||||
<entry name="queue/test"/> | ||||||
<entry name="java:jboss/exported/jms/queue/test"/> | ||||||
</jms-queue> | ||||||
<jms-topic name="testTopic"> | ||||||
<entry name="topic/test"/> | ||||||
<entry name="java:jboss/exported/jms/topic/test"/> | ||||||
</jms-topic> | ||||||
</jms-destinations> | ||||||
</hornetq-server> | ||||||
</subsystem> |
2. I put client.truststore and server.keystore in both
jboss-as-7.2.0.Alpha1\standalone\configuration (for ApplicationRealm)
and
jboss-as-7.2.0.Alpha1\bin (for messaging)
3. I can send message through an ejb and receive it through an MDB successfully:
@Local(ITestQueueSender.class) @Singleton @Startup public class TestQueueSender implements ITestQueueSender { Logger log = Logger.getLogger(TestQueueSender.class); @SuppressWarnings("unused") @Resource private SessionContext sessionContext; @Resource TimerService timerService; @PersistenceContext protected EntityManager em; @PostConstruct public void createTimer() { log.info("==>starting TestQueueSender timer..."); timerService.createIntervalTimer(15000L, 3600000,// intervalDuration new TimerConfig(null, false) ); log.info("==>timer TestQueueSender started!!!"); } @Timeout public void timeout() { try { sendMessageMethod1(); } catch (Exception e) { log.error(e); } } private void sendMessageMethod1() { Context context = null; ConnectionFactory connectionFactory = null; Connection connection = null; // try { context = new InitialContext(); /** * 如何获取JBoss 7 中的连接工厂,请参见: * http://stackoverflow.com/questions/7515220/how-to-get-the-new-jndi-names-esp-connectionfactory */ connectionFactory = (ConnectionFactory) context.lookup("java:/ConnectionFactory"); Queue queue = (Queue) context.lookup("queue/test"); connection = connectionFactory.createConnection(); Session session = connection.createSession( false,//transacted Session.AUTO_ACKNOWLEDGE); MessageProducer publisher = session.createProducer(queue); connection.start(); String message = "Hello AS 7(method1) !"; TextMessage textMessage = session.createTextMessage(message); publisher.send(textMessage); log.info("Message is sent: "+message); } catch (Exception exc) { exc.printStackTrace(); } finally { if (connection != null) { try { connection.close(); } catch (JMSException e) { e.printStackTrace(); } } } } } @MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/test"), //@ActivationConfigProperty(propertyName="messageSelector",propertyValue="MessageFormat = 'Version 3.4'"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") } ) public class TestQueueMDB implements MessageListener { Logger log = Logger.getLogger(TestQueueMDB.class); @PostConstruct public void init() { //log.info("TestQueueMDB.init..."); } @PreDestroy public void cleanup( ) { //log.info("TestQueueMDB.cleanup..."); } @Override public void onMessage(Message message) { TextMessage tm = (TextMessage) message; try { System.out.println("Received message " + tm.getText()); } catch (JMSException e) { e.printStackTrace(); } } }
After JBoss AS is started, It print bellow log:
14:34:35,484 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: JBoss AS 7.2.0.Alpha1-SNAPSHOT "Steropes" started in 13797ms - Started 538 of 627 services (87 services are passive or on-demand) 14:34:48,046 INFO [com.ybxiang.nms.ejb.jms.demo.TestQueueSender] (EJB default - 3) Message is sent: Hello AS 7(method1) ! 14:34:48,078 INFO [stdout] (Thread-1 (HornetQ-client-global-threads-4846268)) Received message Hello AS 7(method1) !
This mean my JMS configuration is correct.
4. But now, my client can NOT find "jms/RemoteConnectionFactory" successfully.
4.1 My client code:
public class MyClient{ ... public void connectToServer(String serverIP, String username, String password) throws Exception{ this.username = username; this.serverIP = serverIP; InitialContext context; try{ Properties p = new Properties(); p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "true"); p.put("remote.connections", "default"); p.put("remote.connection.default.host", serverIP); p.put("remote.connection.default.port", "4447"); p.put("remote.connection.default.username", username); p.put("remote.connection.default.password", password); p.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false"); p.put("remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS", "JBOSS-LOCAL-USER"); p.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false"); p.put("remote.connection.default.connect.options.org.xnio.Options.SSL_STARTTLS", "true"); p.put("remote.connection.default.connect.timeout", "30000");//for xnio EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(p); ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc); EJBClientContext.setSelector(selector); EJBClientContext.getCurrent().registerInterceptor(0,new ClientSessionTokenInterceptor()); EJBClientContext.getCurrent().registerInterceptor(1,new ClientExceptionInterceptor()); Properties props = new Properties(); props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); context = new InitialContext(props); securedRemoteSessionProxy = (ISecuredRemoteSession)context.lookup(jndiName); }catch(Exception e){ throw ConnectionToServerFailedException.INSTANCE; } shakeHands(username, password);//fetch initial data from server. testJms2(context,username,password); } public static void testJms2(InitialContext context, String username, String password) throws Exception { ConnectionFactory connectionFactory = null; Destination destination = null; try { connectionFactory = (ConnectionFactory) context.lookup("jms/RemoteConnectionFactory"); destination = (Destination) context.lookup("jms/queue/test"); // sendJmsMessage(connectionFactory,destination,username,password); } catch (Exception e) { log.error(e); } } public static void sendJmsMessage(ConnectionFactory connectionFactory, Destination destination, String username, String password){ Connection connection = null; Session session = null; MessageProducer producer = null; MessageConsumer consumer = null; TextMessage message = null; try { // Create the JMS connection, session, producer, and consumer connection = connectionFactory.createConnection(username,password); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); producer = session.createProducer(destination); consumer = session.createConsumer(destination); connection.start(); int count = 1; String content = "Hellow World!"; log.info("Sending " + count + " messages with content: " + content); // Send the specified number of messages for (int i = 0; i < count; i++) { message = session.createTextMessage(content); producer.send(message); } // Then receive the same number of messaes that were sent for (int i = 0; i < count; i++) { message = (TextMessage) consumer.receive(5000); log.info("Received message with content " + message.getText()); } } catch (Exception e) { log.error(e); } finally { if (connection != null) { try{ connection.close(); }catch(Exception e){ log.error(e); } } } } }
VM arguments:
-Djavax.net.ssl.trustStore=D:\\java\\jboss-as-7.2.0.Alpha1\\standalone\\configuration\\client.truststore -Djavax.net.ssl.trustStorePassword=ybxiang_truststore_password
The client can fetch initial data though EJB calling from the jboss as successfully.
But it can NOT find the jms connection factory:
"javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial"
Now, I change
Properties props = new Properties(); | ||
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); | ||
context = new InitialContext(props); |
to
Properties props = new Properties(); | ||
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); | ||
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory"); | ||
props.put(Context.PROVIDER_URL, System.getProperty(Context.PROVIDER_URL, "remote://"+serverIP+":4447")); | ||
props.put(Context.SECURITY_PRINCIPAL, username); | ||
props.put(Context.SECURITY_CREDENTIALS, password); | ||
context = new InitialContext(props); |
This time, I got bellow Exception:
org.jboss.remoting.remote.connection: "JBREM000200: Remote connection failed: java.io.IOException: Client starting STARTTLS but channel doesn't support SSL" "javax.naming.NamingException: Failed to connect to any server. Servers tried: [remote://192.168.1.100:4447]"
I think there is something wrong with my client code.
Would you please help me to fix it???
Thank you VERY much!!!
I do need JMS client function!
-
standalone.xml 26.7 KB