| CODENOTIFIER | HelpYou are not signed inSign in |
Project: Acegi
Revision: 3267
Author: luke_t
Date: 01 Sep 2008 21:05:57
Changes:Converted literals to classname/interfacename docbook tags for easier indexing
Files:| ... | ...@@ -5,50 +5,50 @@ | |
| 5 | 5 | <info><title>Authorities</title></info> |
| 6 | 6 | |
| 7 | 7 | <para>As briefly mentioned in the Authentication section, all |
| 8 | <literal>Authentication</literal> implementations are required to | |
| 9 | store an array of <literal>GrantedAuthority</literal> objects. These | |
| 8 | <interfacename>Authentication</interfacename> implementations are required to | |
| 9 | store an array of <interfacename>GrantedAuthority</interfacename> objects. These | |
| 10 | 10 | represent the authorities that have been granted to the principal. The |
| 11 | <literal>GrantedAuthority</literal> objects are inserted into the | |
| 12 | <literal>Authentication</literal> object by the | |
| 13 | <literal>AuthenticationManager</literal> and are later read by | |
| 14 | <literal>AccessDecisionManager</literal>s when making authorization | |
| 11 | <interfacename>GrantedAuthority</interfacename> objects are inserted into the | |
| 12 | <interfacename>Authentication</interfacename> object by the | |
| 13 | <interfacename>AuthenticationManager</interfacename> and are later read by | |
| 14 | <interfacename>AccessDecisionManager</interfacename>s when making authorization | |
| 15 | 15 | decisions.</para> |
| 16 | 16 | |
| 17 | <para><literal>GrantedAuthority</literal> is an interface with only | |
| 17 | <para><interfacename>GrantedAuthority</interfacename> is an interface with only | |
| 18 | 18 | one method: |
| 19 | 19 | <programlisting> |
| 20 | 20 | String getAuthority(); |
| 21 | 21 | </programlisting> |
| 22 | This method allows <literal>AccessDecisionManager</literal>s to | |
| 22 | This method allows <interfacename>AccessDecisionManager</interfacename>s to | |
| 23 | 23 | obtain a precise <literal>String</literal> representation of the |
| 24 | <literal>GrantedAuthority</literal>. By returning a representation as | |
| 25 | a <literal>String</literal>, a <literal>GrantedAuthority</literal> can | |
| 26 | be easily "read" by most <literal>AccessDecisionManager</literal>s. If | |
| 27 | a <literal>GrantedAuthority</literal> cannot be precisely represented | |
| 24 | <interfacename>GrantedAuthority</interfacename>. By returning a representation as | |
| 25 | a <literal>String</literal>, a <interfacename>GrantedAuthority</interfacename> can | |
| 26 | be easily "read" by most <interfacename>AccessDecisionManager</interfacename>s. If | |
| 27 | a <interfacename>GrantedAuthority</interfacename> cannot be precisely represented | |
| 28 | 28 | as a <literal>String</literal>, the |
| 29 | <literal>GrantedAuthority</literal> is considered "complex" and | |
| 29 | <interfacename>GrantedAuthority</interfacename> is considered "complex" and | |
| 30 | 30 | <literal>getAuthority()</literal> must return |
| 31 | 31 | <literal>null</literal>.</para> |
| 32 | 32 | |
| 33 | <para>An example of a "complex" <literal>GrantedAuthority</literal> | |
| 33 | <para>An example of a "complex" <interfacename>GrantedAuthority</interfacename> | |
| 34 | 34 | would be an implementation that stores a list of operations and |
| 35 | 35 | authority thresholds that apply to different customer account numbers. |
| 36 | Representing this complex <literal>GrantedAuthority</literal> as a | |
| 36 | Representing this complex <interfacename>GrantedAuthority</interfacename> as a | |
| 37 | 37 | <literal>String</literal> would be quite complex, and as a result the |
| 38 | 38 | <literal>getAuthority()</literal> method should return |
| 39 | 39 | <literal>null</literal>. This will indicate to any |
| 40 | <literal>AccessDecisionManager</literal> that it will need to | |
| 41 | specifically support the <literal>GrantedAuthority</literal> | |
| 40 | <interfacename>AccessDecisionManager</interfacename> that it will need to | |
| 41 | specifically support the <interfacename>GrantedAuthority</interfacename> | |
| 42 | 42 | implementation in order to understand its contents.</para> |
| 43 | 43 | |
| 44 | 44 | <para>Spring Security includes one concrete |
| 45 | <literal>GrantedAuthority</literal> implementation, | |
| 45 | <interfacename>GrantedAuthority</interfacename> implementation, | |
| 46 | 46 | <literal>GrantedAuthorityImpl</literal>. This allows any |
| 47 | 47 | user-specified <literal>String</literal> to be converted into a |
| 48 | <literal>GrantedAuthority</literal>. All | |
| 49 | <literal>AuthenticationProvider</literal>s included with the security | |
| 48 | <interfacename>GrantedAuthority</interfacename>. All | |
| 49 | <classname>AuthenticationProvider</classname>s included with the security | |
| 50 | 50 | architecture use <literal>GrantedAuthorityImpl</literal> to populate |
| 51 | the <literal>Authentication</literal> object.</para> | |
| 51 | the <interfacename>Authentication</interfacename> object.</para> | |
| 52 | 52 | </section> |
| 53 | 53 | |
| 54 | 54 | <section xml:id="pre-invocation"> |
| ... | ...@@ -64,10 +64,10 @@ | |
| 64 | 64 | |
| 65 | 65 | <section> |
| 66 | 66 | <title>The AccessDecisionManager</title> |
| 67 | <para>The <literal>AccessDecisionManager</literal> is called by the | |
| 68 | <literal>AbstractSecurityInterceptor</literal> and is responsible for | |
| 67 | <para>The <interfacename>AccessDecisionManager</interfacename> is called by the | |
| 68 | <classname>AbstractSecurityInterceptor</classname> and is responsible for | |
| 69 | 69 | making final access control decisions. The |
| 70 | <literal>AccessDecisionManager</literal> interface contains three | |
| 70 | <interfacename>AccessDecisionManager</interfacename> interface contains three | |
| 71 | 71 | methods: |
| 72 | 72 | <programlisting> |
| 73 | 73 | void decide(Authentication authentication, Object secureObject, ConfigAttributeDefinition config) throws AccessDeniedException; |
| ... | ...@@ -75,33 +75,33 @@ | |
| 75 | 75 | boolean supports(Class clazz); |
| 76 | 76 | </programlisting> |
| 77 | 77 | As can be seen from the first method, the |
| 78 | <literal>AccessDecisionManager</literal> is passed via method | |
| 78 | <interfacename>AccessDecisionManager</interfacename> is passed via method | |
| 79 | 79 | parameters all information that is likely to be of value in assessing |
| 80 | 80 | an authorization decision. In particular, passing the secure |
| 81 | 81 | <literal>Object</literal> enables those arguments contained in the |
| 82 | 82 | actual secure object invocation to be inspected. For example, let's |
| 83 | assume the secure object was a <literal>MethodInvocation</literal>. It | |
| 84 | would be easy to query the <literal>MethodInvocation</literal> for any | |
| 83 | assume the secure object was a <classname>MethodInvocation</classname>. It | |
| 84 | would be easy to query the <classname>MethodInvocation</classname> for any | |
| 85 | 85 | <literal>Customer</literal> argument, and then implement some sort of |
| 86 | security logic in the <literal>AccessDecisionManager</literal> to | |
| 86 | security logic in the <interfacename>AccessDecisionManager</interfacename> to | |
| 87 | 87 | ensure the principal is permitted to operate on that customer. |
| 88 | 88 | Implementations are expected to throw an |
| 89 | 89 | <literal>AccessDeniedException</literal> if access is denied.</para> |
| 90 | 90 | |
| 91 | 91 | <para>The <literal>supports(ConfigAttribute)</literal> method is |
| 92 | called by the <literal>AbstractSecurityInterceptor</literal> at | |
| 92 | called by the <classname>AbstractSecurityInterceptor</classname> at | |
| 93 | 93 | startup time to determine if the |
| 94 | <literal>AccessDecisionManager</literal> can process the passed | |
| 94 | <interfacename>AccessDecisionManager</interfacename> can process the passed | |
| 95 | 95 | <literal>ConfigAttribute</literal>. The |
| 96 | 96 | <literal>supports(Class)</literal> method is called by a security |
| 97 | 97 | interceptor implementation to ensure the configured |
| 98 | <literal>AccessDecisionManager</literal> supports the type of secure | |
| 98 | <interfacename>AccessDecisionManager</interfacename> supports the type of secure | |
| 99 | 99 | object that the security interceptor will present.</para> |
| 100 | 100 | |
| 101 | 101 | <section> |
| 102 | 102 | <title>Voting-Based AccessDecisionManager Implementations</title> |
| 103 | <para>Whilst users can implement their own <literal>AccessDecisionManager</literal> to control all aspects of | |
| 104 | authorization, Spring Security includes several <literal>AccessDecisionManager</literal> implementations that are | |
| 103 | <para>Whilst users can implement their own <interfacename>AccessDecisionManager</interfacename> to control all aspects of | |
| 104 | authorization, Spring Security includes several <interfacename>AccessDecisionManager</interfacename> implementations that are | |
| 105 | 105 | based on voting. <xref linkend="authz-access-voting"/> illustrates the relevant classes.</para> |
| 106 | 106 | <figure xml:id="authz-access-voting"> |
| 107 | 107 | <title>Voting Decision Manager</title> |
| ... | ...@@ -115,13 +115,13 @@ | |
| 115 | 115 | </mediaobject> |
| 116 | 116 | </figure> |
| 117 | 117 | <para>Using this approach, a series of |
| 118 | <literal>AccessDecisionVoter</literal> implementations are polled on | |
| 118 | <interfacename>AccessDecisionVoter</interfacename> implementations are polled on | |
| 119 | 119 | an authorization decision. The |
| 120 | <literal>AccessDecisionManager</literal> then decides whether or not | |
| 120 | <interfacename>AccessDecisionManager</interfacename> then decides whether or not | |
| 121 | 121 | to throw an <literal>AccessDeniedException</literal> based on its |
| 122 | 122 | assessment of the votes.</para> |
| 123 | 123 | |
| 124 | <para>The <literal>AccessDecisionVoter</literal> interface has three | |
| 124 | <para>The <interfacename>AccessDecisionVoter</interfacename> interface has three | |
| 125 | 125 | methods: |
| 126 | 126 | <programlisting> |
| 127 | 127 | int vote(Authentication authentication, Object object, ConfigAttributeDefinition config); |
| ... | ...@@ -130,7 +130,7 @@ | |
| 130 | 130 | </programlisting> |
| 131 | 131 | Concrete implementations return an <literal>int</literal>, with |
| 132 | 132 | possible values being reflected in the |
| 133 | <literal>AccessDecisionVoter</literal> static fields | |
| 133 | <interfacename>AccessDecisionVoter</interfacename> static fields | |
| 134 | 134 | <literal>ACCESS_ABSTAIN</literal>, <literal>ACCESS_DENIED</literal> |
| 135 | 135 | and <literal>ACCESS_GRANTED</literal>. A voting implementation will |
| 136 | 136 | return <literal>ACCESS_ABSTAIN</literal> if it has no opinion on an |
| ... | ...@@ -139,7 +139,7 @@ | |
| 139 | 139 | <literal>ACCESS_GRANTED</literal>.</para> |
| 140 | 140 | |
| 141 | 141 | <para>There are three concrete |
| 142 | <literal>AccessDecisionManager</literal>s provided with Spring | |
| 142 | <interfacename>AccessDecisionManager</interfacename>s provided with Spring | |
| 143 | 143 | Security that tally the votes. The <literal>ConsensusBased</literal> |
| 144 | 144 | implementation will grant or deny access based on the consensus of |
| 145 | 145 | non-abstain votes. Properties are provided to control behavior in the |
| ... | ...@@ -157,21 +157,21 @@ | |
| 157 | 157 | abstain.</para> |
| 158 | 158 | |
| 159 | 159 | <para>It is possible to implement a custom |
| 160 | <literal>AccessDecisionManager</literal> that tallies votes | |
| 160 | <interfacename>AccessDecisionManager</interfacename> that tallies votes | |
| 161 | 161 | differently. For example, votes from a particular |
| 162 | <literal>AccessDecisionVoter</literal> might receive additional | |
| 162 | <interfacename>AccessDecisionVoter</interfacename> might receive additional | |
| 163 | 163 | weighting, whilst a deny vote from a particular voter may have a veto |
| 164 | 164 | effect.</para> |
| 165 | 165 | |
| 166 | 166 | <section> |
| 167 | 167 | <title><classname>RoleVoter</classname></title> |
| 168 | 168 | <para> |
| 169 | The most commonly used <literal>AccessDecisionVoter</literal> | |
| 169 | The most commonly used <interfacename>AccessDecisionVoter</interfacename> | |
| 170 | 170 | provided with Spring Security is the simple <classname>RoleVoter</classname>, which treats |
| 171 | 171 | configuration attributes as simple role names and votes to grant access if the user has been assigned |
| 172 | 172 | that role.</para> |
| 173 | 173 | <para>It will vote if any ConfigAttribute begins with the prefix <literal>ROLE_</literal>. |
| 174 | It will vote to grant access if there is a <literal>GrantedAuthority</literal> which returns a | |
| 174 | It will vote to grant access if there is a <interfacename>GrantedAuthority</interfacename> which returns a | |
| 175 | 175 | <literal>String</literal> representation (via the |
| 176 | 176 | <literal>getAuthority()</literal> method) exactly equal to one or more |
| 177 | 177 | <literal>ConfigAttributes</literal> starting with |
| ... | ...@@ -222,7 +222,7 @@ | |
| 222 | 222 | In the above example, you'd define |
| 223 | 223 | <literal>ACL_CONTACT_READ</literal> or |
| 224 | 224 | <literal>ACL_CONTACT_DELETE</literal> against some methods on a |
| 225 | <literal>MethodSecurityInterceptor</literal> or | |
| 225 | <classname>MethodSecurityInterceptor</classname> or | |
| 226 | 226 | <literal>AspectJSecurityInterceptor</literal>. When those methods are |
| 227 | 227 | invoked, the above applicable voter defined above would vote to grant |
| 228 | 228 | or deny access. The voter would look at the method invocation to |
| ... | ...@@ -230,7 +230,7 @@ | |
| 230 | 230 | <literal>sample.contact.Contact</literal>, and then pass that |
| 231 | 231 | <literal>Contact</literal> to the <literal>AclManager</literal>. The |
| 232 | 232 | <literal>AclManager</literal> will then return an access control list |
| 233 | (ACL) that applies to the current <literal>Authentication</literal>. | |
| 233 | (ACL) that applies to the current <interfacename>Authentication</interfacename>. | |
| 234 | 234 | Assuming that ACL contains one of the listed |
| 235 | 235 | <literal>requirePermission</literal>s, the voter will vote to grant |
| 236 | 236 | access. If the ACL does not contain one of the permissions defined |
| ... | ...@@ -252,21 +252,21 @@ | |
| 252 | 252 | <section> |
| 253 | 253 | <title>Custom Voters</title> |
| 254 | 254 | <para>It is also possible to implement a custom |
| 255 | <literal>AccessDecisionVoter</literal>. Several examples are provided | |
| 255 | <interfacename>AccessDecisionVoter</interfacename>. Several examples are provided | |
| 256 | 256 | in Spring Security unit tests, including |
| 257 | 257 | <literal>ContactSecurityVoter</literal> and |
| 258 | 258 | <literal>DenyVoter</literal>. The |
| 259 | 259 | <literal>ContactSecurityVoter</literal> abstains from voting decisions |
| 260 | 260 | where a <literal>CONTACT_OWNED_BY_CURRENT_USER</literal> |
| 261 | 261 | <literal>ConfigAttribute</literal> is not found. If voting, it queries |
| 262 | the <literal>MethodInvocation</literal> to extract the owner of the | |
| 262 | the <classname>MethodInvocation</classname> to extract the owner of the | |
| 263 | 263 | <literal>Contact</literal> object that is subject of the method call. |
| 264 | 264 | It votes to grant access if the <literal>Contact</literal> owner |
| 265 | 265 | matches the principal presented in the |
| 266 | <literal>Authentication</literal> object. It could have just as easily | |
| 266 | <interfacename>Authentication</interfacename> object. It could have just as easily | |
| 267 | 267 | compared the <literal>Contact</literal> owner with some |
| 268 | <literal>GrantedAuthority</literal> the | |
| 269 | <literal>Authentication</literal> object presented. All of this is | |
| 268 | <interfacename>GrantedAuthority</interfacename> the | |
| 269 | <interfacename>Authentication</interfacename> object presented. All of this is | |
| 270 | 270 | achieved with relatively few lines of code and demonstrates the |
| 271 | 271 | flexibility of the authorization model.</para> |
| 272 | 272 | </section> |
| ... | ...@@ -276,8 +276,8 @@ | |
| 276 | 276 | |
| 277 | 277 | <section xml:id="after-invocation"> |
| 278 | 278 | <info><title>After Invocation Handling</title></info> |
| 279 | <para>Whilst the <literal>AccessDecisionManager</literal> is called by | |
| 280 | the <literal>AbstractSecurityInterceptor</literal> before proceeding | |
| 279 | <para>Whilst the <interfacename>AccessDecisionManager</interfacename> is called by | |
| 280 | the <classname>AbstractSecurityInterceptor</classname> before proceeding | |
| 281 | 281 | with the secure object invocation, some applications need a way of |
| 282 | 282 | modifying the object actually returned by the secure object |
| 283 | 283 | invocation. Whilst you could easily implement your own AOP concern to |
| ... | ...@@ -317,21 +317,21 @@ | |
| 317 | 317 | <para>Please be aware that if you're using |
| 318 | 318 | <literal>AfterInvocationManager</literal>, you will still need |
| 319 | 319 | configuration attributes that allow the |
| 320 | <literal>MethodSecurityInterceptor</literal>'s | |
| 321 | <literal>AccessDecisionManager</literal> to allow an operation. If | |
| 320 | <classname>MethodSecurityInterceptor</classname>'s | |
| 321 | <interfacename>AccessDecisionManager</interfacename> to allow an operation. If | |
| 322 | 322 | you're using the typical Spring Security included |
| 323 | <literal>AccessDecisionManager</literal> implementations, having no | |
| 323 | <interfacename>AccessDecisionManager</interfacename> implementations, having no | |
| 324 | 324 | configuration attributes defined for a particular secure method |
| 325 | invocation will cause each <literal>AccessDecisionVoter</literal> to | |
| 325 | invocation will cause each <interfacename>AccessDecisionVoter</interfacename> to | |
| 326 | 326 | abstain from voting. In turn, if the |
| 327 | <literal>AccessDecisionManager</literal> property | |
| 327 | <interfacename>AccessDecisionManager</interfacename> property | |
| 328 | 328 | "<literal>allowIfAllAbstainDecisions</literal>" is |
| 329 | 329 | <literal>false</literal>, an <literal>AccessDeniedException</literal> |
| 330 | 330 | will be thrown. You may avoid this potential issue by either (i) |
| 331 | 331 | setting "<literal>allowIfAllAbstainDecisions</literal>" to |
| 332 | 332 | <literal>true</literal> (although this is generally not recommended) |
| 333 | 333 | or (ii) simply ensure that there is at least one configuration |
| 334 | attribute that an <literal>AccessDecisionVoter</literal> will vote to | |
| 334 | attribute that an <interfacename>AccessDecisionVoter</interfacename> will vote to | |
| 335 | 335 | grant access for. This latter (recommended) approach is usually |
| 336 | 336 | achieved through a <literal>ROLE_USER</literal> or |
| 337 | 337 | <literal>ROLE_AUTHENTICATED</literal> configuration attribute</para> |
| ... | ...@@ -357,8 +357,8 @@ | |
| 357 | 357 | |
| 358 | 358 | <para>Quite often, only principals with permission to read the |
| 359 | 359 | <literal>Contact</literal> should be allowed to obtain it. In this |
| 360 | situation the <literal>AccessDecisionManager</literal> approach | |
| 361 | provided by the <literal>AbstractSecurityInterceptor</literal> will | |
| 360 | situation the <interfacename>AccessDecisionManager</interfacename> approach | |
| 361 | provided by the <classname>AbstractSecurityInterceptor</classname> will | |
| 362 | 362 | not suffice. This is because the identity of the |
| 363 | 363 | <literal>Contact</literal> is all that is available before the |
| 364 | 364 | secure object is invoked. The |
| ... | ...@@ -381,10 +381,10 @@ | |
| 381 | 381 | <literal>AclEntryAfterInvocationProvider</literal>. The provider |
| 382 | 382 | will thrown an <literal>AccessDeniedException</literal> if one of |
| 383 | 383 | the listed <literal>requirePermission</literal>s is not held by the |
| 384 | <literal>Authentication</literal>. The | |
| 384 | <interfacename>Authentication</interfacename>. The | |
| 385 | 385 | <literal>AclEntryAfterInvocationProvider</literal> queries the |
| 386 | 386 | <literal>Acl</literal>Service to determine the ACL that applies for |
| 387 | this domain object to this <literal>Authentication</literal>.</para> | |
| 387 | this domain object to this <interfacename>Authentication</interfacename>.</para> | |
| 388 | 388 | |
| 389 | 389 | <para>Similar to the |
| 390 | 390 | <literal>AclEntryAfterInvocationProvider</literal> is |
| ... | ...@@ -410,7 +410,7 @@ | |
| 410 | 410 | must be a <literal>Collection</literal> or array for this provider |
| 411 | 411 | to operate. It will remove any element if the |
| 412 | 412 | <literal>AclManager</literal> indicates the |
| 413 | <literal>Authentication</literal> does not hold one of the listed | |
| 413 | <interfacename>Authentication</interfacename> does not hold one of the listed | |
| 414 | 414 | <literal>requirePermission</literal>s.</para> |
| 415 | 415 | |
| 416 | 416 | <para>The Contacts sample application demonstrates these two |
| ... | ...@@ -437,8 +437,8 @@ | |
| 437 | 437 | |
| 438 | 438 | <para>Quite often, only principals with permission to read the |
| 439 | 439 | <literal>Contact</literal> should be allowed to obtain it. In this |
| 440 | situation the <literal>AccessDecisionManager</literal> approach | |
| 441 | provided by the <literal>AbstractSecurityInterceptor</literal> will | |
| 440 | situation the <interfacename>AccessDecisionManager</interfacename> approach | |
| 441 | provided by the <classname>AbstractSecurityInterceptor</classname> will | |
| 442 | 442 | not suffice. This is because the identity of the |
| 443 | 443 | <literal>Contact</literal> is all that is available before the |
| 444 | 444 | secure object is invoked. The |
| ... | ...@@ -463,10 +463,10 @@ | |
| 463 | 463 | <literal>BasicAclEntryAfterInvocationProvider</literal>. The |
| 464 | 464 | provider will thrown an <literal>AccessDeniedException</literal> if |
| 465 | 465 | one of the listed <literal>requirePermission</literal>s is not held |
| 466 | by the <literal>Authentication</literal>. The | |
| 466 | by the <interfacename>Authentication</interfacename>. The | |
| 467 | 467 | <literal>BasicAclEntryAfterInvocationProvider</literal> queries the |
| 468 | 468 | <literal>AclManager</literal> to determine the ACL that applies for |
| 469 | this domain object to this <literal>Authentication</literal>.</para> | |
| 469 | this domain object to this <interfacename>Authentication</interfacename>.</para> | |
| 470 | 470 | |
| 471 | 471 | <para>Similar to the |
| 472 | 472 | <literal>BasicAclEntryAfterInvocationProvider</literal> is |
| ... | ...@@ -492,7 +492,7 @@ | |
| 492 | 492 | must be a <literal>Collection</literal> or array for this provider |
| 493 | 493 | to operate. It will remove any element if the |
| 494 | 494 | <literal>AclManager</literal> indicates the |
| 495 | <literal>Authentication</literal> does not hold one of the listed | |
| 495 | <interfacename>Authentication</interfacename> does not hold one of the listed | |
| 496 | 496 | <literal>requirePermission</literal>s.</para> |
| 497 | 497 | |
| 498 | 498 | <para>The Contacts sample application demonstrates these two |
| ... | ...@@ -505,7 +505,7 @@ | |
| 505 | 505 | |
| 506 | 506 | <para><literal>AuthorizeTag</literal> is used to include content if |
| 507 | 507 | the current principal holds certain |
| 508 | <literal>GrantedAuthority</literal>s.</para> | |
| 508 | <interfacename>GrantedAuthority</interfacename>s.</para> | |
| 509 | 509 | |
| 510 | 510 | <para>The following JSP fragment illustrates how to use the |
| 511 | 511 | <literal>AuthorizeTag</literal>:</para> |
| ... | ...@@ -15,8 +15,8 @@ | |
| 15 | 15 | <literal>org.springframework.security.acls</literal> package.</para> |
| 16 | 16 | <para>Complex applications often will find the need to define access permissions not simply |
| 17 | 17 | at a web request or method invocation level. Instead, security decisions need to |
| 18 | comprise both who (<literal>Authentication</literal>), where | |
| 19 | (<literal>MethodInvocation</literal>) and what (<literal>SomeDomainObject</literal>). In | |
| 18 | comprise both who (<interfacename>Authentication</interfacename>), where | |
| 19 | (<classname>MethodInvocation</classname>) and what (<literal>SomeDomainObject</literal>). In | |
| 20 | 20 | other words, authorization decisions also need to consider the actual domain object |
| 21 | 21 | instance subject of a method invocation.</para> |
| 22 | 22 | <para>Imagine you're designing an application for a pet clinic. There will be two main |
| ... | ...@@ -32,21 +32,21 @@ | |
| 32 | 32 | collection within the <literal>Customer</literal> domain object instance to |
| 33 | 33 | determine which users have access. By using the |
| 34 | 34 | <literal>SecurityContextHolder.getContext().getAuthentication()</literal>, |
| 35 | you'll be able to access the <literal>Authentication</literal> | |
| 35 | you'll be able to access the <interfacename>Authentication</interfacename> | |
| 36 | 36 | object.</para> |
| 37 | 37 | </listitem> |
| 38 | 38 | <listitem> |
| 39 | <para>Write an <literal>AccessDecisionVoter</literal> to enforce the security | |
| 39 | <para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the security | |
| 40 | 40 | from the <literal>GrantedAuthority[]</literal>s stored in the |
| 41 | <literal>Authentication</literal> object. This would mean your | |
| 42 | <literal>AuthenticationManager</literal> would need to populate the | |
| 43 | <literal>Authentication</literal> with custom | |
| 44 | <literal>GrantedAuthority</literal>[]s representing each of the | |
| 41 | <interfacename>Authentication</interfacename> object. This would mean your | |
| 42 | <interfacename>AuthenticationManager</interfacename> would need to populate the | |
| 43 | <interfacename>Authentication</interfacename> with custom | |
| 44 | <interfacename>GrantedAuthority</interfacename>[]s representing each of the | |
| 45 | 45 | <literal>Customer</literal> domain object instances the principal has |
| 46 | 46 | access to.</para> |
| 47 | 47 | </listitem> |
| 48 | 48 | <listitem> |
| 49 | <para>Write an <literal>AccessDecisionVoter</literal> to enforce the security | |
| 49 | <para>Write an <interfacename>AccessDecisionVoter</interfacename> to enforce the security | |
| 50 | 50 | and open the target <literal>Customer</literal> domain object directly. This |
| 51 | 51 | would mean your voter needs access to a DAO that allows it to retrieve the |
| 52 | 52 | <literal>Customer</literal> object. It would then access the |
| ... | ...@@ -58,16 +58,16 @@ | |
| 58 | 58 | authorization checking to your business code. The main problems with this include the |
| 59 | 59 | enhanced difficulty of unit testing and the fact it would be more difficult to reuse the |
| 60 | 60 | <literal>Customer</literal> authorization logic elsewhere. Obtaining the |
| 61 | <literal>GrantedAuthority[]</literal>s from the <literal>Authentication</literal> | |
| 61 | <literal>GrantedAuthority[]</literal>s from the <interfacename>Authentication</interfacename> | |
| 62 | 62 | object is also fine, but will not scale to large numbers of |
| 63 | 63 | <literal>Customer</literal>s. If a user might be able to access 5,000 |
| 64 | 64 | <literal>Customer</literal>s (unlikely in this case, but imagine if it were a popular |
| 65 | 65 | vet for a large Pony Club!) the amount of memory consumed and time required to construct |
| 66 | the <literal>Authentication</literal> object would be undesirable. The final method, | |
| 66 | the <interfacename>Authentication</interfacename> object would be undesirable. The final method, | |
| 67 | 67 | opening the <literal>Customer</literal> directly from external code, is probably the |
| 68 | 68 | best of the three. It achieves separation of concerns, and doesn't misuse memory or CPU |
| 69 | 69 | cycles, but it is still inefficient in that both the |
| 70 | <literal>AccessDecisionVoter</literal> and the eventual business method itself will | |
| 70 | <interfacename>AccessDecisionVoter</interfacename> and the eventual business method itself will | |
| 71 | 71 | perform a call to the DAO responsible for retrieving the <literal>Customer</literal> |
| 72 | 72 | object. Two accesses per method invocation is clearly undesirable. In addition, with |
| 73 | 73 | every approach listed you'll need to write your own access control list (ACL) |
| ... | ...@@ -119,8 +119,8 @@ | |
| 119 | 119 | system ("SID" stands for "security identity"). The only columns are the ID, |
| 120 | 120 | a textual representation of the SID, and a flag to indicate whether the |
| 121 | 121 | textual representation refers to a prncipal name or a |
| 122 | <literal>GrantedAuthority</literal>. Thus, there is a single row for | |
| 123 | each unique principal or <literal>GrantedAuthority</literal>. When used in | |
| 122 | <interfacename>GrantedAuthority</interfacename>. Thus, there is a single row for | |
| 123 | each unique principal or <interfacename>GrantedAuthority</interfacename>. When used in | |
| 124 | 124 | the context of receiving a permission, a SID is generally called a |
| 125 | 125 | "recipient".</para> |
| 126 | 126 | </listitem> |
| ... | ...@@ -193,7 +193,7 @@ | |
| 193 | 193 | <literal>GrantedAuthority[]</literal>s. A level of indirection is provided |
| 194 | 194 | by the <literal>Sid</literal> interface, which is an abbreviation of "security |
| 195 | 195 | identity". Common classes include <literal>PrincipalSid</literal> (to represent |
| 196 | the principal inside an <literal>Authentication</literal> object) and | |
| 196 | the principal inside an <interfacename>Authentication</interfacename> object) and | |
| 197 | 197 | <literal>GrantedAuthoritySid</literal>. The security identity information is |
| 198 | 198 | stored in the ACL_SID table.</para> |
| 199 | 199 | </listitem> |
| ... | ...@@ -289,7 +289,7 @@ | |
| 289 | 289 | <para>Once you've used the above techniques to store some ACL information in the database, |
| 290 | 290 | the next step is to actually use the ACL information as part of authorization decision |
| 291 | 291 | logic. You have a number of choices here. You could write your own |
| 292 | <literal>AccessDecisionVoter</literal> or <literal>AfterInvocationProvider</literal> | |
| 292 | <interfacename>AccessDecisionVoter</interfacename> or <literal>AfterInvocationProvider</literal> | |
| 293 | 293 | that respectively fires before or after a method invocation. Such classes would use |
| 294 | 294 | <literal>AclService</literal> to retrieve the relevant ACL and then call |
| 295 | 295 | <literal>Acl.isGranted(Permission[] permission, Sid[] sids, boolean |
| ... | ...@@ -86,7 +86,7 @@ | |
| 86 | 86 | are using your own customized versions of classes.</para> |
| 87 | 87 | <para>In this case, you have a choice in how these filters are added to your web application, in that you can use either |
| 88 | 88 | Spring's <literal>DelegatingFilterProxy</literal> or |
| 89 | <literal>FilterChainProxy</literal>. We'll look at both below.</para> | |
| 89 | <classname>FilterChainProxy</classname>. We'll look at both below.</para> | |
| 90 | 90 | |
| 91 | 91 | <para>When using <literal>DelegatingFilterProxy</literal>, you will see |
| 92 | 92 | something like this in the web.xml file: |
| ... | ...@@ -135,14 +135,14 @@ | |
| 135 | 135 | for more information</para> |
| 136 | 136 | |
| 137 | 137 | <para>Rather than using <literal>DelegatingFilterProxy</literal>, we |
| 138 | strongly recommend that you use <literal>FilterChainProxy</literal> instead. | |
| 138 | strongly recommend that you use <classname>FilterChainProxy</classname> instead. | |
| 139 | 139 | Whilst <literal>DelegatingFilterProxy</literal> is a very useful class, |
| 140 | 140 | the problem is that the number of lines of code required for |
| 141 | 141 | <literal><filter></literal> and |
| 142 | 142 | <literal><filter-mapping></literal> entries in |
| 143 | 143 | <literal>web.xml</literal> explodes when using more than a few |
| 144 | 144 | filters. To overcome this issue, Spring Security provides a |
| 145 | <literal>FilterChainProxy</literal> class. It is wired using a | |
| 145 | <classname>FilterChainProxy</classname> class. It is wired using a | |
| 146 | 146 | <literal>DelegatingFilterProxy</literal> (just like in the example above), |
| 147 | 147 | but the target class is |
| 148 | 148 | <literal>org.springframework.security.util.FilterChainProxy</literal>. |
| ... | ...@@ -162,9 +162,9 @@ | |
| 162 | 162 | </programlisting></para> |
| 163 | 163 | |
| 164 | 164 | <para>You may notice similarities with the way |
| 165 | <literal>FilterSecurityInterceptor</literal> is declared. Both regular | |
| 165 | <classname>FilterSecurityInterceptor</classname> is declared. Both regular | |
| 166 | 166 | expressions and Ant Paths are supported, and the most specific URIs |
| 167 | appear first. At runtime the <literal>FilterChainProxy</literal> will | |
| 167 | appear first. At runtime the <classname>FilterChainProxy</classname> will | |
| 168 | 168 | locate the first URI pattern that matches the current web request and the list |
| 169 | 169 | of filter beans specified by the <literal>filters</literal> attribute |
| 170 | 170 | will be applied to that request. The filters will be invoked in the order |
| ... | ...@@ -172,28 +172,28 @@ | |
| 172 | 172 | which is applied to a particular URL.</para> |
| 173 | 173 | |
| 174 | 174 | <para>You may have noticed we have declared two |
| 175 | <literal>HttpSessionContextIntegrationFilter</literal>s in the filter | |
| 175 | <classname>HttpSessionContextIntegrationFilter</classname>s in the filter | |
| 176 | 176 | chain (<literal>ASC</literal> is short for |
| 177 | 177 | <literal>allowSessionCreation</literal>, a property of |
| 178 | <literal>HttpSessionContextIntegrationFilter</literal>). As web | |
| 178 | <classname>HttpSessionContextIntegrationFilter</classname>). As web | |
| 179 | 179 | services will never present a <literal>jsessionid</literal> on future |
| 180 | 180 | requests, creating <literal>HttpSession</literal>s for such user |
| 181 | 181 | agents would be wasteful. If you had a high-volume application which |
| 182 | 182 | required maximum scalability, we recommend you use the approach shown |
| 183 | 183 | above. For smaller applications, using a single |
| 184 | <literal>HttpSessionContextIntegrationFilter</literal> (with its | |
| 184 | <classname>HttpSessionContextIntegrationFilter</classname> (with its | |
| 185 | 185 | default <literal>allowSessionCreation</literal> as |
| 186 | 186 | <literal>true</literal>) would likely be sufficient.</para> |
| 187 | 187 | |
| 188 | 188 | <para>In relation to lifecycle issues, the |
| 189 | <literal>FilterChainProxy</literal> will always delegate | |
| 189 | <classname>FilterChainProxy</classname> will always delegate | |
| 190 | 190 | <literal>init(FilterConfig)</literal> and <literal>destroy()</literal> |
| 191 | 191 | methods through to the underlaying <literal>Filter</literal>s if such |
| 192 | methods are called against <literal>FilterChainProxy</literal> itself. | |
| 193 | In this case, <literal>FilterChainProxy</literal> guarantees to only | |
| 192 | methods are called against <classname>FilterChainProxy</classname> itself. | |
| 193 | In this case, <classname>FilterChainProxy</classname> guarantees to only | |
| 194 | 194 | initialize and destroy each <literal>Filter</literal> once, |
| 195 | 195 | irrespective of how many times it is declared by the |
| 196 | <literal>FilterInvocationDefinitionSource</literal>. You control the | |
| 196 | <interfacename>FilterInvocationDefinitionSource</interfacename>. You control the | |
| 197 | 197 | overall choice as to whether these methods are called or not via the |
| 198 | 198 | <literal>targetFilterLifecycle</literal> initialization parameter of the |
| 199 | 199 | <literal>DelegatingFilterProxy</literal> that proxies |
| ... | ...@@ -222,17 +222,17 @@ | |
| 222 | 222 | |
| 223 | 223 | <listitem> |
| 224 | 224 | <para><literal>ConcurrentSessionFilter</literal>, because it |
| 225 | doesn't use any <literal>SecurityContextHolder</literal> | |
| 225 | doesn't use any <classname>SecurityContextHolder</classname> | |
| 226 | 226 | functionality but needs to update the |
| 227 | <literal>SessionRegistry</literal> to reflect ongoing requests | |
| 227 | <interfacename>SessionRegistry</interfacename> to reflect ongoing requests | |
| 228 | 228 | from the principal</para> |
| 229 | 229 | </listitem> |
| 230 | 230 | |
| 231 | 231 | <listitem> |
| 232 | <para><literal>HttpSessionContextIntegrationFilter</literal>, so a | |
| 233 | <literal>SecurityContext</literal> can be setup in the | |
| 234 | <literal>SecurityContextHolder</literal> at the beginning of a web | |
| 235 | request, and any changes to the <literal>SecurityContext</literal> | |
| 232 | <para><classname>HttpSessionContextIntegrationFilter</classname>, so a | |
| 233 | <interfacename>SecurityContext</interfacename> can be setup in the | |
| 234 | <classname>SecurityContextHolder</classname> at the beginning of a web | |
| 235 | request, and any changes to the <interfacename>SecurityContext</interfacename> | |
| 236 | 236 | can be copied to the <literal>HttpSession</literal> when the web |
| 237 | 237 | request ends (ready for use with the next web request)</para> |
| 238 | 238 | </listitem> |
| ... | ...@@ -243,8 +243,8 @@ | |
| 243 | 243 | <literal>CasProcessingFilter</literal>, |
| 244 | 244 | <literal>BasicProcessingFilter, HttpRequestIntegrationFilter, |
| 245 | 245 | JbossIntegrationFilter</literal> etc - so that the |
| 246 | <literal>SecurityContextHolder</literal> can be modified to | |
| 247 | contain a valid <literal>Authentication</literal> request | |
| 246 | <classname>SecurityContextHolder</classname> can be modified to | |
| 247 | contain a valid <interfacename>Authentication</interfacename> request | |
| 248 | 248 | token</para> |
| 249 | 249 | </listitem> |
| 250 | 250 | |
| ... | ...@@ -257,46 +257,46 @@ | |
| 257 | 257 | </listitem> |
| 258 | 258 | |
| 259 | 259 | <listitem> |
| 260 | <para><literal>RememberMeProcessingFilter</literal>, so that if no | |
| 260 | <para><classname>RememberMeProcessingFilter</classname>, so that if no | |
| 261 | 261 | earlier authentication processing mechanism updated the |
| 262 | <literal>SecurityContextHolder</literal>, and the request presents | |
| 262 | <classname>SecurityContextHolder</classname>, and the request presents | |
| 263 | 263 | a cookie that enables remember-me services to take place, a |
| 264 | 264 | suitable remembered |
| 265 | <literal>Authentication</literal> object will | |
| 265 | <interfacename>Authentication</interfacename> object will | |
| 266 | 266 | be put there</para> |
| 267 | 267 | </listitem> |
| 268 | 268 | |
| 269 | 269 | <listitem> |
| 270 | 270 | <para><literal>AnonymousProcessingFilter</literal>, so that if no |
| 271 | 271 | earlier authentication processing mechanism updated the |
| 272 | <literal>SecurityContextHolder</literal>, an anonymous | |
| 273 | <literal>Authentication</literal> object will be put there</para> | |
| 272 | <classname>SecurityContextHolder</classname>, an anonymous | |
| 273 | <interfacename>Authentication</interfacename> object will be put there</para> | |
| 274 | 274 | </listitem> |
| 275 | 275 | |
| 276 | 276 | <listitem> |
| 277 | <para><literal>ExceptionTranslationFilter</literal>, to catch any | |
| 277 | <para><classname>ExceptionTranslationFilter</classname>, to catch any | |
| 278 | 278 | Spring Security exceptions so that either an HTTP error response |
| 279 | 279 | can be returned or an appropriate |
| 280 | <literal>AuthenticationEntryPoint</literal> can be launched</para> | |
| 280 | <interfacename>AuthenticationEntryPoint</interfacename> can be launched</para> | |
| 281 | 281 | </listitem> |
| 282 | 282 | |
| 283 | 283 | <listitem> |
| 284 | <para><literal>FilterSecurityInterceptor</literal>, to protect web | |
| 284 | <para><classname>FilterSecurityInterceptor</classname>, to protect web | |
| 285 | 285 | URIs</para> |
| 286 | 286 | </listitem> |
| 287 | 287 | </orderedlist> |
| 288 | 288 | |
| 289 | 289 | <para>All of the above filters use |
| 290 | 290 | <literal>DelegatingFilterProxy</literal> or |
| 291 | <literal>FilterChainProxy</literal>. It is recommended that a single | |
| 291 | <classname>FilterChainProxy</classname>. It is recommended that a single | |
| 292 | 292 | <literal>DelegatingFilterProxy</literal> proxy through to a single |
| 293 | <literal>FilterChainProxy</literal> for each application, with that | |
| 294 | <literal>FilterChainProxy</literal> defining all of Spring Security | |
| 293 | <classname>FilterChainProxy</classname> for each application, with that | |
| 294 | <classname>FilterChainProxy</classname> defining all of Spring Security | |
| 295 | 295 | filters.</para> |
| 296 | 296 | |
| 297 | 297 | <para>If you're using SiteMesh, ensure Spring Security filters execute |
| 298 | 298 | before the SiteMesh filters are called. This enables the |
| 299 | <literal>SecurityContextHolder</literal> to be populated in time for | |
| 299 | <classname>SecurityContextHolder</classname> to be populated in time for | |
| 300 | 300 | use by SiteMesh decorators</para> |
| 301 | 301 | </section> |
| 302 | 302 |
| ... | ...@@ -6,7 +6,7 @@ | |
| 6 | 6 | <info><title>Overview</title></info> |
| 7 | 7 | |
| 8 | 8 | <para>Spring Security includes a production-quality |
| 9 | <literal>AuthenticationProvider</literal> implementation called | |
| 9 | <classname>AuthenticationProvider</classname> implementation called | |
| 10 | 10 | <literal>DaoAuthenticationProvider</literal>. This authentication |
| 11 | 11 | provider is compatible with all of the authentication mechanisms that |
| 12 | 12 | generate a <literal>UsernamePasswordAuthenticationToken</literal>, and |
| ... | ...@@ -43,8 +43,8 @@ | |
| 43 | 43 | <para>The <literal>PasswordEncoder</literal> and |
| 44 | 44 | <literal>SaltSource</literal> are optional. A |
| 45 | 45 | <literal>PasswordEncoder</literal> provides encoding and decoding of |
| 46 | passwords presented in the <literal>UserDetails</literal> object that | |
| 47 | is returned from the configured <literal>UserDetailsService</literal>. | |
| 46 | passwords presented in the <interfacename>UserDetails</interfacename> object that | |
| 47 | is returned from the configured <interfacename>UserDetailsService</interfacename>. | |
| 48 | 48 | A <literal>SaltSource</literal> enables the passwords to be populated |
| 49 | 49 | with a "salt", which enhances the security of the passwords in the |
| 50 | 50 | authentication repository. <literal>PasswordEncoder</literal> |
| ... | ...@@ -54,15 +54,15 @ |