]> git.argeo.org Git - lgpl/argeo-commons.git/blob - ArgeoSecurityDaoLdap.java
3d6d8ff9949dd9c22664abb6788ae508e5a55a73
[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.context.SecurityContextHolder;
40 import org.springframework.security.ldap.DefaultLdapUsernameToDnMapper;
41 import org.springframework.security.ldap.LdapAuthoritiesPopulator;
42 import org.springframework.security.ldap.LdapUsernameToDnMapper;
43 import org.springframework.security.ldap.LdapUtils;
44 import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator;
45 import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
46 import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
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 synchronized void create(ArgeoUser user) {
122 userDetailsManager.createUser(new ArgeoUserDetails(user));
123 }
124
125 public synchronized ArgeoUser getUser(String uname) {
126 SimpleArgeoUser user = createSimpleArgeoUser(getDetails(uname));
127 user.setPassword(null);
128 return user;
129 }
130
131 public synchronized 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 synchronized 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 synchronized void update(ArgeoUser user) {
175 ArgeoUserDetails argeoUserDetails = new ArgeoUserDetails(user);
176 userDetailsManager.updateUser(new ArgeoUserDetails(user));
177 // refresh logged in user
178 if (ArgeoUserDetails.securityContextUser().getUsername()
179 .equals(argeoUserDetails.getUsername())) {
180 SecurityContextHolder.getContext().setAuthentication(
181 new UsernamePasswordAuthenticationToken(argeoUserDetails,
182 null, argeoUserDetails.getAuthorities()));
183 }
184 }
185
186 public synchronized void delete(String username) {
187 userDetailsManager.deleteUser(username);
188 }
189
190 public synchronized Boolean userExists(String username) {
191 return userDetailsManager.userExists(username);
192 }
193
194 public void createRole(String role, final String superuserName) {
195 String group = convertRoleToGroup(role);
196 DistinguishedName superuserDn = (DistinguishedName) ldapTemplate
197 .executeReadWrite(new ContextExecutor() {
198 public Object executeWithContext(DirContext ctx)
199 throws NamingException {
200 return LdapUtils.getFullDn(
201 usernameMapper.buildDn(superuserName), ctx);
202 }
203 });
204
205 Name groupDn = buildGroupDn(group);
206 DirContextAdapter context = new DirContextAdapter();
207 context.setAttributeValues("objectClass", groupClasses);
208 context.setAttributeValue("cn", group);
209
210 // Add superuser because cannot create empty group
211 context.setAttributeValue(groupMemberAttributeName,
212 superuserDn.toString());
213
214 ldapTemplate.bind(groupDn, context, null);
215 }
216
217 public void deleteRole(String role) {
218 String group = convertRoleToGroup(role);
219 Name dn = buildGroupDn(group);
220 ldapTemplate.unbind(dn);
221 }
222
223 protected String convertRoleToGroup(String role) {
224 String group = role;
225 if (group.startsWith(rolePrefix)) {
226 group = group.substring(rolePrefix.length());
227 group = group.toLowerCase();
228 }
229 return group;
230 }
231
232 public String convertGroupToRole(String groupName) {
233 groupName = groupName.toUpperCase();
234
235 return rolePrefix + groupName;
236 }
237
238 protected Name buildGroupDn(String name) {
239 return new DistinguishedName(groupRoleAttributeName + "=" + name + ","
240 + groupBase);
241 }
242
243 public void setUserDetailsManager(UserDetailsManager userDetailsManager) {
244 this.userDetailsManager = userDetailsManager;
245 }
246
247 public void setUserBase(String userBase) {
248 this.userBase = userBase;
249 }
250
251 public void setUsernameAttributeName(String usernameAttribute) {
252 this.usernameAttributeName = usernameAttribute;
253 }
254
255 public void setAuthoritiesPopulator(
256 LdapAuthoritiesPopulator authoritiesPopulator) {
257 this.authoritiesPopulator = authoritiesPopulator;
258 }
259
260 protected UserDetails getDetails(String username) {
261 return userDetailsManager.loadUserByUsername(username);
262 }
263
264 public void setGroupBase(String groupBase) {
265 this.groupBase = groupBase;
266 }
267
268 public void setGroupRoleAttributeName(String groupRoleAttributeName) {
269 this.groupRoleAttributeName = groupRoleAttributeName;
270 }
271
272 public void setGroupMemberAttributeName(String groupMemberAttributeName) {
273 this.groupMemberAttributeName = groupMemberAttributeName;
274 }
275
276 public void setDefaultRole(String defaultRole) {
277 this.defaultRole = defaultRole;
278 }
279
280 public void setRolePrefix(String rolePrefix) {
281 this.rolePrefix = rolePrefix;
282 }
283
284 public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper) {
285 this.usernameMapper = usernameMapper;
286 }
287
288 public void setUserDetailsMapper(UserDetailsContextMapper userDetailsMapper) {
289 this.userDetailsMapper = userDetailsMapper;
290 }
291
292 public LdapAuthoritiesPopulator getAuthoritiesPopulator() {
293 return authoritiesPopulator;
294 }
295
296 public UserDetailsContextMapper getUserDetailsMapper() {
297 return userDetailsMapper;
298 }
299
300 public void setUserNatureMappers(List<UserNatureMapper> userNatureMappers) {
301 this.userNatureMappers = userNatureMappers;
302 }
303
304 public String getDefaultRole() {
305 return defaultRole;
306 }
307
308 public void setGroupClasses(String[] groupClasses) {
309 this.groupClasses = groupClasses;
310 }
311
312 public UserDetailsService getUserDetailsService() {
313 return ldapUserDetailsService;
314 }
315
316 }