activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From chir...@apache.org
Subject svn commit: r439357 - /incubator/activemq/site/weblogic-integration.html
Date Fri, 01 Sep 2006 15:51:23 GMT
Author: chirino
Date: Fri Sep  1 08:51:22 2006
New Revision: 439357

URL: http://svn.apache.org/viewvc?rev=439357&view=rev
Log:
Latest export from confluence

Modified:
    incubator/activemq/site/weblogic-integration.html

Modified: incubator/activemq/site/weblogic-integration.html
URL: http://svn.apache.org/viewvc/incubator/activemq/site/weblogic-integration.html?rev=439357&r1=439356&r2=439357&view=diff
==============================================================================
--- incubator/activemq/site/weblogic-integration.html (original)
+++ incubator/activemq/site/weblogic-integration.html Fri Sep  1 08:51:22 2006
@@ -475,13 +475,202 @@
 
 <P>Of these, Derby could be omitted if ActiveMQ was configured to not use a database
for persistence or to use a separate database for persistence.  The WebLogic JAR is needed
only at build time (it&apos;s provided by the server at runtime).  Spring could be omitted
if a different strategy was used to start and stop ActiveMQ when the web app was started or
stopped (a little custom code could replace this dependency).  The rest are probably unavoidable,
unless ActiveMQ changes its dependencies in a future version.</P>
 
-<H5><A name="WebLogicIntegration-CodeandConfigurationFiles"></A>Code and
Configuration Files</H5>
+<H5><A name="WebLogicIntegration-WebLogicIntegrationCode"></A>WebLogic
Integration Code</H5>
 
