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