| /** |
| * 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.shiro; |
| |
| import org.apache.activemq.ConfigurationException; |
| import org.apache.activemq.broker.Broker; |
| import org.apache.activemq.broker.BrokerPluginSupport; |
| import org.apache.activemq.shiro.authc.AuthenticationFilter; |
| import org.apache.activemq.shiro.authc.AuthenticationPolicy; |
| import org.apache.activemq.shiro.authc.DefaultAuthenticationPolicy; |
| import org.apache.activemq.shiro.authz.AuthorizationFilter; |
| import org.apache.activemq.shiro.env.IniEnvironment; |
| import org.apache.activemq.shiro.subject.ConnectionSubjectFactory; |
| import org.apache.activemq.shiro.subject.DefaultConnectionSubjectFactory; |
| import org.apache.activemq.shiro.subject.SubjectFilter; |
| import org.apache.shiro.config.Ini; |
| import org.apache.shiro.env.Environment; |
| import org.apache.shiro.mgt.SecurityManager; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * @since 5.10.0 |
| */ |
| public class ShiroPlugin extends BrokerPluginSupport { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(ShiroPlugin.class); |
| |
| private volatile boolean enabled = true; |
| |
| private Broker broker; //the downstream broker after any/all Shiro-specific broker filters |
| |
| private SecurityManager securityManager; |
| private Environment environment; |
| private IniEnvironment iniEnvironment; //only used if the above environment instance is not explicitly configured |
| |
| private SubjectFilter subjectFilter; |
| |
| private AuthenticationFilter authenticationFilter; |
| |
| private AuthorizationFilter authorizationFilter; |
| |
| public ShiroPlugin() { |
| |
| //Default if this.environment is not configured. See the ensureEnvironment() method below. |
| iniEnvironment = new IniEnvironment(); |
| |
| authorizationFilter = new AuthorizationFilter(); |
| |
| // we want to share one AuthenticationPolicy instance across both the AuthenticationFilter and the |
| // ConnectionSubjectFactory: |
| AuthenticationPolicy authcPolicy = new DefaultAuthenticationPolicy(); |
| |
| authenticationFilter = new AuthenticationFilter(); |
| authenticationFilter.setAuthenticationPolicy(authcPolicy); |
| authenticationFilter.setNext(authorizationFilter); |
| |
| subjectFilter = new SubjectFilter(); |
| DefaultConnectionSubjectFactory subjectFactory = new DefaultConnectionSubjectFactory(); |
| subjectFactory.setAuthenticationPolicy(authcPolicy); |
| subjectFilter.setConnectionSubjectFactory(subjectFactory); |
| subjectFilter.setNext(authenticationFilter); |
| } |
| |
| public SubjectFilter getSubjectFilter() { |
| return subjectFilter; |
| } |
| |
| public void setSubjectFilter(SubjectFilter subjectFilter) { |
| this.subjectFilter = subjectFilter; |
| this.subjectFilter.setNext(this.authenticationFilter); |
| } |
| |
| public AuthenticationFilter getAuthenticationFilter() { |
| return authenticationFilter; |
| } |
| |
| public void setAuthenticationFilter(AuthenticationFilter authenticationFilter) { |
| this.authenticationFilter = authenticationFilter; |
| this.authenticationFilter.setNext(this.authorizationFilter); |
| this.subjectFilter.setNext(authenticationFilter); |
| } |
| |
| public AuthorizationFilter getAuthorizationFilter() { |
| return authorizationFilter; |
| } |
| |
| public void setAuthorizationFilter(AuthorizationFilter authorizationFilter) { |
| this.authorizationFilter = authorizationFilter; |
| this.authorizationFilter.setNext(this.broker); |
| this.authenticationFilter.setNext(authorizationFilter); |
| } |
| |
| public void setEnabled(boolean enabled) { |
| this.enabled = enabled; |
| if (isInstalled()) { |
| //we're running, so apply the changes now: |
| applyEnabled(enabled); |
| } |
| } |
| |
| public boolean isEnabled() { |
| if (isInstalled()) { |
| return getNext() == this.subjectFilter; |
| } |
| return enabled; |
| } |
| |
| private void applyEnabled(boolean enabled) { |
| if (enabled) { |
| //ensure the SubjectFilter and downstream filters are used: |
| super.setNext(this.subjectFilter); |
| } else { |
| //Shiro is not enabled, restore the original downstream broker: |
| super.setNext(this.broker); |
| } |
| } |
| |
| public Environment getEnvironment() { |
| return environment; |
| } |
| |
| public void setEnvironment(Environment environment) { |
| this.environment = environment; |
| } |
| |
| public SecurityManager getSecurityManager() { |
| return securityManager; |
| } |
| |
| public void setSecurityManager(SecurityManager securityManager) { |
| this.securityManager = securityManager; |
| } |
| |
| public void setIni(Ini ini) { |
| this.iniEnvironment.setIni(ini); |
| } |
| |
| public void setIniConfig(String iniConfig) { |
| this.iniEnvironment.setIniConfig(iniConfig); |
| } |
| |
| public void setIniResourcePath(String resourcePath) { |
| this.iniEnvironment.setIniResourcePath(resourcePath); |
| } |
| |
| // =============================================================== |
| // Authentication Configuration |
| // =============================================================== |
| public void setAuthenticationEnabled(boolean authenticationEnabled) { |
| this.authenticationFilter.setEnabled(authenticationEnabled); |
| } |
| |
| public boolean isAuthenticationEnabled() { |
| return this.authenticationFilter.isEnabled(); |
| } |
| |
| public AuthenticationPolicy getAuthenticationPolicy() { |
| return authenticationFilter.getAuthenticationPolicy(); |
| } |
| |
| public void setAuthenticationPolicy(AuthenticationPolicy authenticationPolicy) { |
| authenticationFilter.setAuthenticationPolicy(authenticationPolicy); |
| //also set it on the ConnectionSubjectFactory: |
| ConnectionSubjectFactory factory = subjectFilter.getConnectionSubjectFactory(); |
| if (factory instanceof DefaultConnectionSubjectFactory) { |
| ((DefaultConnectionSubjectFactory) factory).setAuthenticationPolicy(authenticationPolicy); |
| } |
| } |
| |
| // =============================================================== |
| // Authorization Configuration |
| // =============================================================== |
| public void setAuthorizationEnabled(boolean authorizationEnabled) { |
| this.authorizationFilter.setEnabled(authorizationEnabled); |
| } |
| |
| public boolean isAuthorizationEnabled() { |
| return this.authorizationFilter.isEnabled(); |
| } |
| |
| private Environment ensureEnvironment() throws ConfigurationException { |
| if (this.environment != null) { |
| return this.environment; |
| } |
| |
| //this.environment is null - set it: |
| if (this.securityManager != null) { |
| this.environment = new Environment() { |
| @Override |
| public SecurityManager getSecurityManager() { |
| return ShiroPlugin.this.securityManager; |
| } |
| }; |
| return this.environment; |
| } |
| |
| this.iniEnvironment.init(); //will automatically catch any config errors and throw. |
| |
| this.environment = iniEnvironment; |
| |
| return this.iniEnvironment; |
| } |
| |
| @Override |
| public Broker installPlugin(Broker broker) throws Exception { |
| |
| Environment environment = ensureEnvironment(); |
| |
| this.authorizationFilter.setEnvironment(environment); |
| this.authenticationFilter.setEnvironment(environment); |
| this.subjectFilter.setEnvironment(environment); |
| |
| this.broker = broker; |
| this.authorizationFilter.setNext(broker); |
| this.authenticationFilter.setNext(this.authorizationFilter); |
| this.subjectFilter.setNext(this.authenticationFilter); |
| |
| Broker next = this.subjectFilter; |
| if (!this.enabled) { |
| //not enabled at startup - default to the original broker: |
| next = broker; |
| } |
| |
| setNext(next); |
| return this; |
| } |
| |
| private boolean isInstalled() { |
| return getNext() != null; |
| } |
| } |