1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.shiro.realm.activedirectory;
20
21 import org.apache.shiro.authc.AuthenticationInfo;
22 import org.apache.shiro.authc.AuthenticationToken;
23 import org.apache.shiro.authc.SimpleAuthenticationInfo;
24 import org.apache.shiro.authc.UsernamePasswordToken;
25 import org.apache.shiro.authz.AuthorizationInfo;
26 import org.apache.shiro.authz.SimpleAuthorizationInfo;
27 import org.apache.shiro.realm.Realm;
28 import org.apache.shiro.realm.ldap.AbstractLdapRealm;
29 import org.apache.shiro.realm.ldap.LdapContextFactory;
30 import org.apache.shiro.realm.ldap.LdapUtils;
31 import org.apache.shiro.subject.PrincipalCollection;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import javax.naming.NamingEnumeration;
36 import javax.naming.NamingException;
37 import javax.naming.directory.Attribute;
38 import javax.naming.directory.Attributes;
39 import javax.naming.directory.SearchControls;
40 import javax.naming.directory.SearchResult;
41 import javax.naming.ldap.LdapContext;
42 import java.util.Collection;
43 import java.util.HashSet;
44 import java.util.LinkedHashSet;
45 import java.util.Locale;
46 import java.util.Map;
47 import java.util.Set;
48
49
50
51
52
53
54
55
56
57
58 public class ActiveDirectoryRealm extends AbstractLdapRealm {
59
60
61
62
63
64 private static final Logger LOGGER = LoggerFactory.getLogger(ActiveDirectoryRealm.class);
65
66 private static final String ROLE_NAMES_DELIMETER = ",";
67
68
69
70
71
72
73
74
75
76
77 private Map<String, String> groupRolesMap;
78
79
80
81
82
83 public void setGroupRolesMap(Map<String, String> groupRolesMap) {
84 this.groupRolesMap = groupRolesMap;
85 }
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 protected AuthenticationInfo queryForAuthenticationInfo(AuthenticationToken token, LdapContextFactory ldapContextFactory)
104 throws NamingException {
105
106 UsernamePasswordToken upToken = (UsernamePasswordToken) token;
107
108
109 LdapContext ctx = null;
110 try {
111 ctx = ldapContextFactory.getLdapContext(upToken.getUsername(), String.valueOf(upToken.getPassword()));
112 } finally {
113 LdapUtils.closeContext(ctx);
114 }
115
116 return buildAuthenticationInfo(upToken.getUsername(), upToken.getPassword());
117 }
118
119 protected AuthenticationInfo buildAuthenticationInfo(String username, char[] password) {
120 return new SimpleAuthenticationInfo(username, password, getName());
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 protected AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principals,
140 LdapContextFactory ldapContextFactory) throws NamingException {
141
142 String username = (String) getAvailablePrincipal(principals);
143
144
145 LdapContext ldapContext = ldapContextFactory.getSystemLdapContext();
146
147 Set<String> roleNames;
148
149 try {
150 roleNames = getRoleNamesForUser(username, ldapContext);
151 } finally {
152 LdapUtils.closeContext(ldapContext);
153 }
154
155 return buildAuthorizationInfo(roleNames);
156 }
157
158 protected AuthorizationInfo buildAuthorizationInfo(Set<String> roleNames) {
159 return new SimpleAuthorizationInfo(roleNames);
160 }
161
162 protected Set<String> getRoleNamesForUser(String username, LdapContext ldapContext) throws NamingException {
163 Set<String> roleNames;
164 roleNames = new LinkedHashSet<String>();
165
166 SearchControls searchControls = new SearchControls();
167 searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
168
169 String userPrincipalName = username;
170 if (principalSuffix != null
171 && !userPrincipalName.toLowerCase(Locale.ROOT).endsWith(principalSuffix.toLowerCase(Locale.ROOT))) {
172 userPrincipalName += principalSuffix;
173 }
174
175 Object[] searchArguments = new Object[] {userPrincipalName};
176
177 NamingEnumeration answer = ldapContext.search(searchBase, searchFilter, searchArguments, searchControls);
178
179 while (answer.hasMoreElements()) {
180 SearchResult sr = (SearchResult) answer.next();
181
182 if (LOGGER.isDebugEnabled()) {
183 LOGGER.debug("Retrieving group names for user [" + sr.getName() + "]");
184 }
185
186 Attributes attrs = sr.getAttributes();
187
188 if (attrs != null) {
189 NamingEnumeration ae = attrs.getAll();
190 while (ae.hasMore()) {
191 Attribute attr = (Attribute) ae.next();
192
193 if (attr.getID().equals("memberOf")) {
194
195 Collection<String> groupNames = LdapUtils.getAllAttributeValues(attr);
196
197 if (LOGGER.isDebugEnabled()) {
198 LOGGER.debug("Groups found for user [" + username + "]: " + groupNames);
199 }
200
201 Collection<String> rolesForGroups = getRoleNamesForGroups(groupNames);
202 roleNames.addAll(rolesForGroups);
203 }
204 }
205 }
206 }
207 return roleNames;
208 }
209
210
211
212
213
214
215
216
217 protected Collection<String> getRoleNamesForGroups(Collection<String> groupNames) {
218 Set<String> roleNames = new HashSet<String>(groupNames.size());
219
220 if (groupRolesMap != null) {
221 for (String groupName : groupNames) {
222 String strRoleNames = groupRolesMap.get(groupName);
223 if (strRoleNames != null) {
224 for (String roleName : strRoleNames.split(ROLE_NAMES_DELIMETER)) {
225
226 if (LOGGER.isDebugEnabled()) {
227 LOGGER.debug("User is member of group [" + groupName + "] so adding role [" + roleName + "]");
228 }
229
230 roleNames.add(roleName);
231
232 }
233 }
234 }
235 }
236 return roleNames;
237 }
238
239 }