-<P><B>TODO:</B> show and discuss code for:</P>
+<P>There are several custom classes used for this example.  We&apos;ll show in
a minute how to configure ActiveMQ to use these.  Note that these are all optional &ndash;
if you don&apos;t want to leverage WebLogic&apos;s MBeanServer or security realm,
you can skip these.</P>
+
+<P>The first lets ActiveMQ installed its JMX MBeans into the WebLogic runtime MBeanServer:</P>
+
+<P><B>ActiveMQToWebLogicManagement.java</B></P>
+
+<P>This class overrides the ActiveMQ default MBeanServer lookup behavior (in the ActiveMQ
class <TT>ManagementContext</TT> to prefer the WebLogic runtime MBeanServer.</P>
+
+<DIV class="code"><DIV class="codeContent">
+<PRE class="code-java">/**
+ * Makes ActiveMQ favor the WebLogic runtime MBeanServer
+ */
+<SPAN class="code-keyword">public</SPAN> class ActiveMQToWebLogicManagement <SPAN
class="code-keyword">extends</SPAN> ManagementContext {
+    <SPAN class="code-keyword">protected</SPAN> <SPAN class="code-keyword">synchronized</SPAN>
MBeanServer findMBeanServer() {
+        <SPAN class="code-keyword">try</SPAN> {
+            Context ctx = <SPAN class="code-keyword">new</SPAN> InitialContext();
+            MBeanServer server = (MBeanServer) ctx.lookup(<SPAN class="code-quote">&quot;java:comp/env/jmx/runtime&quot;</SPAN>);
+            <SPAN class="code-keyword">if</SPAN>(server != <SPAN class="code-keyword">null</SPAN>)
{
+                <SPAN class="code-object">System</SPAN>.out.println(<SPAN
class="code-quote">&quot;ACTIVEMQ Found WebLogic MBeanServer&quot;</SPAN>);
+                <SPAN class="code-keyword">return</SPAN> server;
+            }
+        } <SPAN class="code-keyword">catch</SPAN> (NamingException e) {
+            e.printStackTrace();
+        }
+        <SPAN class="code-object">System</SPAN>.out.println(<SPAN class="code-quote">&quot;ACTIVEMQ
Did not find WebLogic MBeanServer&quot;</SPAN>);
+        <SPAN class="code-keyword">return</SPAN> <SPAN class="code-keyword">super</SPAN>.findMBeanServer();
+    }
+}</PRE>
+</DIV></DIV>
+
+<P>The next class makes ActiveMQ use the WebLogic security realm for authentication,
and lets you specify a single WebLogic group to use for authorization (only members of that
group can access ActiveMQ, though group members have full access to ActiveMQ).</P>
+
+<P><B>ActiveMQToWebLogicSecurity.java</B></P>
+
+<P>This class is an ActiveMQ &quot;plugin&quot;, which installs two filters
(authorization and authentication) which will be invoked on every request.  This is similar
to the default behavior provided by ActiveMQ&apos;s <TT>JaasAuthenticationPlugin</TT>
and <TT>AuthorizationPlugin</TT>.</P>
+
+<DIV class="code"><DIV class="codeContent">
+<PRE class="code-java">/**
+ * An ActiveMQ security plugin that installs two security filters
+ * (authentication and authorization) that use WebLogic security realms to
+ * handle the login and provide user and group principals.
+ */
+<SPAN class="code-keyword">public</SPAN> class ActiveMQToWebLogicSecurity <SPAN
class="code-keyword">implements</SPAN> BrokerPlugin {
+    <SPAN class="code-keyword">private</SPAN> <SPAN class="code-object">String</SPAN>
authorizedGroup;
+
+    <SPAN class="code-keyword">public</SPAN> Broker installPlugin(Broker broker)
{
+        <SPAN class="code-comment">// Install the first filter <SPAN class="code-keyword">for</SPAN>
authentication
+</SPAN>        Broker first = <SPAN class="code-keyword">new</SPAN> ActiveMQWebLogicAuthenticationFilter(broker);
+        <SPAN class="code-comment">// Configure and install the second filter <SPAN
class="code-keyword">for</SPAN> authorization
+</SPAN>        AuthorizationEntry entry = <SPAN class="code-keyword">new</SPAN>
AuthorizationEntry();
+        Set acls = <SPAN class="code-keyword">new</SPAN> HashSet();
+        acls.add(<SPAN class="code-keyword">new</SPAN> WLSGroupImpl(authorizedGroup));
+        entry.setAdminACLs(acls);
+        entry.setReadACLs(acls);
+        entry.setWriteACLs(acls);
+        DefaultAuthorizationMap map = <SPAN class="code-keyword">new</SPAN> DefaultAuthorizationMap();
+        map.setDefaultEntry(entry);
+        <SPAN class="code-comment">//todo: <SPAN class="code-keyword">if</SPAN>
finer-grained access is required, add more entries to the authorization map
+</SPAN>        Broker second = <SPAN class="code-keyword">new</SPAN> AuthorizationBroker(first,
map);
+        <SPAN class="code-keyword">return</SPAN> second;
+    }
+
+    <SPAN class="code-keyword">public</SPAN> <SPAN class="code-object">String</SPAN>
getAuthorizedGroup() {
+        <SPAN class="code-keyword">return</SPAN> authorizedGroup;
+    }
+
+    /**
+     * Called by XBean at configuration time to set the authorized group from a
+     * property in the main ActiveMQ configuration file.
+     */
+    <SPAN class="code-keyword">public</SPAN> void setAuthorizedGroup(<SPAN
class="code-object">String</SPAN> authorizedGroup) {
+        <SPAN class="code-keyword">this</SPAN>.authorizedGroup = authorizedGroup;
+    }
+}</PRE>
+</DIV></DIV>
+
+<P>Finally, the last class is the authentication filter used by the class above to
authenticate all logins against the WebLogic default security realm.</P>
+
+<P><B>ActiveMQWebLogicAuthenticationFilter.java</B></P>
+
+<DIV class="code"><DIV class="codeContent">
+<PRE class="code-java">/**
+ * A broker filter that authenticates callers against WebLogic security.
+ * This is similar to the ActiveMQ JaasAuthenticationBroker except <SPAN class="code-keyword">for</SPAN>
two
+ * things:
+ * &lt;ul&gt;
+ *   &lt;li&gt;Instead of reading a JAAS configuration file, it hardcodes the JAAS
+ *     configuration to require authentication against WebLogic&lt;/li&gt;
+ *
+ *   &lt;li&gt;The SecurityContext implementation overrides the method used to
+ *     compare actual and eligible principals in order to handle the fact
+ *     that WebLogic principals (WLSGroupImpl in particular) <SPAN class="code-keyword">do</SPAN>
not seem
+ *     to match according to equals and hashCode even <SPAN class="code-keyword">if</SPAN>
the principal class
+ *     and principal name are the same (perhaps having to <SPAN class="code-keyword">do</SPAN>
with the
+ *     signature data on the WLSAbstractPrincipal).&lt;/li&gt;
+ * &lt;/ul&gt;
+ */
+<SPAN class="code-keyword">public</SPAN> class ActiveMQWebLogicAuthenticationFilter
<SPAN class="code-keyword">extends</SPAN> BrokerFilter {
+    <SPAN class="code-keyword">private</SPAN> <SPAN class="code-keyword">final</SPAN>
<SPAN class="code-keyword">static</SPAN> Configuration WEBLOGIC_JAAS_CONFIGURATION
= <SPAN class="code-keyword">new</SPAN> Configuration() {
+        <SPAN class="code-keyword">public</SPAN> AppConfigurationEntry[] getAppConfigurationEntry(<SPAN
class="code-object">String</SPAN> name) {
+            <SPAN class="code-keyword">return</SPAN> <SPAN class="code-keyword">new</SPAN>
AppConfigurationEntry[]{
+                    <SPAN class="code-keyword">new</SPAN> AppConfigurationEntry(<SPAN
class="code-quote">&quot;weblogic.security.auth.login.UsernamePasswordLoginModule&quot;</SPAN>,
+                            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, Collections.EMPTY_MAP)
+            };
+        }
+
+        <SPAN class="code-keyword">public</SPAN> void refresh() {
+        }
+    };
+    <SPAN class="code-keyword">private</SPAN> <SPAN class="code-keyword">final</SPAN>
CopyOnWriteArrayList securityContexts = <SPAN class="code-keyword">new</SPAN>
CopyOnWriteArrayList();
+
+    <SPAN class="code-keyword">public</SPAN> ActiveMQWebLogicAuthenticationFilter(Broker
next) {
+        <SPAN class="code-keyword">super</SPAN>(next);
+    }
+
+    <SPAN class="code-keyword">static</SPAN> class JaasSecurityContext <SPAN
class="code-keyword">extends</SPAN> SecurityContext {
+
+        <SPAN class="code-keyword">private</SPAN> <SPAN class="code-keyword">final</SPAN>
Subject subject;
+
+        <SPAN class="code-keyword">public</SPAN> JaasSecurityContext(<SPAN
class="code-object">String</SPAN> userName, Subject subject) {
+            <SPAN class="code-keyword">super</SPAN>(userName);
+            <SPAN class="code-keyword">this</SPAN>.subject = subject;
+        }
+
+        <SPAN class="code-keyword">public</SPAN> Set getPrincipals() {
+            <SPAN class="code-keyword">return</SPAN> subject.getPrincipals();
+        }
+
+        /**
+         * This is necessary because WebLogic uses extra logic when comparing principals,
+         * probably to check whether they are cryptographically signed (which WebLogic
+         * supports).  We skip that test because ActiveMQ does not sign the principals
+         * it deals with.
+         */
+        <SPAN class="code-keyword">public</SPAN> <SPAN class="code-object">boolean</SPAN>
isInOneOf(Set eligiblePrincipals) {
+            <SPAN class="code-keyword">for</SPAN> (Iterator it = getPrincipals().iterator();
it.hasNext();) {
+                Principal test = (Principal) it.next();
+                <SPAN class="code-keyword">for</SPAN> (Iterator el = eligiblePrincipals.iterator();
el.hasNext();) {
+                    Principal eligible = (Principal) el.next();
+                    <SPAN class="code-keyword">if</SPAN>(test.getName().equals(eligible.getName())
&amp;&amp;
+                            test.getClass().getName().equals(eligible.getClass().getName()))
{
+                        <SPAN class="code-keyword">return</SPAN> <SPAN class="code-keyword">true</SPAN>;
+                    }
+                }
+            }
+            <SPAN class="code-keyword">return</SPAN> <SPAN class="code-keyword">false</SPAN>;
+        }
+    }
+
+    <SPAN class="code-keyword">public</SPAN> void addConnection(ConnectionContext
context, ConnectionInfo info) <SPAN class="code-keyword">throws</SPAN> Exception
{
+        <SPAN class="code-keyword">if</SPAN>( context.getSecurityContext()==<SPAN
class="code-keyword">null</SPAN> ) {
+            <SPAN class="code-comment">// Do the login.
+</SPAN>            <SPAN class="code-keyword">try</SPAN> {
+                LoginContext lc = <SPAN class="code-keyword">new</SPAN> LoginContext(<SPAN
class="code-quote">&quot;ActiveMQ&quot;</SPAN>, <SPAN class="code-keyword">new</SPAN>
Subject(),
+                        <SPAN class="code-keyword">new</SPAN> URLCallbackHandler(info.getUserName(),
info.getPassword()),
+                        WEBLOGIC_JAAS_CONFIGURATION);
+                lc.login();
+                Subject subject = lc.getSubject();
+
+                SecurityContext s = <SPAN class="code-keyword">new</SPAN> JaasSecurityContext(info.getUserName(),
subject);
+                context.setSecurityContext(s);
+                securityContexts.add(s);
+            } <SPAN class="code-keyword">catch</SPAN> (Exception e) {
+                <SPAN class="code-keyword">throw</SPAN> (SecurityException)<SPAN
class="code-keyword">new</SPAN> SecurityException(<SPAN class="code-quote">&quot;User
name or password is invalid.&quot;</SPAN>).initCause(e);
+            }
+        }
+        <SPAN class="code-keyword">super</SPAN>.addConnection(context, info);
+    }
+
+    <SPAN class="code-keyword">public</SPAN> void removeConnection(ConnectionContext
context, ConnectionInfo info, Throwable error) <SPAN class="code-keyword">throws</SPAN>
Exception {
+        <SPAN class="code-keyword">super</SPAN>.removeConnection(context, info,
error);
+        <SPAN class="code-keyword">if</SPAN>( securityContexts.remove(context.getSecurityContext())
) {
+            context.setSecurityContext(<SPAN class="code-keyword">null</SPAN>);
+        }
+    }
+
+    /**
+     * Previously logged in users may no longer have the same access anymore.  Refresh
+     * all the logged into users.
+     */
+    <SPAN class="code-keyword">public</SPAN> void refresh() {
+        <SPAN class="code-keyword">for</SPAN> (Iterator iter = securityContexts.iterator();
iter.hasNext();) {
+            SecurityContext sc = (SecurityContext) iter.next();
+            sc.getAuthorizedReadDests().clear();
+            sc.getAuthorizedWriteDests().clear();
+        }
+    }
+}</PRE>
+</DIV></DIV>
+
+<H5><A name="WebLogicIntegration-SampleActiveMQConfigurationFiles"></A>Sample
ActiveMQ Configuration Files</H5>
+
+<P><B>TODO:</B> show and discuss:</P>
 <UL>
-	<LI>ActiveMQ Management plugin for WebLogic</LI>
-	<LI>ActiveMQ Security plugin for WebLogic</LI>
-	<LI>ActiveMQ authentication filter for WebLogic</LI>
 	<LI>ActiveMQ config file for one broker or a network of brokers, with the plugins
above</LI>
 </UL>
 
@@ -561,7 +750,7 @@
     <DIV id="site-footer">
           Added by     <A href="http://goopen.org/confluence/users/viewuserprofile.action?username=ammulder">Aaron
Mulder</A>,
     last edited by     <A href="http://goopen.org/confluence/users/viewuserprofile.action?username=ammulder">Aaron
Mulder</A> on Sep 01, 2006
-                  &nbsp;(<A href="http://goopen.org/confluence/pages/diffpages.action?pageId=13349&originalId=13363">view
change</A>)
+                  &nbsp;(<A href="http://goopen.org/confluence/pages/diffpages.action?pageId=13349&originalId=13364">view
change</A>)
               
       (<A href="http://goopen.org/confluence/pages/editpage.action?pageId=13349">edit
page</A>)
     </DIV>



Mime
View raw message