]> git.argeo.org Git - lgpl/argeo-commons.git/blob - ArgeoSecurityDaoLdap.java
f9628c3b2984e2ecc1711000220c4fd9b1509304
[lgpl/argeo-commons.git] / ArgeoSecurityDaoLdap.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.argeo.security.ldap;
18
19 import static org.argeo.security.core.ArgeoUserDetails.createSimpleArgeoUser;
20
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import javax.naming.Name;
25 import javax.naming.NamingException;
26 import javax.naming.directory.DirContext;
27
28 import org.argeo.security.ArgeoSecurityDao;
29 import org.argeo.security.ArgeoUser;
30 import org.argeo.security.SimpleArgeoUser;
31 import org.argeo.security.core.ArgeoUserDetails;
32 import org.springframework.beans.factory.InitializingBean;
33 import org.springframework.ldap.core.ContextExecutor;
34 import org.springframework.ldap.core.ContextMapper;
35 import org.springframework.ldap.core.DirContextAdapter;
36 import org.springframework.ldap.core.DistinguishedName;
37 import org.springframework.ldap.core.LdapTemplate;
38 import org.springframework.ldap.core.support.BaseLdapPathContextSource;
39 import org.springframework.security.Authentication;
40 import org.springframework.security.context.SecurityContextHolder;
41 import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper;
42 import org.springframework.security.ldap.LdapAuthoritiesPopulator;
43 import org.springframework.security.ldap.LdapUsernameToDnMapper;
44 import org.springframework.security.ldap.LdapUtils;
45 import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator;
46 import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
47 import org.springframework.security.userdetails.UserDetails;
48 import org.springframework.security.userdetails.UserDetailsManager;
49 import org.springframework.security.userdetails.UserDetailsService;
50 import org.springframework.security.userdetails.ldap.LdapUserDetailsManager;
51 import org.springframework.security.userdetails.ldap.LdapUserDetailsService;
52 import org.springframework.security.userdetails.ldap.UserDetailsContextMapper;
53
54 public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean {
55 // private final static Log log = LogFactory.getLog(UserDaoLdap.class);
56
57 private UserDetailsManager userDetailsManager;
58 private LdapAuthoritiesPopulator authoritiesPopulator;
59 private String userBase = "ou=People";
60 private String usernameAttributeName = "uid";
61 private String groupBase = "ou=Roles";
62 private String[] groupClasses = { "top", "groupOfNames" };
63 private String groupRoleAttributeName = "cn";
64 private String groupMemberAttributeName = "member";
65 private String defaultRole = "ROLE_USER";
66 private String rolePrefix = "ROLE_";
67
68 private final BaseLdapPathContextSource contextSource;
69 private final LdapTemplate ldapTemplate;
70
71 private LdapUsernameToDnMapper usernameMapper = null;
72
73 private UserDetailsContextMapper userDetailsMapper;
74 private LdapUserDetailsService ldapUserDetailsService;
75 private List<UserNatureMapper> userNatureMappers;
76
77 public void afterPropertiesSet() throws Exception {
78 if (usernameMapper == null)
79 usernameMapper = new DefaultLdapUsernameToDnMapper(userBase,
80 usernameAttributeName);
81
82 if (authoritiesPopulator == null) {
83 DefaultLdapAuthoritiesPopulator ap = new DefaultLdapAuthoritiesPopulator(
84 ldapTemplate.getContextSource(), groupBase);
85 ap.setDefaultRole(defaultRole);
86 ap.setGroupSearchFilter(groupMemberAttributeName + "={0}");
87 authoritiesPopulator = ap;
88 }
89
90 if (userDetailsMapper == null) {
91 ArgeoUserDetailsContextMapper audm = new ArgeoUserDetailsContextMapper();
92 audm.setUserNatureMappers(userNatureMappers);
93 userDetailsMapper = audm;
94 }
95
96 if (userDetailsManager == null) {
97 LdapUserDetailsManager ludm = new LdapUserDetailsManager(
98 ldapTemplate.getContextSource());
99 ludm.setGroupSearchBase(groupBase);
100 ludm.setUserDetailsMapper(userDetailsMapper);
101 ludm.setUsernameMapper(usernameMapper);
102 ludm.setGroupMemberAttributeName(groupMemberAttributeName);
103 userDetailsManager = ludm;
104 }
105
106 if (ldapUserDetailsService == null) {
107 FilterBasedLdapUserSearch ldapUserSearch = new FilterBasedLdapUserSearch(
108 userBase, "(" + usernameAttributeName + "={0})",
109 contextSource);
110 ldapUserDetailsService = new LdapUserDetailsService(ldapUserSearch,
111 authoritiesPopulator);
112 ldapUserDetailsService.setUserDetailsMapper(userDetailsMapper);
113 }
114 }
115
116 public ArgeoSecurityDaoLdap(BaseLdapPathContextSource contextSource) {
117 this.contextSource = contextSource;
118 ldapTemplate = new LdapTemplate(this.contextSource);
119 }
120
121 public void create(ArgeoUser user) {
122 userDetailsManager.createUser(new ArgeoUserDetails(user));
123 }
124
125 public ArgeoUser getUser(String uname) {
126 SimpleArgeoUser user = createSimpleArgeoUser(getDetails(uname));
127 user.setPassword(null);
128 return user;
129 }
130
131 public ArgeoUser getUserWithPassword(String uname) {
132 return createSimpleArgeoUser(getDetails(uname));
133 }
134
135 public ArgeoUser getCurrentUser() {
136 ArgeoUser argeoUser = ArgeoUserDetails.securityContextUser();
137 if (argeoUser == null)
138 return null;
139 if (argeoUser.getRoles().contains(defaultRole))
140 argeoUser.getRoles().remove(defaultRole);
141 return argeoUser;
142 }
143
144 @SuppressWarnings("unchecked")
145 public List<ArgeoUser> listUsers() {
146 List<String> usernames = (List<String>) ldapTemplate.listBindings(
147 new DistinguishedName(userBase), new ContextMapper() {
148 public Object mapFromContext(Object ctxArg) {
149 DirContextAdapter ctx = (DirContextAdapter) ctxArg;
150 return ctx.getStringAttribute(usernameAttributeName);
151 }
152 });
153
154 List<ArgeoUser> lst = new ArrayList<ArgeoUser>();
155 for (String username : usernames) {
156 lst.add(createSimpleArgeoUser(getDetails(username)));
157 }
158 return lst;
159 }
160
161 @SuppressWarnings("unchecked")
162 public List<String> listEditableRoles() {
163 return (List<String>) ldapTemplate.listBindings(groupBase,
164 new ContextMapper() {
165 public Object mapFromContext(Object ctxArg) {
166 String groupName = ((DirContextAdapter) ctxArg)
167 .getStringAttribute(groupRoleAttributeName);
168 String roleName = convertGroupToRole(groupName);
169 return roleName;
170 }
171 });
172 }
173
174 public void update(ArgeoUser user) {
175 userDetailsManager.updateUser(new ArgeoUserDetails(user));
176 }
177
178 public void delete(String username) {
179 userDetailsManager.deleteUser(username);
180 }
181
182 public Boolean userExists(String username) {
183 return userDetailsManager.userExists(username);
184 }
185
186 public void createRole(String role, final String superuserName) {
187 String group = convertRoleToGroup(role);
188 DistinguishedName superuserDn = (DistinguishedName) ldapTemplate
189 .executeReadWrite(new ContextExecutor() {
190 public Object executeWithContext(DirContext ctx)
191 throws NamingException {
192 return LdapUtils.getFullDn(
193 usernameMapper.buildDn(superuserName), ctx);
194 }
195 });
196
197 Name groupDn = buildGroupDn(group);
198 DirContextAdapter context = new DirContextAdapter();
199 context.setAttributeValues("objectClass", groupClasses);
200 context.setAttributeValue("cn", group);
201
202 // Add superuser because cannot create empty group
203 context.setAttributeValue(groupMemberAttributeName,
204 superuserDn.toString());
205
206 ldapTemplate.bind(groupDn, context, null);
207 }
208
209 public void deleteRole(String role) {
210 String group = convertRoleToGroup(role);
211 Name dn = buildGroupDn(group);
212 ldapTemplate.unbind(dn);
213 }
214
215 protected String convertRoleToGroup(String role) {
216 String group = role;
217 if (group.startsWith(rolePrefix)) {
218 group = group.substring(rolePrefix.length());
219 group = group.toLowerCase();
220 }
221 return group;
222 }
223
224 public String convertGroupToRole(String groupName) {
225 groupName = groupName.toUpperCase();
226
227 return rolePrefix + groupName;
228 }
229
230 protected Name buildGroupDn(String name) {
231 return new DistinguishedName(groupRoleAttributeName + "=" + name + ","
232 + groupBase);
233 }
234
235 public void setUserDetailsManager(UserDetailsManager userDetailsManager) {
236 this.userDetailsManager = userDetailsManager;
237 }
238
239 public void setUserBase(String userBase) {
240 this.userBase = userBase;
241 }
242
243 public void setUsernameAttributeName(String usernameAttribute) {
244 this.usernameAttributeName = usernameAttribute;
245 }
246
247 public void setAuthoritiesPopulator(
248 LdapAuthoritiesPopulator authoritiesPopulator) {
249 this.authoritiesPopulator = authoritiesPopulator;
250 }
251
252 protected UserDetails getDetails(String username) {
253 return userDetailsManager.loadUserByUsername(username);
254 }
255
256 public void setGroupBase(String groupBase) {
257 this.groupBase = groupBase;
258 }
259
260 public void setGroupRoleAttributeName(String groupRoleAttributeName) {
261 this.groupRoleAttributeName = groupRoleAttributeName;
262 }
263
264 public void setGroupMemberAttributeName(String groupMemberAttributeName) {
265 this.groupMemberAttributeName = groupMemberAttributeName;
266 }
267
268 public void setDefaultRole(String defaultRole) {
269 this.defaultRole = defaultRole;
270 }
271
272 public void setRolePrefix(String rolePrefix) {
273 this.rolePrefix = rolePrefix;
274 }
275
276 public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper) {
277 this.usernameMapper = usernameMapper;
278 }
279
280 public void setUserDetailsMapper(UserDetailsContextMapper userDetailsMapper) {
281 this.userDetailsMapper = userDetailsMapper;
282 }
283
284 public LdapAuthoritiesPopulator getAuthoritiesPopulator() {
285 return authoritiesPopulator;
286 }
287
288 public UserDetailsContextMapper getUserDetailsMapper() {
289 return userDetailsMapper;
290 }
291
292 public void setUserNatureMappers(List<UserNatureMapper> userNatureMappers) {
293 this.userNatureMappers = userNatureMappers;
294 }
295
296 public String getDefaultRole() {
297 return defaultRole;
298 }
299
300 public void setGroupClasses(String[] groupClasses) {
301 this.groupClasses = groupClasses;
302 }
303
304 public UserDetailsService getUserDetailsService() {
305 return ldapUserDetailsService;
306 }
307
308 }