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.taglibs.authz;
    17
    18  import org.acegisecurity.Authentication;
    19  import org.acegisecurity.GrantedAuthority;
    20  import org.acegisecurity.GrantedAuthorityImpl;
    21  import org.acegisecurity.context.SecurityContextHolder;
    22
    23  import org.springframework.util.StringUtils;
    24
    25  import org.springframework.web.util.ExpressionEvaluationUtils;
    26
    27  import java.util.Arrays;
    28  import java.util.Collection;
    29  import java.util.Collections;
    30  import java.util.HashSet;
    31  import java.util.Iterator;
    32  import java.util.Set;
    33
    34  import javax.servlet.jsp.JspException;
    35  import javax.servlet.jsp.tagext.Tag;
    36  import javax.servlet.jsp.tagext.TagSupport;
    37
    38
    39  /***
    40   * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows it's
    41   * body through if some authorizations are granted to the request's principal.
    42   *
    43   * @author Francois Beausoleil
    44   * @version $Id: AuthorizeTag.java,v 1.13 2005/11/17 00:56:29 benalex Exp $
    45   */
    46  public class AuthorizeTag extends TagSupport {
    47      //~ Instance fields ========================================================
    48
    49      private String ifAllGranted = "";
    50      private String ifAnyGranted = "";
    51      private String ifNotGranted = "";
    52
    53      //~ Methods ================================================================
    54
    55      public void setIfAllGranted(String ifAllGranted) throws JspException {
    56          this.ifAllGranted = ifAllGranted;
    57      }
    58
    59      public String getIfAllGranted() {
    60          return ifAllGranted;
    61      }
    62
    63      public void setIfAnyGranted(String ifAnyGranted) throws JspException {
    64          this.ifAnyGranted = ifAnyGranted;
    65      }
    66
    67      public String getIfAnyGranted() {
    68          return ifAnyGranted;
    69      }
    70
    71      public void setIfNotGranted(String ifNotGranted) throws JspException {
    72          this.ifNotGranted = ifNotGranted;
    73      }
    74
    75      public String getIfNotGranted() {
    76          return ifNotGranted;
    77      }
    78
    79      public int doStartTag() throws JspException {
    80          if (((null == ifAllGranted) || "".equals(ifAllGranted))
    81              && ((null == ifAnyGranted) || "".equals(ifAnyGranted))
    82              && ((null == ifNotGranted) || "".equals(ifNotGranted))) {
    83              return Tag.SKIP_BODY;
    84          }
    85
    86          final Collection granted = getPrincipalAuthorities();
    87
    88          final String evaledIfNotGranted = ExpressionEvaluationUtils
    89              .evaluateString("ifNotGranted", ifNotGranted, pageContext);
    90
    91          if ((null != evaledIfNotGranted) && !"".equals(evaledIfNotGranted)) {
    92              Set grantedCopy = retainAll(granted,
    93                      parseAuthoritiesString(evaledIfNotGranted));
    94
    95              if (!grantedCopy.isEmpty()) {
    96                  return Tag.SKIP_BODY;
    97              }
    98          }
    99
    100         final String evaledIfAllGranted = ExpressionEvaluationUtils
    101             .evaluateString("ifAllGranted", ifAllGranted, pageContext);
    102
    103         if ((null != evaledIfAllGranted) && !"".equals(evaledIfAllGranted)) {
    104             if (!granted.containsAll(parseAuthoritiesString(evaledIfAllGranted))) {
    105                 return Tag.SKIP_BODY;
    106             }
    107         }
    108
    109         final String evaledIfAnyGranted = ExpressionEvaluationUtils
    110             .evaluateString("ifAnyGranted", ifAnyGranted, pageContext);
    111
    112         if ((null != evaledIfAnyGranted) && !"".equals(evaledIfAnyGranted)) {
    113             Set grantedCopy = retainAll(granted,
    114                     parseAuthoritiesString(evaledIfAnyGranted));
    115
    116             if (grantedCopy.isEmpty()) {
    117                 return Tag.SKIP_BODY;
    118             }
    119         }
    120
    121         return Tag.EVAL_BODY_INCLUDE;
    122     }
    123
    124     private Collection getPrincipalAuthorities() {
    125         Authentication currentUser = SecurityContextHolder.getContext()
    126                                                           .getAuthentication();
    127
    128         if (null == currentUser) {
    129             return Collections.EMPTY_LIST;
    130         }
    131
    132         if ((null == currentUser.getAuthorities())
    133             || (currentUser.getAuthorities().length < 1)) {
    134             return Collections.EMPTY_LIST;
    135         }
    136
    137         Collection granted = Arrays.asList(currentUser.getAuthorities());
    138
    139         return granted;
    140     }
    141
    142     private Set authoritiesToRoles(Collection c) {
    143         Set target = new HashSet();
    144
    145         for (Iterator iterator = c.iterator(); iterator.hasNext();) {
    146             GrantedAuthority authority = (GrantedAuthority) iterator.next();
    147
    148             if (null == authority.getAuthority()) {
    149                 throw new IllegalArgumentException(
    150                     "Cannot process GrantedAuthority objects which return null from getAuthority() - attempting to process "
    151                     + authority.toString());
    152             }
    153
    154             target.add(authority.getAuthority());
    155         }
    156
    157         return target;
    158     }
    159
    160     private Set parseAuthoritiesString(String authorizationsString) {
    161         final Set requiredAuthorities = new HashSet();
    162         final String[] authorities = StringUtils
    163             .commaDelimitedListToStringArray(authorizationsString);
    164
    165         for (int i = 0; i < authorities.length; i++) {
    166             String authority = authorities[i];
    167
    168          // Remove the role's whitespace characters without depending on JDK 1.4+
    169          // Includes space, tab, new line, carriage return and form feed.
    170          String role = StringUtils.replace(authority, " ", "");
    171          role = StringUtils.replace(role, "\t", "");
    172          role = StringUtils.replace(role, "\r", "");
    173          role = StringUtils.replace(role, "\n", "");
    174          role = StringUtils.replace(role, "\f", "");
    175
    176          requiredAuthorities.add(new GrantedAuthorityImpl(role));
    177         }
    178
    179         return requiredAuthorities;
    180     }
    181
    182     /***
    183      * Find the common authorities between the current authentication's {@link
    184      * GrantedAuthority} and the ones that have been specified in the tag's
    185      * ifAny, ifNot or ifAllGranted attributes.
    186      *
    187      * <p>
    188      * We need to manually iterate over both collections, because the granted
    189      * authorities might not implement {@link Object#equals(Object)} and
    190      * {@link Object#hashCode()} in the same way as {@link
    191      * GrantedAuthorityImpl}, thereby invalidating {@link
    192      * Collection#retainAll(java.util.Collection)} results.
    193      * </p>
    194      *
    195      * <p>
    196      * <strong>CAVEAT</strong>:  This method <strong>will not</strong> work if
    197      * the granted authorities returns a <code>null</code> string as the
    198      * return value of {@link
    199      * org.acegisecurity.GrantedAuthority#getAuthority()}.
    200      * </p>
    201      *
    202      * <p>
    203      * Reported by rawdave, on Fri Feb 04, 2005 2:11 pm in the Acegi Security
    204      * System for Spring forums.
    205      * </p>
    206      *
    207      * @param granted The authorities granted by the authentication. May be any
    208      *        implementation of {@link GrantedAuthority} that does
    209      *        <strong>not</strong> return <code>null</code> from {@link
    210      *        org.acegisecurity.GrantedAuthority#getAuthority()}.
    211      * @param required A {@link Set} of {@link GrantedAuthorityImpl}s that have
    212      *        been built using ifAny, ifAll or ifNotGranted.
    213      *
    214      * @return A set containing only the common authorities between
    215      *         <var>granted</var> and <var>required</var>.
    216      *
    217      * @see <a
    218      *      href="http://forum.springframework.org/viewtopic.php?t=3367">authz:authorize
    219      *      ifNotGranted not behaving as expected</a>
    220      */
    221     private Set retainAll(final Collection granted, final Set required) {
    222         Set grantedRoles = authoritiesToRoles(granted);
    223         Set requiredRoles = authoritiesToRoles(required);
    224         grantedRoles.retainAll(requiredRoles);
    225
    226         return rolesToAuthorities(grantedRoles, granted);
    227     }
    228
    229     private Set rolesToAuthorities(Set grantedRoles, Collection granted) {
    230         Set target = new HashSet();
    231
    232         for (Iterator iterator = grantedRoles.iterator(); iterator.hasNext();) {
    233             String role = (String) iterator.next();
    234
    235             for (Iterator grantedIterator = granted.iterator();
    236                 grantedIterator.hasNext();) {
    237                 GrantedAuthority authority = (GrantedAuthority) grantedIterator
    238                     .next();
    239
    240                 if (authority.getAuthority().equals(role)) {
    241                     target.add(authority);
    242
    243                     break;
    244                 }
    245             }
    246         }
    247
    248         return target;
    249     }
    250 }