1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.context.httpinvoker;
17
18 import org.acegisecurity.Authentication;
19 import org.acegisecurity.AuthenticationCredentialsNotFoundException;
20 import org.acegisecurity.context.SecurityContextHolder;
21
22 import org.apache.commons.codec.binary.Base64;
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25
26 import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor;
27
28 import java.io.IOException;
29
30 import java.net.HttpURLConnection;
31
32
33 /***
34 * Adds BASIC authentication support to
35 * <code>SimpleHttpInvokerRequestExecutor</code>.
36 *
37 * @author Ben Alex
38 * @version $Id: AuthenticationSimpleHttpInvokerRequestExecutor.java,v 1.6 2005/11/17 00:56:47 benalex Exp $
39 */
40 public class AuthenticationSimpleHttpInvokerRequestExecutor
41 extends SimpleHttpInvokerRequestExecutor {
42
43
44 private static final Log logger = LogFactory.getLog(AuthenticationSimpleHttpInvokerRequestExecutor.class);
45
46
47
48 /***
49 * Provided so subclasses can perform additional configuration if required
50 * (eg set additional request headers for non-security related information
51 * etc).
52 *
53 * @param con the HTTP connection to prepare
54 * @param contentLength the length of the content to send
55 *
56 * @throws IOException if thrown by HttpURLConnection methods
57 */
58 protected void doPrepareConnection(HttpURLConnection con, int contentLength)
59 throws IOException {}
60
61 /***
62 * Called every time a HTTP invocation is made.
63 *
64 * <p>
65 * Simply allows the parent to setup the connection, and then adds an
66 * <code>Authorization</code> HTTP header property that will be used for
67 * BASIC authentication.
68 * </p>
69 *
70 * <p>
71 * The <code>SecurityContextHolder</code> is used to obtain the relevant principal
72 * and credentials.
73 * </p>
74 *
75 * @param con the HTTP connection to prepare
76 * @param contentLength the length of the content to send
77 *
78 * @throws IOException if thrown by HttpURLConnection methods
79 * @throws AuthenticationCredentialsNotFoundException if the
80 * <code>SecurityContextHolder</code> does not contain a valid
81 * <code>Authentication</code> with both its
82 * <code>principal</code> and <code>credentials</code> not
83 * <code>null</code>
84 */
85 protected void prepareConnection(HttpURLConnection con, int contentLength)
86 throws IOException, AuthenticationCredentialsNotFoundException {
87 super.prepareConnection(con, contentLength);
88
89 Authentication auth = SecurityContextHolder.getContext()
90 .getAuthentication();
91
92 if ((auth != null) && (auth.getPrincipal() != null)
93 && (auth.getCredentials() != null)) {
94 String base64 = auth.getPrincipal().toString() + ":"
95 + auth.getCredentials().toString();
96 con.setRequestProperty("Authorization",
97 "Basic " + new String(Base64.encodeBase64(base64.getBytes())));
98
99 if (logger.isDebugEnabled()) {
100 logger.debug(
101 "HttpInvocation now presenting via BASIC authentication SecurityContextHolder-derived: "
102 + auth.toString());
103 }
104 } else {
105 if (logger.isDebugEnabled()) {
106 logger.debug(
107 "Unable to set BASIC authentication header as SecurityContext did not provide valid Authentication: "
108 + auth);
109 }
110 }
111
112 doPrepareConnection(con, contentLength);
113 }
114 }