ActiveMQ授权源码分析jaasAuthentication(二)

编程

上次说了 ActiveMQ 授权源码分析simpleAuthentication (一)  这次来看看JAAS 是怎么做的。首先要使用JAAS 认证那么在ActiveMQ.xml 当中需要引入JAAS认证

<jaasAuthenticationPlugin configuration="activemq-domain" 

discoverLoginConfig="true" />

同时配置 users.properties 和  group.properties  这两个文件都在conf 目录结构下

在来看看JAAS 源码目录

 

打开看一下JaasAuthenticationPlugin

/**

* Licensed to the Apache Software Foundation (ASF) under one or more

* contributor license agreements. See the NOTICE file distributed with

* this work for additional information regarding copyright ownership.

* The ASF licenses this file to You under the Apache License, Version 2.0

* (the "License"); you may not use this file except in compliance with

* the License. You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.apache.activemq.security;

import java.net.URL;

import org.apache.activemq.broker.Broker;

import org.apache.activemq.broker.BrokerPlugin;

/**

* Adds a JAAS based authentication security plugin

*

* @org.apache.xbean.XBean description="Provides a JAAS based authentication plugin"

*

*

*/

public class JaasAuthenticationPlugin implements BrokerPlugin {

protected String configuration = "activemq-domain";

protected boolean discoverLoginConfig = true;

public Broker installPlugin(Broker broker) {

initialiseJaas();

return new JaasAuthenticationBroker(broker, configuration);

}

// Properties

// -------------------------------------------------------------------------

public String getConfiguration() {

return configuration;

}

/**

* Sets the JAAS configuration domain name used

*/

public void setConfiguration(String jaasConfiguration) {

this.configuration = jaasConfiguration;

}

public boolean isDiscoverLoginConfig() {

return discoverLoginConfig;

}

/**

* Enables or disables the auto-discovery of the login.config file for JAAS to initialize itself.

* This flag is enabled by default such that if the <b>java.security.auth.login.config</b> system property

* is not defined then it is set to the location of the <b>login.config</b> file on the classpath.

*/

public void setDiscoverLoginConfig(boolean discoverLoginConfig) {

this.discoverLoginConfig = discoverLoginConfig;

}

// Implementation methods

// -------------------------------------------------------------------------

protected void initialiseJaas() {

if (discoverLoginConfig) {

String path = System.getProperty("java.security.auth.login.config");

if (path == null) {

//URL resource = Thread.currentThread().getContextClassLoader().getResource("login.config");

URL resource = null;

if (resource == null) {

resource = getClass().getClassLoader().getResource("login.config");

}

if (resource != null) {

path = resource.getFile();

System.setProperty("java.security.auth.login.config", path);

}

}

}

}

}

configuration 属性默认的是 "activemq-domain" 也就是使用的JAAS配置域名

discoverLoginConfig 属性可以看到我们在配置JAAS 认证时候可以在XML中设置启用或禁用自动发现login.config文件

  public Broker installPlugin(Broker broker) {

initialiseJaas();

return new JaasAuthenticationBroker(broker, configuration);

}

将JaasAuthenticationBroker 插件安装到brokerFiler

JaasAuthenticationBroker 代码示例

/**

* Licensed to the Apache Software Foundation (ASF) under one or more

* contributor license agreements. See the NOTICE file distributed with

* this work for additional information regarding copyright ownership.

* The ASF licenses this file to You under the Apache License, Version 2.0

* (the "License"); you may not use this file except in compliance with

* the License. You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.apache.activemq.security;

import java.security.Principal;

import java.security.cert.X509Certificate;

import java.util.Set;

import javax.security.auth.Subject;

import javax.security.auth.login.LoginContext;

import org.apache.activemq.broker.Broker;

import org.apache.activemq.broker.ConnectionContext;

import org.apache.activemq.command.ConnectionInfo;

import org.apache.activemq.jaas.JassCredentialCallbackHandler;

/**

* Logs a user in using JAAS.

*

*

*/

