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 }