Topic Archive

Securing WebLogic JMS Resources

This is an interesting post that describes how we can secure the WebLogic JMS resources using the security policies.

By default, destinations are not protected. This means that any valid user for a WebLogic server instance can send, receive, and browse messages on a destination.  Security policies allows only users defined by the policy condition to have access control of the destination.

There are two ways of securing the JMS resources.

  1. At the JMSModule level (Group level), where a single security policy is specified for  a set of JMS resources.
  2. At the individual JMS resource level, which provides much more grained controlled over the operations that you want to secure.

Note:  If you have defined a security policy for both the JMSModule and the individual JMS Resource, the security policy of the JMS Resource would take precedence over the JMSModule security policy.

Make sure that a JMS Queue is already configured. Please follow the below post to do so.

http://weblogic-wonders.com/weblogic/2010/11/30/weblogic-jms-feature-using-a-queue/

Steps to configure security for JMS Resources.

1. Setting the security policy.

At the JMS Module Level (Group Level)

a. Login into the server console, navigate to the JMSModule.

b. Click on the Security Tab –> Policies sub tab –> Click on the Add Conditions tab to add the policy conditions.

c. From the predicate list, specify the policy conditions.

We would select the User from the drop down list for demo.

d. Specify the user who needs to have the access permissions for the JMS Module resources. Click Add –> Finish.

This completes the security policy configuration at the JMS Module level, the above configured policy is applicable for all the JMS resources under this Module unless they have their individual security policies.

The above configured policy states that the JMS resources can only be accessed by the user “weblogic”.

Security policy for a JMS Queue (Resource Level).

When you define a security policy for an individual destination on a JMS server, you can protect all operations of the destination.

a. Login into the Admin server console –> Navigate to the Queue that needs to be secured.

b. Click on the security tab –> Policies sub tab.

You can see a small drop down list, which lists the set of the operations that can be protected.

c. Click Add Conditions to add the policy conditions.

d. From the predicate list, specify the policy conditions.

We would select the User from the drop down list for demo.

e. Specify the user who needs to have the access permissions for the JMS  Queue. Click Add  –>  Finish.

This completes the security policy configuration at the JMS Queue level. Similarly you can specify policies for JMS Topic.

If you try to send a message to the Queue without having sufficient permissions , it  fails with the AccessDenied Error.

Exception in thread “Main Thread” weblogic.jms.common.JMSSecurityException: Acce

ss denied to resource: type=<jms>, application=SystemModule-0, destinationType=q

ueue, resource=Queue-0, action=send

2. Lookup Code:

In the JMS Destination lookup code, we need to pass the username and password who has the access permissions on the resource.

env.put(Context.SECURITY_PRINCIPAL, “weblogic”);
env.put(Context.SECURITY_CREDENTIALS, “weblogic”);

3. To send a  JMS message to the queue with the user credentials, execute the below QueueSend.java program.

***********************************************************************

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Hashtable;

import javax.jms.*;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

public class QueueSend

{

public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";

public final static String JMS_FACTORY="CF";

public final static String QUEUE="Queue";

private QueueConnectionFactory qconFactory;

private QueueConnection qcon;

private QueueSession qsession;

private QueueSender qsender;

private Queue queue;

private TextMessage msg;

public void init(Context ctx, String queueName)     throws NamingException, JMSException

{

qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);

qcon = qconFactory.createQueueConnection();

qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

queue = (Queue) ctx.lookup(queueName);

qsender = qsession.createSender(queue);

msg = qsession.createTextMessage();

qcon.start();   }

public void send(String message) throws JMSException {

msg.setText(message);

qsender.send(msg);

}

public void close() throws JMSException {

qsender.close();

qsession.close();

qcon.close();

}

public static void main(String[] args) throws Exception {

if (args.length != 1) {

System.out.println("Usage: java examples.jms.queue.QueueSend WebLogicURL");

return;

}

InitialContext ic = getInitialContext(args[0]);

QueueSend qs = new QueueSend();

qs.init(ic, QUEUE);

readAndSend(qs);

qs.close();

}

private static void readAndSend(QueueSend qs)     throws IOException, JMSException

{     BufferedReader msgStream = new BufferedReader(new InputStreamReader(System.in));

String line=null;

boolean quitNow = false;

do {

System.out.print("Enter message (\"quit\" to quit): \n");

line = msgStream.readLine();

if (line != null && line.trim().length() != 0) {

qs.send(line);

System.out.println("JMS Message Sent: "+line+"\n");

quitNow = line.equalsIgnoreCase("quit");

}

} while (! quitNow);

}

private static InitialContext getInitialContext(String url)     throws NamingException

{

Hashtable<String,String> env = new Hashtable<String,String>();

env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);

env.put(Context.PROVIDER_URL, url);

env.put(Context.SECURITY_PRINCIPAL, "weblogic");

env.put(Context.SECURITY_CREDENTIALS, "weblogic");

return new InitialContext(env);

}}

 

***********************************************************************

4. Execute the below QueueReceive.java program to receive the JMS messages.

***********************************************************************

 

import java.util.Hashtable;

