1 package org
.argeo
.security
.ldap
;
3 import java
.security
.NoSuchAlgorithmException
;
4 import java
.security
.SecureRandom
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Collections
;
7 import java
.util
.Iterator
;
9 import java
.util
.Random
;
11 import java
.util
.TreeSet
;
13 import org
.argeo
.ArgeoException
;
14 import org
.argeo
.security
.UserAdminDao
;
15 import org
.argeo
.security
.UserAdminService
;
16 import org
.springframework
.ldap
.core
.ContextSource
;
17 import org
.springframework
.security
.Authentication
;
18 import org
.springframework
.security
.GrantedAuthority
;
19 import org
.springframework
.security
.context
.SecurityContextHolder
;
20 import org
.springframework
.security
.providers
.encoding
.PasswordEncoder
;
21 import org
.springframework
.security
.userdetails
.UserDetails
;
22 import org
.springframework
.security
.userdetails
.ldap
.LdapUserDetailsManager
;
24 /** Extends {@link LdapUserDetailsManager} by adding password encoding support. */
25 public class ArgeoLdapUserDetailsManager
extends LdapUserDetailsManager
26 implements UserAdminService
{
27 private String superUsername
= "root";
28 private UserAdminDao userAdminDao
;
29 private PasswordEncoder passwordEncoder
;
30 private final Random random
;
32 public ArgeoLdapUserDetailsManager(ContextSource contextSource
) {
34 this.random
= createRandom();
37 private static Random
createRandom() {
39 return SecureRandom
.getInstance("SHA1PRNG");
40 } catch (NoSuchAlgorithmException e
) {
41 return new Random(System
.currentTimeMillis());
46 public void changePassword(String oldPassword
, String newPassword
) {
47 Authentication authentication
= SecurityContextHolder
.getContext()
49 if (authentication
== null)
50 throw new ArgeoException(
51 "Cannot change password without authentication");
52 String username
= authentication
.getName();
53 UserDetails userDetails
= loadUserByUsername(username
);
54 String currentPassword
= userDetails
.getPassword();
55 if (currentPassword
== null)
56 throw new ArgeoException("Cannot access current password");
58 .isPasswordValid(currentPassword
, oldPassword
, null))
59 throw new ArgeoException("Old password invalid");
60 // Spring Security LDAP 2.0 is buggy when used with OpenLDAP and called
61 // with oldPassword argument
62 super.changePassword(null, encodePassword(newPassword
));
65 public void newRole(String role
) {
66 userAdminDao
.createRole(role
, superUsername
);
69 public void synchronize() {
70 for (String username
: userAdminDao
.listUsers())
71 loadUserByUsername(username
);
72 // TODO: find a way to remove from JCR
75 public void deleteRole(String role
) {
76 userAdminDao
.deleteRole(role
);
79 public Set
<String
> listUsers() {
80 return userAdminDao
.listUsers();
83 public Set
<String
> listUsersInRole(String role
) {
84 Set
<String
> lst
= new TreeSet
<String
>(
85 userAdminDao
.listUsersInRole(role
));
86 Iterator
<String
> it
= lst
.iterator();
87 while (it
.hasNext()) {
88 if (it
.next().equals(superUsername
)) {
96 public List
<String
> listUserRoles(String username
) {
97 UserDetails userDetails
= loadUserByUsername(username
);
98 List
<String
> roles
= new ArrayList
<String
>();
99 for (GrantedAuthority ga
: userDetails
.getAuthorities()) {
100 roles
.add(ga
.getAuthority());
102 return Collections
.unmodifiableList(roles
);
105 public Set
<String
> listEditableRoles() {
106 return userAdminDao
.listEditableRoles();
109 protected String
encodePassword(String password
) {
110 if (!password
.startsWith("{")) {
111 byte[] salt
= new byte[16];
112 random
.nextBytes(salt
);
113 return passwordEncoder
.encodePassword(password
, salt
);
119 public void setPasswordEncoder(PasswordEncoder passwordEncoder
) {
120 this.passwordEncoder
= passwordEncoder
;
123 public void setSuperUsername(String superUsername
) {
124 this.superUsername
= superUsername
;
127 public void setUserAdminDao(UserAdminDao userAdminDao
) {
128 this.userAdminDao
= userAdminDao
;