2 * Copyright (C) 2007-2012 Argeo GmbH
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.
16 package org
.argeo
.cms
.internal
.useradmin
.ldap
;
18 import java
.security
.NoSuchAlgorithmException
;
19 import java
.security
.SecureRandom
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Collections
;
22 import java
.util
.Iterator
;
23 import java
.util
.List
;
24 import java
.util
.Random
;
26 import java
.util
.TreeSet
;
28 import org
.argeo
.ArgeoException
;
29 import org
.argeo
.security
.UserAdminService
;
30 import org
.springframework
.ldap
.core
.ContextSource
;
31 import org
.springframework
.security
.authentication
.encoding
.PasswordEncoder
;
32 import org
.springframework
.security
.core
.Authentication
;
33 import org
.springframework
.security
.core
.GrantedAuthority
;
34 import org
.springframework
.security
.core
.context
.SecurityContextHolder
;
35 import org
.springframework
.security
.core
.userdetails
.UserDetails
;
36 import org
.springframework
.security
.ldap
.userdetails
.LdapUserDetailsManager
;
38 /** Extends {@link LdapUserDetailsManager} by adding password encoding support. */
39 @SuppressWarnings("deprecation")
40 public class ArgeoLdapUserDetailsManager
extends LdapUserDetailsManager
41 implements UserAdminService
{
42 private String superUsername
= "root";
43 private ArgeoUserAdminDaoLdap userAdminDao
;
44 private PasswordEncoder passwordEncoder
;
45 private final Random random
;
47 public ArgeoLdapUserDetailsManager(ContextSource contextSource
) {
49 this.random
= createRandom();
52 private static Random
createRandom() {
54 return SecureRandom
.getInstance("SHA1PRNG");
55 } catch (NoSuchAlgorithmException e
) {
56 return new Random(System
.currentTimeMillis());
61 public void changePassword(String oldPassword
, String newPassword
) {
62 Authentication authentication
= SecurityContextHolder
.getContext()
64 if (authentication
== null)
65 throw new ArgeoException(
66 "Cannot change password without authentication");
67 String username
= authentication
.getName();
68 UserDetails userDetails
= loadUserByUsername(username
);
69 String currentPassword
= userDetails
.getPassword();
70 if (currentPassword
== null)
71 throw new ArgeoException("Cannot access current password");
73 .isPasswordValid(currentPassword
, oldPassword
, null))
74 throw new ArgeoException("Old password invalid");
75 // Spring Security LDAP 2.0 is buggy when used with OpenLDAP and called
76 // with oldPassword argument
77 super.changePassword(null, encodePassword(newPassword
));
80 public void newRole(String role
) {
81 userAdminDao
.createRole(role
, superUsername
);
84 public void synchronize() {
85 for (String username
: userAdminDao
.listUsers())
86 loadUserByUsername(username
);
87 // TODO: find a way to remove from JCR
90 public void deleteRole(String role
) {
91 userAdminDao
.deleteRole(role
);
94 public Set
<String
> listUsers() {
95 return userAdminDao
.listUsers();
98 public Set
<String
> listUsersInRole(String role
) {
99 Set
<String
> lst
= new TreeSet
<String
>(
100 userAdminDao
.listUsersInRole(role
));
101 Iterator
<String
> it
= lst
.iterator();
102 while (it
.hasNext()) {
103 if (it
.next().equals(superUsername
)) {
111 public List
<String
> listUserRoles(String username
) {
112 UserDetails userDetails
= loadUserByUsername(username
);
113 List
<String
> roles
= new ArrayList
<String
>();
114 for (GrantedAuthority ga
: userDetails
.getAuthorities()) {
115 roles
.add(ga
.getAuthority());
117 return Collections
.unmodifiableList(roles
);
120 public Set
<String
> listEditableRoles() {
121 return userAdminDao
.listEditableRoles();
124 protected String
encodePassword(String password
) {
125 if (!password
.startsWith("{")) {
126 byte[] salt
= new byte[16];
127 random
.nextBytes(salt
);
128 return passwordEncoder
.encodePassword(password
, salt
);
134 public void setPasswordEncoder(PasswordEncoder passwordEncoder
) {
135 this.passwordEncoder
= passwordEncoder
;
138 public void setSuperUsername(String superUsername
) {
139 this.superUsername
= superUsername
;
142 public void setUserAdminDao(ArgeoUserAdminDaoLdap userAdminDao
) {
143 this.userAdminDao
= userAdminDao
;