1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.adapters.catalina;
17
18 import org.acegisecurity.Authentication;
19 import org.acegisecurity.AuthenticationException;
20 import org.acegisecurity.AuthenticationManager;
21
22 import org.acegisecurity.adapters.PrincipalAcegiUserToken;
23
24 import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
25
26 import org.apache.catalina.Container;
27 import org.apache.catalina.LifecycleException;
28 import org.apache.catalina.realm.RealmBase;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 import org.springframework.context.support.FileSystemXmlApplicationContext;
34
35 import java.io.File;
36
37 import java.security.Principal;
38 import java.security.cert.X509Certificate;
39
40 import java.util.Map;
41
42
43 /***
44 * Adapter to enable Catalina (Tomcat) to authenticate via the Acegi Security
45 * System for Spring.
46 *
47 * <p>
48 * Returns a {@link PrincipalAcegiUserToken} to Catalina's authentication
49 * system, which is subsequently available via
50 * <code>HttpServletRequest.getUserPrincipal()</code>.
51 * </p>
52 *
53 * @author Ben Alex
54 * @version $Id: CatalinaAcegiUserRealm.java,v 1.9 2005/11/25 00:26:30 benalex Exp $
55 */
56 public class CatalinaAcegiUserRealm extends RealmBase {
57
58
59 private static final Log logger = LogFactory.getLog(CatalinaAcegiUserRealm.class);
60
61
62
63 protected final String name = "CatalinaSpringUserRealm / $Id: CatalinaAcegiUserRealm.java,v 1.9 2005/11/25 00:26:30 benalex Exp $";
64 private AuthenticationManager authenticationManager;
65 private Container container;
66 private String appContextLocation;
67 private String key;
68
69
70
71 public void setAppContextLocation(String appContextLocation) {
72 this.appContextLocation = appContextLocation;
73 }
74
75 public String getAppContextLocation() {
76 return appContextLocation;
77 }
78
79 public void setKey(String key) {
80 this.key = key;
81 }
82
83 public String getKey() {
84 return key;
85 }
86
87 public Principal authenticate(String username, String credentials) {
88 if (username == null) {
89 return null;
90 }
91
92 if (credentials == null) {
93 credentials = "";
94 }
95
96 Authentication request = new UsernamePasswordAuthenticationToken(username,
97 credentials);
98 Authentication response = null;
99
100 try {
101 response = authenticationManager.authenticate(request);
102 } catch (AuthenticationException failed) {
103 if (logger.isDebugEnabled()) {
104 logger.debug("Authentication request for user: " + username
105 + " failed: " + failed.toString());
106 }
107
108 return null;
109 }
110
111 return new PrincipalAcegiUserToken(this.key,
112 response.getPrincipal().toString(),
113 response.getCredentials().toString(), response.getAuthorities(),
114 response.getPrincipal());
115 }
116
117 public Principal authenticate(String username, byte[] credentials) {
118 return authenticate(username, new String(credentials));
119 }
120
121 /***
122 * Not supported, returns null
123 *
124 * @param username DOCUMENT ME!
125 * @param digest DOCUMENT ME!
126 * @param nonce DOCUMENT ME!
127 * @param nc DOCUMENT ME!
128 * @param cnonce DOCUMENT ME!
129 * @param qop DOCUMENT ME!
130 * @param realm DOCUMENT ME!
131 * @param md5a2 DOCUMENT ME!
132 *
133 * @return DOCUMENT ME!
134 */
135 public java.security.Principal authenticate(java.lang.String username,
136 java.lang.String digest, java.lang.String nonce, java.lang.String nc,
137 java.lang.String cnonce, java.lang.String qop, java.lang.String realm,
138 java.lang.String md5a2) {
139 return null;
140 }
141
142 /***
143 * Not supported, returns null
144 *
145 * @param x509Certificates DOCUMENT ME!
146 *
147 * @return DOCUMENT ME!
148 */
149 public Principal authenticate(X509Certificate[] x509Certificates) {
150 return null;
151 }
152
153 public boolean hasRole(Principal principal, String role) {
154 if ((principal == null) || (role == null)) {
155 return false;
156 }
157
158 if (!(principal instanceof PrincipalAcegiUserToken)) {
159 logger.warn(
160 "Expected passed principal to be of type PrincipalAcegiUserToken but was "
161 + principal.getClass().getName());
162
163 return false;
164 }
165
166 PrincipalAcegiUserToken test = (PrincipalAcegiUserToken) principal;
167
168 return test.isUserInRole(role);
169 }
170
171 /***
172 * Provides the method that Catalina will use to start the container.
173 *
174 * @throws LifecycleException if a problem is detected
175 */
176 public void start() throws LifecycleException {
177 this.start(true);
178 }
179
180 protected String getName() {
181 return this.name;
182 }
183
184 /***
185 * Always returns null (we override authenticate methods)
186 *
187 * @param arg0 DOCUMENT ME!
188 *
189 * @return DOCUMENT ME!
190 */
191 protected String getPassword(String arg0) {
192 return null;
193 }
194
195 /***
196 * Always returns null (we override authenticate methods)
197 *
198 * @param arg0 DOCUMENT ME!
199 *
200 * @return DOCUMENT ME!
201 */
202 protected Principal getPrincipal(String arg0) {
203 return null;
204 }
205
206 /***
207 * Provides a method to load the container adapter without delegating to
208 * the superclass, which cannot operate outside the Catalina container.
209 *
210 * @throws LifecycleException if a problem is detected
211 */
212 protected void startForTest() throws LifecycleException {
213 this.start(false);
214 }
215
216 private void start(boolean startParent) throws LifecycleException {
217 if (startParent) {
218 super.start();
219 }
220
221 if ((appContextLocation == null) || "".equals(appContextLocation)) {
222 throw new LifecycleException("appContextLocation must be defined");
223 }
224
225 if ((key == null) || "".equals(key)) {
226 throw new LifecycleException("key must be defined");
227 }
228
229 File xml = new File(System.getProperty("catalina.base"),
230 appContextLocation);
231
232 if (!xml.exists()) {
233 throw new LifecycleException(
234 "appContextLocation does not seem to exist in "
235 + xml.toString());
236 }
237
238 FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext(
239 "file:" + xml.getAbsolutePath());
240 Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true);
241
242 if (beans.size() == 0) {
243 throw new IllegalArgumentException(
244 "Bean context must contain at least one bean of type AuthenticationManager");
245 }
246
247 String beanName = (String) beans.keySet().iterator().next();
248 authenticationManager = (AuthenticationManager) beans.get(beanName);
249 logger.info("CatalinaAcegiUserRealm Started");
250 }
251 }