View Javadoc

1   /* Copyright 2004, 2005 Acegi Technology Pty Limited
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    *     http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
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      //~ Static fields/initializers =============================================
43  
44      private static final Log logger = LogFactory.getLog(AuthenticationSimpleHttpInvokerRequestExecutor.class);
45  
46      //~ Methods ================================================================
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 }