import javax.jms.*;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

public class QueueReceive implements MessageListener

{

public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";

public final static String JMS_FACTORY="CF";

public final static String QUEUE="Queue";

private QueueConnectionFactory qconFactory;

private QueueConnection qcon;

private QueueSession qsession;

private QueueReceiver qreceiver;

private Queue queue;

private boolean quit = false;

public void onMessage(Message msg)

{

try {

String msgText;

if (msg instanceof TextMessage) {

msgText = ((TextMessage)msg).getText();

} else {

msgText = msg.toString();

}

System.out.println("Message Received: "+ msgText );

if (msgText.equalsIgnoreCase("quit")) {

synchronized(this) {

quit = true;

this.notifyAll(); // Notify main thread to quit

}

}

} catch (JMSException jmse) {

System.err.println("An exception occurred: "+jmse.getMessage());

}

}

public void init(Context ctx, String queueName)

throws NamingException, JMSException

{

qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);

qcon = qconFactory.createQueueConnection();

qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

queue = (Queue) ctx.lookup(queueName);

qreceiver = qsession.createReceiver(queue);

qreceiver.setMessageListener(this);

qcon.start();

}

public void close()throws JMSException

{

qreceiver.close();

qsession.close();

qcon.close();

}

public static void main(String[] args) throws Exception {

if (args.length != 1) {

System.out.println("Usage: java examples.jms.queue.QueueReceive WebLogicURL");

return;

}

InitialContext ic = getInitialContext(args[0]);

QueueReceive qr = new QueueReceive();

qr.init(ic, QUEUE);

System.out.println("JMS Ready To Receive Messages (To quit, send a \"quit\" message).");

synchronized(qr) {

while (! qr.quit) {

try {

qr.wait();

} catch (InterruptedException ie) {}

}

}

qr.close();

}

private static InitialContext getInitialContext(String url)

throws NamingException

{

Hashtable<String,String> env = new Hashtable<String,String>();

env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);

env.put(Context.PROVIDER_URL, url);

env.put(Context.SECURITY_PRINCIPAL, "weblogic");

env.put(Context.SECURITY_CREDENTIALS, "weblogic");

return new InitialContext(env);

}

}

 

***********************************************************************

References:

http://download.oracle.com/docs/cd/E13222_01/wls/docs103/secwlres/types.html#wp1229971

Cheers,

Wonders Team. 🙂

WebLogic JMS feature using Topic

The following article shows a simple usage of WebLogic JMS feature using a Topic.

1. Login into the WebLogic Admin Console, navigate to Services à Messaging à JMS Servers.

JMS Server acts as a management containers for the queues and topics.

Create a JMS Server as below.

2.Target the JMS Server to any one of the WebLogic Servers.

3. Create a JMS System Module to hold the queues and topics.

Navigate to Services –> Messaging –> JMS Modules.

4. Target the JMS System Module to the server on which the JMS Server is targeted.

5. Before adding JMS Topics, create a Sub Deployment.

6. Target the Sub Deployment to the created JMS Server.

7. Under the configuration tab, click New to add resources like Connection Factories, Queues,Topics.

8. Create a JMS Connection Factory, specify a JNDI name.

9. Target the Connection Factory to the Sub Deployment.

10. Similarly create a Topic, then target to the Sub Deployment.

11. Navigate to the JMS Resources page and you would see the Connection Factory and the JMS Topic created.

12. Open  command prompt, and set the class path.

13. Execute the below, TopicSend.java program to send a message to the Topic.

*************************************************************

 

import java.io.*;

import java.util.*;

import javax.transaction.*;

import javax.naming.*;

import javax.jms.*;

import javax.rmi.PortableRemoteObject;

public class TopicSend

{

public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";

public final static String JMS_FACTORY="CF1";

public final static String TOPIC="Topic1";

protected TopicConnectionFactory tconFactory;

protected TopicConnection tcon;

protected TopicSession tsession;

protected TopicPublisher tpublisher;

protected Topic topic;

protected TextMessage msg;

public void init(Context ctx, String topicName) throws NamingException, JMSException

{

tconFactory = (TopicConnectionFactory)

PortableRemoteObject.narrow(ctx.lookup(JMS_FACTORY),TopicConnectionFactory.class);

tcon = tconFactory.createTopicConnection();

tsession = tcon.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

topic = (Topic) PortableRemoteObject.narrow(ctx.lookup(topicName), Topic.class);

tpublisher = tsession.createPublisher(topic);

msg = tsession.createTextMessage();

tcon.start();

}

public void send(String message) throws JMSException {

msg.setText(message);

tpublisher.publish(msg);

}

public void close() throws JMSException {

tpublisher.close();

tsession.close();

tcon.close();

}

public static void main(String[] args) throws Exception {

if (args.length != 1) {

System.out.println("Usage: java examples.jms.topic.TopicSend WebLogicURL");

return;

}

InitialContext ic = getInitialContext(args[0]);

TopicSend ts = new TopicSend();

ts.init(ic, TOPIC);

readAndSend(ts);

ts.close();

}

protected static void readAndSend(TopicSend ts)

throws IOException, JMSException

{

BufferedReader msgStream = new BufferedReader (new InputStreamReader(System.in));

String line=null;

do {

System.out.print("Enter message (\"quit\" to quit): \n");

line = msgStream.readLine();

if (line != null && line.trim().length() != 0) {

ts.send(line);

System.out.println("JMS Message Sent: "+line+"\n");

}

} while (line != null && ! line.equalsIgnoreCase("quit"));

}

protected static InitialContext getInitialContext(String url)

throws NamingException

{

Hashtable<String,String> env = new Hashtable<String,String>();

env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);

env.put(Context.PROVIDER_URL, url);

env.put("weblogic.jndi.createIntermediateContexts", "true");

return new InitialContext(env);

}}

 

