我正在学习jms并找到了一个示例聊天应用程序但是当我尝试运行它时,我得到一个安全异常。在创建新的主题会话时,我似乎需要传递用户名和密码,但教程没有提到这一点。
聊天应用代码:
package ch02.chat;
import java.io.*;
import javax.jms.*;
import javax.naming.*;
public class Chat implements javax.jms.MessageListener {
private TopicSession pubSession;
private TopicPublisher publisher;
private TopicConnection connection;
private String username;
/* Constructor used to Initialize Chat */
public Chat(String topicFactory, String topicName, String username)
throws Exception {
// Obtain a JNDI connection using the jndi.properties file
InitialContext ctx = new InitialContext();
// Look up a JMS connection factory and create the connection
TopicConnectionFactory conFactory =
(TopicConnectionFactory)ctx.lookup(topicFactory);
TopicConnection connection = conFactory.createTopicConnection();
// Create two JMS session objects
TopicSession pubSession = connection.createTopicSession(
false, Session.AUTO_ACKNOWLEDGE);
TopicSession subSession = connection.createTopicSession(
false, Session.AUTO_ACKNOWLEDGE);
// Look up a JMS topic
Topic chatTopic = (Topic)ctx.lookup(topicName);
// Create a JMS publisher and subscriber. The additional parameters
// on the createSubscriber are a message selector (null) and a true
// value for the noLocal flag indicating that messages produced from
// this publisher should not be consumed by this publisher.
TopicPublisher publisher =
pubSession.createPublisher(chatTopic);
TopicSubscriber subscriber =
subSession.createSubscriber(chatTopic, null, true);
// Set a JMS message listener
subscriber.setMessageListener(this);
// Intialize the Chat application variables
this.connection = connection;
this.pubSession = pubSession;
this.publisher = publisher;
this.username = username;
// Start the JMS connection; allows messages to be delivered
connection.start();
}
/* Receive Messages From Topic Subscriber */
public void onMessage(Message message) {
try {
TextMessage textMessage = (TextMessage) message;
System.out.println(textMessage.getText());
} catch (JMSException jmse){ jmse.printStackTrace(); }
}
/* Create and Send Message Using Publisher */
protected void writeMessage(String text) throws JMSException {
TextMessage message = pubSession.createTextMessage();
message.setText(username+": "+text);
publisher.publish(message);
}
/* Close the JMS Connection */
public void close() throws JMSException {
connection.close();
}
/* Run the Chat Client */
public static void main(String [] args) {
try {
if (args.length!=3)
System.out.println("Factory, Topic, or username missing");
// args[0]=topicFactory; args[1]=topicName; args[2]=username
Chat chat = new Chat(args[0],args[1],args[2]);
// Read from command line
BufferedReader commandLine = new
java.io.BufferedReader(new InputStreamReader(System.in));
// Loop until the word "exit" is typed
while(true) {
String s = commandLine.readLine();
if (s.equalsIgnoreCase("exit")){
chat.close();
System.exit(0);
} else
chat.writeMessage(s);
}
} catch (Exception e) { e.printStackTrace(); }
}
}
我的类路径中有以下jndi.properties文件:
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
java.naming.provider.url = tcp://localhost:61616
java.naming.security.principal=system
java.naming.security.credentials=manager
connectionFactoryNames = TopicCF
topic.topic1 = jms.topic1
Active mq正在运行(我可以访问管理控制台)。这是运行此应用程序并传递参数'TopicCF topic1 Fred'时出现的错误:
javax.jms.JMSException: User name [null] or password is invalid.
at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:49)
at org.apache.activemq.ActiveMQConnection.syncSendPacket(ActiveMQConnection.java:1391)
at org.apache.activemq.ActiveMQConnection.ensureConnectionInfoSent(ActiveMQConnection.java:1496)
at org.apache.activemq.ActiveMQConnection.createSession(ActiveMQConnection.java:325)
at org.apache.activemq.ActiveMQConnection.createTopicSession(ActiveMQConnection.java:1122)
at ch02.chat.Chat.<init>(Chat.java:47)
at ch02.chat.Chat.main(Chat.java:105)
Caused by: java.lang.SecurityException: User name [null] or password is invalid.
at org.apache.activemq.security.SimpleAuthenticationBroker.addConnection(SimpleAuthenticationBroker.java:81)
at org.apache.activemq.broker.MutableBrokerFilter.addConnection(MutableBrokerFilter.java:91)
at org.apache.activemq.broker.TransportConnection.processAddConnection(TransportConnection.java:766)
at org.apache.activemq.broker.jmx.ManagedTransportConnection.processAddConnection(ManagedTransportConnection.java:79)
at org.apache.activemq.command.ConnectionInfo.visit(ConnectionInfo.java:139)
at org.apache.activemq.broker.TransportConnection.service(TransportConnection.java:329)
at org.apache.activemq.broker.TransportConnection$1.onCommand(TransportConnection.java:184)
at org.apache.activemq.transport.MutexTransport.onCommand(MutexTransport.java:50)
at org.apache.activemq.transport.WireFormatNegotiator.onCommand(WireFormatNegotiator.java:113)
at org.apache.activemq.transport.AbstractInactivityMonitor.onCommand(AbstractInactivityMonitor.java:288)
at org.apache.activemq.transport.TransportSupport.doConsume(TransportSupport.java:83)
at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:214)
at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:196)
at java.lang.Thread.run(Thread.java:745)
我还没有在任何地方创建topic1,但这应该抛出一个不同的异常。
答案 0 :(得分:4)
在建立连接时,将在JMS API中定义您登录到代理的凭据。要传递用户名和密码,请执行以下操作:
TopicConnection connection =
conFactory.createTopicConnection(username, password);
答案 1 :(得分:2)
正如Jake所提出的,正确的方法是使用主题连接工厂构造函数和用户名和密码:
TopicConnection connection =
conFactory.createTopicConnection(username, password);
还有另一个选项,在activemq中我们可以通过在activemq.xml配置文件中添加简单的身份验证插件并设置anonymousAccessAllowed =“true”来允许匿名访问。
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}" schedulerSupport="true">
<plugins>
<!-- users and passwords -->
<simpleAuthenticationPlugin anonymousAccessAllowed="true">
<users>
<authenticationUser username="system" password="manager" groups="admins,publishers,consumers" />
</users>
</simpleAuthenticationPlugin>
</plugins>