View Javadoc

1   /* Copyright 2004 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.runas;
17  
18  import org.acegisecurity.Authentication;
19  import org.acegisecurity.ConfigAttribute;
20  import org.acegisecurity.ConfigAttributeDefinition;
21  import org.acegisecurity.GrantedAuthority;
22  import org.acegisecurity.GrantedAuthorityImpl;
23  import org.acegisecurity.RunAsManager;
24  
25  import org.springframework.beans.factory.InitializingBean;
26  import org.springframework.util.Assert;
27  
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Vector;
31  
32  
33  /***
34   * Basic concrete implementation of a {@link RunAsManager}.
35   * 
36   * <p>
37   * Is activated if any {@link ConfigAttribute#getAttribute()} is prefixed  with
38   * <Code>RUN_AS_</code>. If found, it generates a new {@link RunAsUserToken}
39   * containing the same principal, credentials and granted authorities as the
40   * original {@link Authentication} object, along with {@link
41   * GrantedAuthorityImpl}s for each <code>RUN_AS_</code> indicated. The created
42   * <code>GrantedAuthorityImpl</code>s will be prefixed with a special prefix
43   * indicating that it is a role (default prefix value is <code>ROLE_</code>),
44   * and then the remainder of the <code>RUN_AS_</code> keyword. For example,
45   * <code>RUN_AS_FOO</code> will result in the creation of a granted authority
46   * of <code>ROLE_RUN_AS_FOO</code>.
47   * </p>
48   * 
49   * <p>
50   * The role prefix may be overriden from the default, to match that used
51   * elsewhere, for example when using an existing role database with another
52   * prefix. An empty role prefix may also be specified. Note however that there
53   * are potential issues with using an empty role prefix since different
54   * categories of  {@link org.acegisecurity.ConfigAttribute} can not be
55   * properly discerned based on the prefix, with possible consequences when
56   * performing voting and other actions. However, this option may be of some
57   * use when using preexisting role names without a prefix, and no ability
58   * exists to prefix them with a role prefix on reading them in, such as
59   * provided for example in  {@link
60   * org.acegisecurity.userdetails.jdbc.JdbcDaoImpl}.
61   * </p>
62   *
63   * @author Ben Alex
64   * @author colin sampaleanu
65   * @version $Id: RunAsManagerImpl.java,v 1.8 2005/11/29 13:10:14 benalex Exp $
66   */
67  public class RunAsManagerImpl implements RunAsManager, InitializingBean {
68      //~ Instance fields ========================================================
69  
70      private String key;
71      private String rolePrefix = "ROLE_";
72  
73      //~ Methods ================================================================
74  
75      public void setKey(String key) {
76          this.key = key;
77      }
78  
79      public String getKey() {
80          return key;
81      }
82  
83      /***
84       * Allows the default role prefix of <code>ROLE_</code> to be overriden.
85       * May be set to an empty value, although this is usually not desireable.
86       *
87       * @param rolePrefix the new prefix
88       */
89      public void setRolePrefix(String rolePrefix) {
90          this.rolePrefix = rolePrefix;
91      }
92  
93      public String getRolePrefix() {
94          return rolePrefix;
95      }
96  
97      public void afterPropertiesSet() throws Exception {
98          Assert.notNull(key, "A Key is required and should match that configured for the RunAsImplAuthenticationProvider");
99      }
100 
101     public Authentication buildRunAs(Authentication authentication,
102         Object object, ConfigAttributeDefinition config) {
103         List newAuthorities = new Vector();
104         Iterator iter = config.getConfigAttributes();
105 
106         while (iter.hasNext()) {
107             ConfigAttribute attribute = (ConfigAttribute) iter.next();
108 
109             if (this.supports(attribute)) {
110                 GrantedAuthorityImpl extraAuthority = new GrantedAuthorityImpl(getRolePrefix()
111                         + attribute.getAttribute());
112                 newAuthorities.add(extraAuthority);
113             }
114         }
115 
116         if (newAuthorities.size() == 0) {
117             return null;
118         } else {
119             for (int i = 0; i < authentication.getAuthorities().length; i++) {
120                 newAuthorities.add(authentication.getAuthorities()[i]);
121             }
122 
123             GrantedAuthority[] resultType = {new GrantedAuthorityImpl("holder")};
124             GrantedAuthority[] newAuthoritiesAsArray = (GrantedAuthority[]) newAuthorities
125                 .toArray(resultType);
126 
127             return new RunAsUserToken(this.key, authentication.getPrincipal(),
128                 authentication.getCredentials(), newAuthoritiesAsArray,
129                 authentication.getClass());
130         }
131     }
132 
133     public boolean supports(ConfigAttribute attribute) {
134         if ((attribute.getAttribute() != null)
135             && attribute.getAttribute().startsWith("RUN_AS_")) {
136             return true;
137         } else {
138             return false;
139         }
140     }
141 
142     /***
143      * This implementation supports any type of class, because it does not
144      * query the presented secure object.
145      *
146      * @param clazz the secure object
147      *
148      * @return alwaus <code>true</code>
149      */
150     public boolean supports(Class clazz) {
151         return true;
152     }
153 }