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'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'll show in
a minute how to configure ActiveMQ to use these. Note that these are all
optional – if you don't want to leverage WebLogic'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">"java:comp/env/jmx/runtime"</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">"ACTIVEMQ Found WebLogic MBeanServer"</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">"ACTIVEMQ Did not find WebLogic
MBeanServer"</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 "plugin", which installs two filters
(authorization and authentication) which will be invoked on every request.
This is similar to the default behavior provided by ActiveMQ'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:
+ * <ul>
+ * <li>Instead of reading a JAAS configuration file, it hardcodes the
JAAS
+ * configuration to require authentication against WebLogic</li>
+ *
+ * <li>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).</li>
+ * </ul>
+ */
+<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">"weblogic.security.auth.login.UsernamePasswordLoginModule"</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())
&&
+
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">"ActiveMQ"</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">"User name or password is
invalid."</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
- (<A
href="http://goopen.org/confluence/pages/diffpages.action?pageId=13349&originalId=13363">view
change</A>)
+ (<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>