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.rmi;
    17
    18  import org.acegisecurity.context.SecurityContext;
    19  import org.acegisecurity.context.SecurityContextHolder;
    20  import org.acegisecurity.context.SecurityContextImpl;
    21
    22  import org.aopalliance.intercept.MethodInvocation;
    23
    24  import org.apache.commons.logging.Log;
    25  import org.apache.commons.logging.LogFactory;
    26
    27  import org.springframework.remoting.support.RemoteInvocation;
    28
    29  import java.lang.reflect.InvocationTargetException;
    30
    31
    32  /***
    33   * The actual <code>RemoteInvocation</code> that is passed from the client to
    34   * the server, which contains the contents of {@link SecurityContextHolder},
    35   * being a {@link SecurityContext} object.
    36   *
    37   * <p>
    38   * When constructed on the client via {@link
    39   * org.acegisecurity.context.rmi.ContextPropagatingRemoteInvocationFactory},
    40   * the contents of the <code>SecurityContext</code> are stored inside the
    41   * object. The object is then passed to the server that is processing the
    42   * remote invocation. Upon the server invoking the remote invocation, it will
    43   * retrieve the passed contents of the <code>SecurityContextHolder</code> and
    44   * set them to the server-side <code>SecurityContextHolder</code> whilst the
    45   * target object is invoked. When the target invocation has been completed,
    46   * the server-side <code>SecurityContextHolder</code> will be reset to a new
    47   * instance of <code>SecurityContextImpl</code>.
    48   * </p>
    49   *
    50   * @author James Monaghan
    51   * @author Ben Alex
    52   * @version $Id: ContextPropagatingRemoteInvocation.java,v 1.7 2005/11/23 16:09:44 luke_t Exp $
    53   */
    54  public class ContextPropagatingRemoteInvocation extends RemoteInvocation {
    55      //~ Static fields/initializers =============================================
    56
    57      private static final Log logger = LogFactory.getLog(ContextPropagatingRemoteInvocation.class);
    58
    59      //~ Instance fields ========================================================
    60
    61      private SecurityContext securityContext;
    62
    63      //~ Constructors ===========================================================
    64
    65      /***
    66       * Constructs the object, storing the value of the client-side
    67       * <code>SecurityContextHolder</code> inside the object.
    68       *
    69       * @param methodInvocation the method to invoke
    70       */
    71      public ContextPropagatingRemoteInvocation(MethodInvocation methodInvocation) {
    72          super(methodInvocation);
    73          securityContext = SecurityContextHolder.getContext();
    74
    75          if (logger.isDebugEnabled()) {
    76              logger.debug("RemoteInvocation now has SecurityContext: "
    77                  + securityContext);
    78          }
    79      }
    80
    81      //~ Methods ================================================================
    82
    83      /***
    84       * Invoked on the server-side as described in the class JavaDocs.
    85       *
    86       * <p>
    87       * Invocations will always have their {@link
    88       * org.acegisecurity.Authentication#setAuthenticated(boolean)} set to
    89       * <code>false</code>, which is guaranteed to always be accepted by
    90       * <code>Authentication</code> implementations. This ensures that even
    91       * remotely authenticated <code>Authentication</code>s will be untrusted
    92       * by the server-side, which is an appropriate security measure.
    93       * </p>
    94       *
    95       * @param targetObject the target object to apply the invocation to
    96       *
    97       * @return the invocation result
    98       *
    99       * @throws NoSuchMethodException if the method name could not be resolved
    100      * @throws IllegalAccessException if the method could not be accessed
    101      * @throws InvocationTargetException if the method invocation resulted in
    102      *         an exception
    103      */
    104     public Object invoke(Object targetObject)
    105         throws NoSuchMethodException, IllegalAccessException,
    106             InvocationTargetException {
    107         SecurityContextHolder.setContext(securityContext);
    108
    109         if ((SecurityContextHolder.getContext() != null)
    110             && (SecurityContextHolder.getContext().getAuthentication() != null)) {
    111             SecurityContextHolder.getContext().getAuthentication()
    112                                  .setAuthenticated(false);
    113         }
    114
    115         if (logger.isDebugEnabled()) {
    116             logger.debug("Set SecurityContextHolder to contain: "
    117                 + securityContext);
    118         }
    119
    120         try {
    121
    122             return super.invoke(targetObject);
    123
    124         } finally {
    125
    126             SecurityContextHolder.setContext(new SecurityContextImpl());
    127
    128             if (logger.isDebugEnabled()) {
    129                 logger.debug(
    130                     "Set SecurityContext to new instance of SecurityContextImpl");
    131             }
    132         }
    133     }
    134 }