public class JaasAuthenticationBroker extends AbstractAuthenticationBroker {

private final String jassConfiguration;

public JaasAuthenticationBroker(Broker next, String jassConfiguration) {

super(next);

this.jassConfiguration = jassConfiguration;

}

static class JaasSecurityContext extends SecurityContext {

private final Subject subject;

public JaasSecurityContext(String userName, Subject subject) {

super(userName);

this.subject = subject;

}

@Override

public Set<Principal> getPrincipals() {

return subject.getPrincipals();

}

}

@Override

public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception {

if (context.getSecurityContext() == null) {

// Set the TCCL since it seems JAAS needs it to find the login module classes.

ClassLoader original = Thread.currentThread().getContextClassLoader();

Thread.currentThread().setContextClassLoader(JaasAuthenticationBroker.class.getClassLoader());

SecurityContext securityContext = null;

try {

securityContext = authenticate(info.getUserName(), info.getPassword(), null);

context.setSecurityContext(securityContext);

securityContexts.add(securityContext);

super.addConnection(context, info);

} catch (Exception error) {

if (securityContext != null) {

securityContexts.remove(securityContext);

}

context.setSecurityContext(null);

throw error;

} finally {

Thread.currentThread().setContextClassLoader(original);

}

} else {

super.addConnection(context, info);

}

}

@Override

public SecurityContext authenticate(String username, String password, X509Certificate[] certificates) throws SecurityException {

SecurityContext result = null;

JassCredentialCallbackHandler callback = new JassCredentialCallbackHandler(username, password);

try {

LoginContext lc = new LoginContext(jassConfiguration, callback);

lc.login();

Subject subject = lc.getSubject();

result = new JaasSecurityContext(username, subject);

} catch (Exception ex) {

throw new SecurityException("User name [" + username + "] or password is invalid.", ex);

}

return result;

}

}

初始化broker 以及config 在看看 authenticate 方法

 @Override

public SecurityContext authenticate(String username, String password, X509Certificate[] certificates) throws SecurityException {

SecurityContext result = null;

JassCredentialCallbackHandler callback = new JassCredentialCallbackHandler(username, password);

try {

LoginContext lc = new LoginContext(jassConfiguration, callback);

lc.login();

Subject subject = lc.getSubject();

result = new JaasSecurityContext(username, subject);

} catch (Exception ex) {

throw new SecurityException("User name [" + username + "] or password is invalid.", ex);

}

return result;

}

非常经典的 JAAS 认证案例, JASS 认证在应用程序中使用 JAAS 的步骤为:

1.实例化一个 LoginContext 对象,LoginContext 通过查询一个配置文件确定所使用的认证技术
2.调用 LoginContext 的 login() 方法来进行认证
3.认证通过,可通过 getSubject() 获取 subject 对象

JAAS 教程  https://blog.csdn.net/zc0565/article/details/102923918

JaasCertificateAuthenticationBroker 这个broker 使用SSL证书的JAAS身份验证代理 代码基本与JaasAuthenticationBroker 一致

JaasCertificateAuthenticationPlugin

JaasCertificateSecurityContext 同 JaasSecurityContext 一样 多了个x509证书数组 可以分辨证书

JaasDualAuthenticationPlugin 基于JAAS的SSL证书认证插件。

/**

* Licensed to the Apache Software Foundation (ASF) under one or more

* contributor license agreements. See the NOTICE file distributed with

* this work for additional information regarding copyright ownership.

* The ASF licenses this file to You under the Apache License, Version 2.0

* (the "License"); you may not use this file except in compliance with

* the License. You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.apache.activemq.security;

import org.apache.activemq.broker.Broker;

/**

* A JAAS based SSL certificate authentication plugin.

*

* @org.apache.xbean.XBean description="Provides a JAAS based authentication plugin

* which uses properties for non-SSL and certificates for SSL"

*

*

*/

public class JaasDualAuthenticationPlugin extends JaasAuthenticationPlugin {

private String sslConfiguration = "activemq-ssl-domain";

public Broker installPlugin(Broker broker) {

initialiseJaas();

return new JaasDualAuthenticationBroker(broker, configuration, sslConfiguration);

}

// Properties

// -------------------------------------------------------------------------

/**

* Set the JAAS SSL configuration domain

*/

public void setSslConfiguration(String sslConfiguration) {

this.sslConfiguration = sslConfiguration;

}

public String getSslConfiguration() {

return sslConfiguration;

}

}

大致代码也同一直不过支持的是SSL

JaasDualAuthenticationBroker

/**

* Licensed to the Apache Software Foundation (ASF) under one or more

* contributor license agreements. See the NOTICE file distributed with

* this work for additional information regarding copyright ownership.

* The ASF licenses this file to You under the Apache License, Version 2.0

* (the "License"); you may not use this file except in compliance with

* the License. You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.apache.activemq.broker;

import java.net.URI;

import java.util.Map;

import java.util.Set;

import java.util.concurrent.ThreadPoolExecutor;

import org.apache.activemq.Service;

import org.apache.activemq.broker.region.Destination;

import org.apache.activemq.broker.region.MessageReference;

import org.apache.activemq.broker.region.Region;

import org.apache.activemq.broker.region.Subscription;

import org.apache.activemq.broker.region.virtual.VirtualDestination;

import org.apache.activemq.command.ActiveMQDestination;

import org.apache.activemq.command.BrokerId;

import org.apache.activemq.command.BrokerInfo;

import org.apache.activemq.command.ConnectionInfo;

import org.apache.activemq.command.DestinationInfo;

import org.apache.activemq.command.MessageDispatch;

import org.apache.activemq.command.ProducerInfo;

import org.apache.activemq.command.SessionInfo;

import org.apache.activemq.command.TransactionId;

import org.apache.activemq.store.PListStore;

import org.apache.activemq.thread.Scheduler;

import org.apache.activemq.usage.Usage;

/**

* The Message Broker which routes messages, maintains subscriptions and

* connections, acknowledges messages and handles transactions.

*/

