001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.security; 018 019import java.security.Principal; 020import java.util.HashSet; 021import java.util.Iterator; 022import java.util.Map; 023import java.util.Set; 024import java.util.concurrent.CopyOnWriteArrayList; 025 026import org.apache.activemq.broker.Broker; 027import org.apache.activemq.broker.BrokerFilter; 028import org.apache.activemq.broker.ConnectionContext; 029import org.apache.activemq.command.ConnectionInfo; 030import org.apache.activemq.jaas.GroupPrincipal; 031 032/** 033 * Handles authenticating a users against a simple user name/password map. 034 * 035 * 036 */ 037public class SimpleAuthenticationBroker extends BrokerFilter { 038 039 private boolean anonymousAccessAllowed = false; 040 private String anonymousUser; 041 private String anonymousGroup; 042 private final Map<String,String> userPasswords; 043 private final Map<String,Set<Principal>> userGroups; 044 private final CopyOnWriteArrayList<SecurityContext> securityContexts = new CopyOnWriteArrayList<SecurityContext>(); 045 046 public SimpleAuthenticationBroker(Broker next, Map<String,String> userPasswords, Map<String,Set<Principal>> userGroups) { 047 super(next); 048 this.userPasswords = userPasswords; 049 this.userGroups = userGroups; 050 } 051 052 public void setAnonymousAccessAllowed(boolean anonymousAccessAllowed) { 053 this.anonymousAccessAllowed = anonymousAccessAllowed; 054 } 055 056 public void setAnonymousUser(String anonymousUser) { 057 this.anonymousUser = anonymousUser; 058 } 059 060 public void setAnonymousGroup(String anonymousGroup) { 061 this.anonymousGroup = anonymousGroup; 062 } 063 064 public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception { 065 066 SecurityContext s = context.getSecurityContext(); 067 if (s == null) { 068 // Check the username and password. 069 if (anonymousAccessAllowed && info.getUserName() == null && info.getPassword() == null) { 070 info.setUserName(anonymousUser); 071 s = new SecurityContext(info.getUserName()) { 072 public Set<Principal> getPrincipals() { 073 Set<Principal> groups = new HashSet<Principal>(); 074 groups.add(new GroupPrincipal(anonymousGroup)); 075 return groups; 076 } 077 }; 078 } else { 079 String pw = userPasswords.get(info.getUserName()); 080 if (pw == null || !pw.equals(info.getPassword())) { 081 throw new SecurityException( 082 "User name [" + info.getUserName() + "] or password is invalid."); 083 } 084 085 final Set<Principal> groups = userGroups.get(info.getUserName()); 086 s = new SecurityContext(info.getUserName()) { 087 public Set<Principal> getPrincipals() { 088 return groups; 089 } 090 }; 091 } 092 093 context.setSecurityContext(s); 094 securityContexts.add(s); 095 } 096 try { 097 super.addConnection(context, info); 098 } catch (Exception e) { 099 securityContexts.remove(s); 100 context.setSecurityContext(null); 101 throw e; 102 } 103 } 104 105 public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) 106 throws Exception { 107 super.removeConnection(context, info, error); 108 if (securityContexts.remove(context.getSecurityContext())) { 109 context.setSecurityContext(null); 110 } 111 } 112 113 /** 114 * Previously logged in users may no longer have the same access anymore. 115 * Refresh all the logged into users. 116 */ 117 public void refresh() { 118 for (Iterator<SecurityContext> iter = securityContexts.iterator(); iter.hasNext();) { 119 SecurityContext sc = iter.next(); 120 sc.getAuthorizedReadDests().clear(); 121 sc.getAuthorizedWriteDests().clear(); 122 } 123 } 124 125}