View Javadoc
1   /*
2    * $Id$
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts.chain.commands;
22  
23  import org.apache.struts.chain.contexts.ActionContext;
24  import org.apache.struts.config.ActionConfig;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  /**
29   * <p>Determine whether the requested action is authorized for the current
30   * user. If not, abort chain processing and perferably, return an error
31   * message of some kind.</p>
32   *
33   * @version $Rev$ $Date: 2005-11-12 13:01:44 -0500 (Sat, 12 Nov 2005)
34   *          $
35   */
36  public abstract class AbstractAuthorizeAction extends ActionCommandBase {
37      // ------------------------------------------------------ Instance Variables
38  
39      /**
40       * The {@code Log} instance for this class.
41       */
42      private final Logger log =
43          LoggerFactory.getLogger(AbstractAuthorizeAction.class);
44  
45      // ---------------------------------------------------------- Public Methods
46  
47      /**
48       * <p>Determine whether the requested action is authorized for the current
49       * user.  If not, abort chain processing and perferably, return an error
50       * message of some kind.</p>
51       *
52       * @param actionCtx The <code>Context</code> for the current request
53       * @return <code>false</code> if the user is authorized for the selected
54       *         action, else <code>true</code> to abort processing.
55       * @throws UnauthorizedActionException if authorization fails
56       * or if an error is encountered in the course of performing the authorization.
57       */
58      @Override
59      protected boolean execute_(ActionContext actionCtx)
60          throws Exception {
61          // Retrieve ActionConfig
62          ActionConfig actionConfig = actionCtx.getActionConfig();
63  
64          // Is this action protected by role requirements?
65          if (!isAuthorizationRequired(actionConfig)) {
66              return CONTINUE_PROCESSING;
67          }
68  
69          boolean throwEx;
70  
71          try {
72              throwEx =
73                  !(isAuthorized(actionCtx, actionConfig.getRoleNames(),
74                      actionConfig));
75          } catch (UnauthorizedActionException ex) {
76              throw ex;
77          } catch (Exception ex) {
78              throwEx = true;
79              log.error("Unable to complete authorization process", ex);
80          }
81  
82          if (throwEx) {
83              // The current user is not authorized for this action
84              throw new UnauthorizedActionException(getErrorMessage(actionCtx,
85                      actionConfig));
86          } else {
87              return CONTINUE_PROCESSING;
88          }
89      }
90  
91      /**
92       * <p>Must authorization rules be consulted?  The base implementation
93       * returns <code>true</code> if the given <code>ActionConfig</code> has
94       * one or more roles defined.</p>
95       *
96       * @param actionConfig the current ActionConfig object
97       * @return true if the <code>isAuthorized</code> method should be
98       *         consulted.
99       */
100     protected boolean isAuthorizationRequired(ActionConfig actionConfig) {
101         String[] roles = actionConfig.getRoleNames();
102 
103         return (roles != null) && (roles.length > 0);
104     }
105 
106     // ------------------------------------------------------- Protected Methods
107 
108     /**
109      * <p>Determine if the action is authorized for the given roles.</p>
110      *
111      * @param context      The <code>Context</code> for the current request
112      * @param roles        An array of valid roles for this request
113      * @param actionConfig The current action mapping
114      * @return <code>true</code> if the request is authorized, else
115      *         <code>false</code>
116      * @throws UnauthorizedActionException If the logic determines that the request is not authorized
117      * but does not wish to rely upon the default mechanism reporting the error.
118      * @throws Exception If the action cannot be tested for authorization
119      */
120     protected abstract boolean isAuthorized(ActionContext context,
121         String[] roles, ActionConfig actionConfig)
122         throws Exception;
123 
124     /**
125      * <p> Retrieve error message from context. </p>
126      *
127      * @param context      The <code>Context</code> for the current request
128      * @param actionConfig The current action mapping
129      * @return error message
130      */
131     protected abstract String getErrorMessage(ActionContext context,
132         ActionConfig actionConfig);
133 }