public interface Broker extends Region, Service {

/**

* Get a Broker from the Broker Stack that is a particular class

*

* @param type

* @return a Broker instance.

*/

Broker getAdaptor(Class<?> type);

/**

* Get the id of the broker

*/

BrokerId getBrokerId();

/**

* Get the name of the broker

*/

String getBrokerName();

/**

* A remote Broker connects

*/

void addBroker(Connection connection, BrokerInfo info);

/**

* Remove a BrokerInfo

*

* @param connection

* @param info

*/

void removeBroker(Connection connection, BrokerInfo info);

/**

* A client is establishing a connection with the broker.

*

* @throws Exception TODO

*/

void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception;

/**

* A client is disconnecting from the broker.

*

* @param context the environment the operation is being executed under.

* @param info

* @param error null if the client requested the disconnect or the error

* that caused the client to disconnect.

* @throws Exception TODO

*/

void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) throws Exception;

/**

* Adds a session.

*

* @param context

* @param info

* @throws Exception TODO

*/

void addSession(ConnectionContext context, SessionInfo info) throws Exception;

/**

* Removes a session.

*

* @param context

* @param info

* @throws Exception TODO

*/

void removeSession(ConnectionContext context, SessionInfo info) throws Exception;

/**

* Adds a producer.

*

* @param context the environment the operation is being executed under.

* @throws Exception TODO

*/

@Override

void addProducer(ConnectionContext context, ProducerInfo info) throws Exception;

/**

* Removes a producer.

*

* @param context the environment the operation is being executed under.

* @throws Exception TODO

*/

@Override

void removeProducer(ConnectionContext context, ProducerInfo info) throws Exception;

/**

* @return all clients added to the Broker.

* @throws Exception TODO

*/

Connection[] getClients() throws Exception;

/**

* @return all destinations added to the Broker.

* @throws Exception TODO

*/

ActiveMQDestination[] getDestinations() throws Exception;

/**

* return a reference destination map of a region based on the destination type

*

* @param destination

*

* @return destination Map

*/

public Map<ActiveMQDestination, Destination> getDestinationMap(ActiveMQDestination destination);

/**

* Gets a list of all the prepared xa transactions.

*

* @param context transaction ids

* @return array of TransactionId values

* @throws Exception TODO

*/

TransactionId[] getPreparedTransactions(ConnectionContext context) throws Exception;

/**

* Starts a transaction.

*

* @param context

* @param xid

* @throws Exception TODO

*/

void beginTransaction(ConnectionContext context, TransactionId xid) throws Exception;

/**

* Prepares a transaction. Only valid for xa transactions.

*

* @param context

* @param xid

* @return id

* @throws Exception TODO

*/

int prepareTransaction(ConnectionContext context, TransactionId xid) throws Exception;

/**

* Rollsback a transaction.

*

* @param context

* @param xid

* @throws Exception TODO

*/

void rollbackTransaction(ConnectionContext context, TransactionId xid) throws Exception;

/**

* Commits a transaction.

*

* @param context

* @param xid

* @param onePhase

* @throws Exception TODO

*/

void commitTransaction(ConnectionContext context, TransactionId xid, boolean onePhase) throws Exception;

/**

* Forgets a transaction.

*

* @param context

* @param transactionId

* @throws Exception

*/

void forgetTransaction(ConnectionContext context, TransactionId transactionId) throws Exception;

/**

* Get the BrokerInfo"s of any connected Brokers

*

* @return array of peer BrokerInfos

*/

BrokerInfo[] getPeerBrokerInfos();

/**

* Notify the Broker that a dispatch is going to happen

*

* @param messageDispatch

*/

void preProcessDispatch(MessageDispatch messageDispatch);

/**

* Notify the Broker that a dispatch has happened

*

* @param messageDispatch

*/

void postProcessDispatch(MessageDispatch messageDispatch);

/**

* @return true if the broker has stopped

*/

boolean isStopped();

/**

* @return a Set of all durable destinations

*/

Set<ActiveMQDestination> getDurableDestinations();

/**

* Add and process a DestinationInfo object

*

* @param context

* @param info

* @throws Exception

*/

void addDestinationInfo(ConnectionContext context, DestinationInfo info) throws Exception;

/**

* Remove and process a DestinationInfo object

*

* @param context

* @param info

*

* @throws Exception

*/

void removeDestinationInfo(ConnectionContext context, DestinationInfo info) throws Exception;

/**

* @return true if fault tolerant

*/

