]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java
JCR Keyring
[lgpl/argeo-commons.git] / security / plugins / org.argeo.security.equinox / src / main / java / org / argeo / security / equinox / SpringLoginModule.java
1 package org.argeo.security.equinox;
2
3 import java.util.Map;
4
5 import javax.security.auth.Subject;
6 import javax.security.auth.callback.Callback;
7 import javax.security.auth.callback.CallbackHandler;
8 import javax.security.auth.callback.NameCallback;
9 import javax.security.auth.callback.PasswordCallback;
10 import javax.security.auth.callback.TextOutputCallback;
11 import javax.security.auth.login.LoginException;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15 import org.argeo.security.SiteAuthenticationToken;
16 import org.springframework.security.Authentication;
17 import org.springframework.security.AuthenticationManager;
18 import org.springframework.security.BadCredentialsException;
19 import org.springframework.security.context.SecurityContextHolder;
20 import org.springframework.security.providers.jaas.SecurityContextLoginModule;
21
22 /** Login module which caches one subject per thread. */
23 public class SpringLoginModule extends SecurityContextLoginModule {
24 private final static Log log = LogFactory.getLog(SpringLoginModule.class);
25
26 private AuthenticationManager authenticationManager;
27
28 private CallbackHandler callbackHandler;
29
30 private Subject subject;
31
32 private Long waitBetweenFailedLoginAttempts = 5*1000l;
33
34 public SpringLoginModule() {
35
36 }
37
38 @SuppressWarnings("rawtypes")
39 public void initialize(Subject subject, CallbackHandler callbackHandler,
40 Map sharedState, Map options) {
41 super.initialize(subject, callbackHandler, sharedState, options);
42 this.callbackHandler = callbackHandler;
43 this.subject = subject;
44 }
45
46 public boolean login() throws LoginException {
47 try {
48 // thread already logged in
49 if (SecurityContextHolder.getContext().getAuthentication() != null)
50 return super.login();
51
52 // reset all principals and credentials
53 if (log.isTraceEnabled())
54 log.trace("Resetting all principals and credentials of "
55 + subject);
56 if (subject.getPrincipals() != null)
57 subject.getPrincipals().clear();
58 if (subject.getPrivateCredentials() != null)
59 subject.getPrivateCredentials().clear();
60 if (subject.getPublicCredentials() != null)
61 subject.getPublicCredentials().clear();
62
63 // ask for username and password
64 Callback label = new TextOutputCallback(
65 TextOutputCallback.INFORMATION, "Required login");
66 NameCallback nameCallback = new NameCallback("User");
67 PasswordCallback passwordCallback = new PasswordCallback(
68 "Password", false);
69
70 // NameCallback urlCallback = new NameCallback("Site URL");
71
72 if (callbackHandler == null)
73 throw new LoginException("No call back handler available");
74 callbackHandler.handle(new Callback[] { label, nameCallback,
75 passwordCallback });
76
77 // Set user name and password
78 String username = nameCallback.getName();
79 if (username == null || username.trim().equals(""))
80 return false;
81
82 String password = "";
83 if (passwordCallback.getPassword() != null)
84 password = String.valueOf(passwordCallback.getPassword());
85
86 // String url = urlCallback.getName();
87 // TODO: set it via system properties
88 String workspace = null;
89
90 SiteAuthenticationToken credentials = new SiteAuthenticationToken(
91 username, password, null, workspace);
92
93 Authentication authentication;
94 try {
95 authentication = authenticationManager
96 .authenticate(credentials);
97 } catch (BadCredentialsException e) {
98 // wait between failed login attempts
99 Thread.sleep(waitBetweenFailedLoginAttempts);
100 throw e;
101 }
102 registerAuthentication(authentication);
103 boolean res = super.login();
104 return res;
105 } catch (LoginException e) {
106 throw e;
107 } catch (ThreadDeath e) {
108 LoginException le = new LoginException(
109 "Spring Security login thread died");
110 le.initCause(e);
111 throw le;
112 } catch (Exception e) {
113 LoginException le = new LoginException(
114 "Spring Security login failed");
115 le.initCause(e);
116 throw le;
117 }
118 }
119
120 @Override
121 public boolean logout() throws LoginException {
122 subject.getPrincipals().clear();
123 return super.logout();
124 }
125
126 /**
127 * Register an {@link Authentication} in the security context.
128 *
129 * @param authentication
130 * has to implement {@link Authentication}.
131 */
132 protected void registerAuthentication(Object authentication) {
133 SecurityContextHolder.getContext().setAuthentication(
134 (Authentication) authentication);
135 }
136
137 public void setAuthenticationManager(
138 AuthenticationManager authenticationManager) {
139 this.authenticationManager = authenticationManager;
140 }
141 }