让activeMQ的用户拥有一个名称是用户名的队列

时间:2013-09-13 09:51:32

标签: permissions queue activemq jaas

在我的应用程序中,用户可以自由创建帐户,并且需要拥有一个队列(或主题)来在它们之间传递2个后端进程。每次有人创建帐户时我都不想修改activemq的配置。我已经创建了一个jaasAuthenticationPlugin,它运行正常。以下是我的activemq.xml文件的相关部分:

<plugins>
  <!-- 'activemq-domain' defined in conf/login.conf -->
  <jaasAuthenticationPlugin configuration="activemq-domain" />

  <authorizationPlugin>
    <map>
      <authorizationMap>
        <authorizationEntries>
          <authorizationEntry queue="foobarQueue"
              write="foobarGroup"
              read="foobarGroup"
              admin="foobarGroup"
          />
        </authorizationEntries>
      </authorizationMap>
    </map>
  </authorizationPlugin>
</plugins>

您可以扣除,身份验证插件正在验证用户(在此示例中为foobar)并将用户置于foobarGroup组中。 AuthorizationEntry正在向此read write授予adminfoobarQueuefoobarGroup个权限。这很好用,但现在如果我创建一个新用户,我必须来到这个文件并添加一个新的AuthorizationEntry。是否可以使用activemq.xml中的简单配置行执行以下操作:

<authorizationEntry
    queue="<% Username %>"
    write="<% Username %>"
    read="<% Username %>"
    admin="<% Username %>"
/>

或者我应该写一些JAAS授权类来做这件事吗?

1 个答案:

答案 0 :(得分:3)

最后,我写了一个类来处理授权部分。这有点困难,因为很难找到文档,我找不到任何好的例子。挖掘默认LDAPAuthorizationMap的源代码是关键。无论如何,任何感兴趣的人的来源:

package com.example.activemq;


import org.apache.activemq.advisory.AdvisorySupport;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.jaas.GroupPrincipal;
import org.apache.activemq.security.AuthorizationMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.HashSet;
import java.util.Set;

public class OwnedUserQueueAuthorizator implements AuthorizationMap {
    private static final Log log =
            LogFactory.getLog(OwnedUserQueueAuthorizator.class);
    private boolean debug = false;

    // the Destination will be the name of the user, and we should return that
    // the group with user name has read,write and admin privileges to the
    // topic/queue named like the username


    // for temporary destinations, if null is returned, then everybody has
    // permission.

    public Set<GroupPrincipal> getTempDestinationAdminACLs() {
        return null;
    }

    public Set<GroupPrincipal> getTempDestinationReadACLs() {
        return null;
    }

    public Set<GroupPrincipal> getTempDestinationWriteACLs() {
        return null;
    }

    // for persistent destinations

    public Set<GroupPrincipal> getAdminACLs(ActiveMQDestination destination) {
        if (debug) {
            log.debug("getAdminACLs: " + destination.getPhysicalName());
        }
        return getACLs(destination);
    }

    public Set<GroupPrincipal> getReadACLs(ActiveMQDestination destination) {
        if (debug) {
            log.debug("getReadACLs: " + destination.getPhysicalName());
        }
        return getACLs(destination);
    }

    public Set<GroupPrincipal> getWriteACLs(ActiveMQDestination destination) {
        if (debug) {
            log.debug("getwriteACLs: " + destination.getPhysicalName());
        }
        return getACLs(destination);
    }

    private Set<GroupPrincipal> getACLs(ActiveMQDestination destination) {
        Set<GroupPrincipal> result;

        if (AdvisorySupport.isAdvisoryTopic(destination)) {
            result = getACLsForAdvisory();
        } else {
            result = new HashSet<GroupPrincipal>();
            // Destination should be something like UUID or UUID.whatever...,
            // so we must add only the first component as the group principal
            result.add(new GroupPrincipal(
                    destination.getDestinationPaths()[0])
            );
        }

        if (debug) {
            String s = "";
            for (GroupPrincipal gp : result) {
                s += ", " + gp.getName();
            }
            log.debug("groupPrincipals: " + "[" + s.substring(2) + "]");
        }
        return result;
    }

    private Set<GroupPrincipal> getACLsForAdvisory() {
        Set<GroupPrincipal> result = new HashSet<GroupPrincipal>();
        GroupPrincipal g = new GroupPrincipal("advisories");
        result.add(g);
        return result;
    }

    // Properties
    // -------------------------------------------------------------------------

    // if the <bean> definition in the activemq.xml has some
    // <property name="foo" value="..." />
    // defined, they will call this.setFoo($value), so, even if these get/set
    // methods aren't called from here, they are really needed.

    public void setDebug(String debug) {
        this.debug = "true".equalsIgnoreCase(debug);
    }

    public String getDebug() {
        return String.valueOf(debug);
    }
}

conf/activemq.xml文件:

<beans ...>
    ...
    <broker ...>
    ...
        <plugins>                                                               
            <!-- 'activemq-domain' defined in conf/login.conf -->               
            <jaasAuthenticationPlugin configuration="activemq-domain" />        

            <authorizationPlugin>                                               
                <map>                                                           
                    <bean id="OwnedUserQueueAuthorizationMap"                            
                        class="com.example.activemq.OwnedUserQueueAuthorizator"   
                        xmlns="http://www.springframework.org/schema/beans">    
                        <property name="debug" value="false"/>                   
                    </bean>                                                     
                </map>                                                          
            </authorizationPlugin>                                              
        </plugins>   
        ...
    </broker>
    ...
</beans>