boolean isFaultTolerantConfiguration();

/**

* @return the connection context used to make administration operations on

* startup or via JMX MBeans

*/

ConnectionContext getAdminConnectionContext();

/**

* Sets the default administration connection context used when configuring

* the broker on startup or via JMX

*

* @param adminConnectionContext

*/

void setAdminConnectionContext(ConnectionContext adminConnectionContext);

/**

* @return the temp data store

*/

PListStore getTempDataStore();

/**

* @return the URI that can be used to connect to the local Broker

*/

URI getVmConnectorURI();

/**

* called when the brokerService starts

*/

void brokerServiceStarted();

/**

* @return the BrokerService

*/

BrokerService getBrokerService();

/**

* Ensure we get the Broker at the top of the Stack

*

* @return the broker at the top of the Stack

*/

Broker getRoot();

/**

* Determine if a message has expired -allows default behaviour to be

* overriden - as the timestamp set by the producer can be out of sync with

* the broker

*

* @param messageReference

* @return true if the message is expired

*/

boolean isExpired(MessageReference messageReference);

/**

* A Message has Expired

*

* @param context

* @param messageReference

* @param subscription (may be null)

*/

void messageExpired(ConnectionContext context, MessageReference messageReference, Subscription subscription);

/**

* A message needs to go the a DLQ

*

*

* @param context

* @param messageReference

* @param poisonCause reason for dlq submission, may be null

* @return true if Message was placed in a DLQ false if discarded.

*/

boolean sendToDeadLetterQueue(ConnectionContext context, MessageReference messageReference, Subscription subscription, Throwable poisonCause);

/**

* @return the broker sequence id

*/

long getBrokerSequenceId();

/**

* called when message is consumed

* @param context

* @param messageReference

*/

void messageConsumed(ConnectionContext context, MessageReference messageReference);

/**

* Called when message is delivered to the broker

* @param context

* @param messageReference

*/

void messageDelivered(ConnectionContext context, MessageReference messageReference);

/**

* Called when a message is discarded - e.g. running low on memory

* This will happen only if the policy is enabled - e.g. non durable topics

* @param context

* @param sub

* @param messageReference

*/

void messageDiscarded(ConnectionContext context, Subscription sub, MessageReference messageReference);

/**

* Called when there is a slow consumer

* @param context

* @param destination

* @param subs

*/

void slowConsumer(ConnectionContext context,Destination destination, Subscription subs);

/**

* Called to notify a producer is too fast

* @param context

* @param producerInfo

* @param destination

*/

void fastProducer(ConnectionContext context,ProducerInfo producerInfo,ActiveMQDestination destination);

/**

* Called when a Usage reaches a limit

* @param context

* @param destination

* @param usage

*/

void isFull(ConnectionContext context,Destination destination,Usage<?> usage);

void virtualDestinationAdded(ConnectionContext context, VirtualDestination virtualDestination);

void virtualDestinationRemoved(ConnectionContext context, VirtualDestination virtualDestination);

/**

* called when the broker becomes the master in a master/slave

* configuration

*/

void nowMasterBroker();

Scheduler getScheduler();

ThreadPoolExecutor getExecutor();

void networkBridgeStarted(BrokerInfo brokerInfo, boolean createdByDuplex, String remoteIp);

void networkBridgeStopped(BrokerInfo brokerInfo);

}

其实上面的注释已经说的非常清楚了不同JAAS域配置的JAAS身份验证代理 普通的使用哪套 SSL 使用的是哪套  

不过sslConfiguration = "activemq-ssl-domain"; 和 configuration = "activemq-domain"; 使用的默认域不同

JaasCertificateAuthenticationBroker sslBroker;
JaasAuthenticationBroker nonSslBroker;

这里面一个不是SSL 一个是SSL 的broker  这个broker 管理着2套broker 

   /**

* Overridden to allow for authentication using different Jaas

* configurations depending on if the connection is SSL or not.

*

* @param context The context for the incoming Connection.

* @param info The ConnectionInfo Command representing the incoming

* connection.

*/

从配置中可以明确使用SSL 和非SSL

 @Override

public SecurityContext authenticate(String username, String password, X509Certificate[] peerCertificates) throws SecurityException {

if (peerCertificates != null) {

return this.sslBroker.authenticate(username, password, peerCertificates);

} else {

return this.nonSslBroker.authenticate(username, password, peerCertificates);

}

}

认证也是用的是JaasAuthenticationBroker 或者  JaasCertificateAuthenticationBroker 来认证 基本上就是这样 

总的来说 JAAS 认证 可以分为普通非SSL ,SSL和2中都可以 通过配置JAAS 配置可以实现认证与授权

以上是 ActiveMQ授权源码分析jaasAuthentication(二) 的全部内容, 来源链接: utcz.com/z/515663.html

回到顶部