]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.core/src/org/argeo/security/ldap/ArgeoLdapUserDetailsManager.java
Improve login
[lgpl/argeo-commons.git] / org.argeo.security.core / src / org / argeo / security / ldap / ArgeoLdapUserDetailsManager.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
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 package org.argeo.security.ldap;
17
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;
25 import java.util.Set;
26 import java.util.TreeSet;
27
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;
37
38 /** Extends {@link LdapUserDetailsManager} by adding password encoding support. */
39 public class ArgeoLdapUserDetailsManager extends LdapUserDetailsManager
40 implements UserAdminService {
41 private String superUsername = "root";
42 private ArgeoUserAdminDaoLdap userAdminDao;
43 private PasswordEncoder passwordEncoder;
44 private final Random random;
45
46 public ArgeoLdapUserDetailsManager(ContextSource contextSource) {
47 super(contextSource);
48 this.random = createRandom();
49 }
50
51 private static Random createRandom() {
52 try {
53 return SecureRandom.getInstance("SHA1PRNG");
54 } catch (NoSuchAlgorithmException e) {
55 return new Random(System.currentTimeMillis());
56 }
57 }
58
59 @Override
60 public void changePassword(String oldPassword, String newPassword) {
61 Authentication authentication = SecurityContextHolder.getContext()
62 .getAuthentication();
63 if (authentication == null)
64 throw new ArgeoException(
65 "Cannot change password without authentication");
66 String username = authentication.getName();
67 UserDetails userDetails = loadUserByUsername(username);
68 String currentPassword = userDetails.getPassword();
69 if (currentPassword == null)
70 throw new ArgeoException("Cannot access current password");
71 if (!passwordEncoder
72 .isPasswordValid(currentPassword, oldPassword, null))
73 throw new ArgeoException("Old password invalid");
74 // Spring Security LDAP 2.0 is buggy when used with OpenLDAP and called
75 // with oldPassword argument
76 super.changePassword(null, encodePassword(newPassword));
77 }
78
79 public void newRole(String role) {
80 userAdminDao.createRole(role, superUsername);
81 }
82
83 public void synchronize() {
84 for (String username : userAdminDao.listUsers())
85 loadUserByUsername(username);
86 // TODO: find a way to remove from JCR
87 }
88
89 public void deleteRole(String role) {
90 userAdminDao.deleteRole(role);
91 }
92
93 public Set<String> listUsers() {
94 return userAdminDao.listUsers();
95 }
96
97 public Set<String> listUsersInRole(String role) {
98 Set<String> lst = new TreeSet<String>(
99 userAdminDao.listUsersInRole(role));
100 Iterator<String> it = lst.iterator();
101 while (it.hasNext()) {
102 if (it.next().equals(superUsername)) {
103 it.remove();
104 break;
105 }
106 }
107 return lst;
108 }
109
110 public List<String> listUserRoles(String username) {
111 UserDetails userDetails = loadUserByUsername(username);
112 List<String> roles = new ArrayList<String>();
113 for (GrantedAuthority ga : userDetails.getAuthorities()) {
114 roles.add(ga.getAuthority());
115 }
116 return Collections.unmodifiableList(roles);
117 }
118
119 public Set<String> listEditableRoles() {
120 return userAdminDao.listEditableRoles();
121 }
122
123 protected String encodePassword(String password) {
124 if (!password.startsWith("{")) {
125 byte[] salt = new byte[16];
126 random.nextBytes(salt);
127 return passwordEncoder.encodePassword(password, salt);
128 } else {
129 return password;
130 }
131 }
132
133 public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
134 this.passwordEncoder = passwordEncoder;
135 }
136
137 public void setSuperUsername(String superUsername) {
138 this.superUsername = superUsername;
139 }
140
141 public void setUserAdminDao(ArgeoUserAdminDaoLdap userAdminDao) {
142 this.userAdminDao = userAdminDao;
143 }
144
145 }