*************************************************************

14.Execute the below TopicReceive.java program to retrieve the message from the Topic.

******************************************************

 

import java.io.*;

import java.util.*;

import javax.transaction.*;

import javax.naming.*;

import javax.jms.*;

import javax.rmi.PortableRemoteObject;

public class TopicReceive implements MessageListener {

public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";

public final static String JMS_FACTORY="CF1";

public final static String TOPIC="Topic1";

private TopicConnectionFactory tconFactory;

private TopicConnection tcon;

private TopicSession tsession;

private TopicSubscriber tsubscriber;

private Topic topic;

private boolean quit = false;

public void onMessage(Message msg) {

try {

String msgText;

if (msg instanceof TextMessage) {

msgText = ((TextMessage)msg).getText();

} else {

msgText = msg.toString();

}

System.out.println("JMS Message Received: "+ msgText );

if (msgText.equalsIgnoreCase("quit")) {

synchronized(this) {

quit = true;

this.notifyAll(); // Notify main thread to quit

}

}

} catch (JMSException jmse) {

System.err.println("An exception occurred: "+jmse.getMessage());

}

}

public void init(Context ctx, String topicName)

throws NamingException, JMSException

{

tconFactory = (TopicConnectionFactory)

PortableRemoteObject.narrow(ctx.lookup(JMS_FACTORY),

TopicConnectionFactory.class);

tcon = tconFactory.createTopicConnection();

tsession = tcon.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

topic = (Topic)

PortableRemoteObject.narrow(ctx.lookup(topicName),

Topic.class);

tsubscriber = tsession.createSubscriber(topic);

tsubscriber.setMessageListener(this);

tcon.start();

}

public void close() throws JMSException {

tsubscriber.close();

tsession.close();

tcon.close();

}

public static void main(String[] args) throws Exception {

if (args.length != 1) {

System.out.println("Usage: java examples.jms.topic.TopicReceive WebLogicURL");

return;

}

InitialContext ic = getInitialContext(args[0]);

TopicReceive tr = new TopicReceive();

tr.init(ic, TOPIC);

System.out.println("JMS Ready To Receive Messages (To quit, send a \"quit\" message).");

synchronized(tr) {

while (! tr.quit) {

try {

tr.wait();

} catch (InterruptedException ie) {}

}

}

tr.close();

}

private static InitialContext getInitialContext(String url)

throws NamingException

{

Hashtable<String,String> env = new Hashtable<String,String>();

env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);

env.put(Context.PROVIDER_URL, url);

env.put("weblogic.jndi.createIntermediateContexts", "true");

return new InitialContext(env);

}}

 

******************************************************

Best Regards.

Configuring Distributed Topic on Weblogic Server

A distributed topic is a set of physical JMS topic members. As such, a distributed topic can be used to create a TopicPublisher and TopicSubscriber. The fact that a distributed topic represents multiple physical topics is mostly transparent to the application.

Note: Durable subscribers (DurableTopicSubscriber) cannot be created for distributed topics. However, you can still create a durable subscription on distributed topic member and the other topic members will forward the messages to the topic member that has the durable subscription.

The topic members can be located anywhere but must all be served either by a single WebLogic Server or any number of servers in a cluster. When a message is sent to a distributed topic, it is sent to all of the topic members in the distributed topic set. This allows all subscribers to the distributed topic to receive messages published for the distributed topic.

Read more

Create two managed servers (MS1 and MS2) and assign it to cluster (Cluster).

Create two JMS Server (JMSServer-0 and JMSServer-1) and assign it to each managed servers (MS1 and MS2).

Create JMS module and target it to cluster.

Create a JMS connection factory (ConnectionFactory1) and target it to cluster.

Create a Distributed Topic (MyDistributedTopic) and target it to the cluster.


Check  the jndi tree for connection factory and distributed topic.

Use the TopicSend and TopicReceive Program to send and receive messages.
You can find the programs here
C:\bea\weblogic92\samples\server\examples\src\examples\jms\topic

Change the JNDI Name of the ConnectionFactory and the Topic.

Send message to distributed topic

java TopicSend t3://xxxx.xxxx.com:7003,xxxx.xxxx.com:7005

Receive message from the topic

java TopicReceive t3://xxxx.xxxx.com:7003,xxxx.xxxx.com:7005

Please refer this post for more details.