2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org
.argeo
.security
.ldap
;
19 import static org
.argeo
.security
.core
.ArgeoUserDetails
.createSimpleArgeoUser
;
21 import java
.util
.ArrayList
;
22 import java
.util
.List
;
24 import javax
.naming
.Name
;
25 import javax
.naming
.NamingException
;
26 import javax
.naming
.directory
.DirContext
;
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
;
54 public class ArgeoSecurityDaoLdap
implements ArgeoSecurityDao
, InitializingBean
{
55 // private final static Log log = LogFactory.getLog(UserDaoLdap.class);
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_";
68 private final BaseLdapPathContextSource contextSource
;
69 private final LdapTemplate ldapTemplate
;
71 private LdapUsernameToDnMapper usernameMapper
= null;
73 private UserDetailsContextMapper userDetailsMapper
;
74 private LdapUserDetailsService ldapUserDetailsService
;
75 private List
<UserNatureMapper
> userNatureMappers
;
77 public void afterPropertiesSet() throws Exception
{
78 if (usernameMapper
== null)
79 usernameMapper
= new DefaultLdapUsernameToDnMapper(userBase
,
80 usernameAttributeName
);
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
;
90 if (userDetailsMapper
== null) {
91 ArgeoUserDetailsContextMapper audm
= new ArgeoUserDetailsContextMapper();
92 audm
.setUserNatureMappers(userNatureMappers
);
93 userDetailsMapper
= audm
;
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
;
106 if (ldapUserDetailsService
== null) {
107 FilterBasedLdapUserSearch ldapUserSearch
= new FilterBasedLdapUserSearch(
108 userBase
, "(" + usernameAttributeName
+ "={0})",
110 ldapUserDetailsService
= new LdapUserDetailsService(ldapUserSearch
,
111 authoritiesPopulator
);
112 ldapUserDetailsService
.setUserDetailsMapper(userDetailsMapper
);
116 public ArgeoSecurityDaoLdap(BaseLdapPathContextSource contextSource
) {
117 this.contextSource
= contextSource
;
118 ldapTemplate
= new LdapTemplate(this.contextSource
);
121 public void create(ArgeoUser user
) {
122 userDetailsManager
.createUser(new ArgeoUserDetails(user
));
125 public ArgeoUser
getUser(String uname
) {
126 SimpleArgeoUser user
= createSimpleArgeoUser(getDetails(uname
));
127 user
.setPassword(null);
131 public ArgeoUser
getUserWithPassword(String uname
) {
132 return createSimpleArgeoUser(getDetails(uname
));
135 public ArgeoUser
getCurrentUser() {
136 Authentication authentication
= SecurityContextHolder
.getContext()
137 .getAuthentication();
138 ArgeoUser argeoUser
= ArgeoUserDetails
.asArgeoUser(authentication
);
139 if (argeoUser
== null)
141 if (argeoUser
.getRoles().contains(defaultRole
))
142 argeoUser
.getRoles().remove(defaultRole
);
146 @SuppressWarnings("unchecked")
147 public List
<ArgeoUser
> listUsers() {
148 List
<String
> usernames
= (List
<String
>) ldapTemplate
.listBindings(
149 new DistinguishedName(userBase
), new ContextMapper() {
150 public Object
mapFromContext(Object ctxArg
) {
151 DirContextAdapter ctx
= (DirContextAdapter
) ctxArg
;
152 return ctx
.getStringAttribute(usernameAttributeName
);
156 List
<ArgeoUser
> lst
= new ArrayList
<ArgeoUser
>();
157 for (String username
: usernames
) {
158 lst
.add(createSimpleArgeoUser(getDetails(username
)));
163 @SuppressWarnings("unchecked")
164 public List
<String
> listEditableRoles() {
165 return (List
<String
>) ldapTemplate
.listBindings(groupBase
,
166 new ContextMapper() {
167 public Object
mapFromContext(Object ctxArg
) {
168 String groupName
= ((DirContextAdapter
) ctxArg
)
169 .getStringAttribute(groupRoleAttributeName
);
170 String roleName
= convertGroupToRole(groupName
);
176 public void update(ArgeoUser user
) {
177 userDetailsManager
.updateUser(new ArgeoUserDetails(user
));
180 public void delete(String username
) {
181 userDetailsManager
.deleteUser(username
);
184 public Boolean
userExists(String username
) {
185 return userDetailsManager
.userExists(username
);
188 public void createRole(String role
, final String superuserName
) {
189 String group
= convertRoleToGroup(role
);
190 DistinguishedName superuserDn
= (DistinguishedName
) ldapTemplate
191 .executeReadWrite(new ContextExecutor() {
192 public Object
executeWithContext(DirContext ctx
)
193 throws NamingException
{
194 return LdapUtils
.getFullDn(usernameMapper
195 .buildDn(superuserName
), ctx
);
199 Name groupDn
= buildGroupDn(group
);
200 DirContextAdapter context
= new DirContextAdapter();
201 context
.setAttributeValues("objectClass", groupClasses
);
202 context
.setAttributeValue("cn", group
);
204 // Add superuser because cannot create empty group
205 context
.setAttributeValue(groupMemberAttributeName
, superuserDn
208 ldapTemplate
.bind(groupDn
, context
, null);
211 public void deleteRole(String role
) {
212 String group
= convertRoleToGroup(role
);
213 Name dn
= buildGroupDn(group
);
214 ldapTemplate
.unbind(dn
);
217 protected String
convertRoleToGroup(String role
) {
219 if (group
.startsWith(rolePrefix
)) {
220 group
= group
.substring(rolePrefix
.length());
221 group
= group
.toLowerCase();
226 public String
convertGroupToRole(String groupName
) {
227 groupName
= groupName
.toUpperCase();
229 return rolePrefix
+ groupName
;
232 protected Name
buildGroupDn(String name
) {
233 return new DistinguishedName(groupRoleAttributeName
+ "=" + name
+ ","
237 public void setUserDetailsManager(UserDetailsManager userDetailsManager
) {
238 this.userDetailsManager
= userDetailsManager
;
241 public void setUserBase(String userBase
) {
242 this.userBase
= userBase
;
245 public void setUsernameAttributeName(String usernameAttribute
) {
246 this.usernameAttributeName
= usernameAttribute
;
249 public void setAuthoritiesPopulator(
250 LdapAuthoritiesPopulator authoritiesPopulator
) {
251 this.authoritiesPopulator
= authoritiesPopulator
;
254 protected UserDetails
getDetails(String username
) {
255 return userDetailsManager
.loadUserByUsername(username
);
258 public void setGroupBase(String groupBase
) {
259 this.groupBase
= groupBase
;
262 public void setGroupRoleAttributeName(String groupRoleAttributeName
) {
263 this.groupRoleAttributeName
= groupRoleAttributeName
;
266 public void setGroupMemberAttributeName(String groupMemberAttributeName
) {
267 this.groupMemberAttributeName
= groupMemberAttributeName
;
270 public void setDefaultRole(String defaultRole
) {
271 this.defaultRole
= defaultRole
;
274 public void setRolePrefix(String rolePrefix
) {
275 this.rolePrefix
= rolePrefix
;
278 public void setUsernameMapper(LdapUsernameToDnMapper usernameMapper
) {
279 this.usernameMapper
= usernameMapper
;
282 public void setUserDetailsMapper(UserDetailsContextMapper userDetailsMapper
) {
283 this.userDetailsMapper
= userDetailsMapper
;
286 public LdapAuthoritiesPopulator
getAuthoritiesPopulator() {
287 return authoritiesPopulator
;
290 public UserDetailsContextMapper
getUserDetailsMapper() {
291 return userDetailsMapper
;
294 public void setUserNatureMappers(List
<UserNatureMapper
> userNatureMappers
) {
295 this.userNatureMappers
= userNatureMappers
;
298 public String
getDefaultRole() {
302 public void setGroupClasses(String
[] groupClasses
) {
303 this.groupClasses
= groupClasses
;
306 public UserDetailsService
getUserDetailsService() {
307 return ldapUserDetailsService
;