Просмотр исходного кода

Document spring-security-access

Closes gh-17847
Josh Cummings 2 недель назад
Родитель
Сommit
b87d63cb71

+ 1 - 0
docs/modules/ROOT/nav.adoc

@@ -5,6 +5,7 @@
 * xref:migration-8/index.adoc[Preparing for 8.0]
 * xref:migration/index.adoc[Migrating to 7]
 ** xref:migration/servlet/index.adoc[Servlet]
+*** xref:migration/servlet/authorization.adoc[Authorization]
 *** xref:migration/servlet/oauth2.adoc[OAuth 2.0]
 *** xref:migration/servlet/saml2.adoc[SAML 2.0]
 ** xref:migration/reactive.adoc[Reactive]

+ 29 - 0
docs/modules/ROOT/pages/migration/servlet/authorization.adoc

@@ -0,0 +1,29 @@
+= Authorization Changes
+
+== If Using Access API, Add `spring-security-access`
+
+Spring Security 7 moves `AccessDecisionManager`, `AccessDecisionVoter`, and the related Access API to a legacy module, `spring-security-access`.
+The Access API is deprecated in favor of the Authorization API as of Spring Security 5.
+
+You can add the dependency like other Spring Security dependencies like so:
+
+[tabs]
+======
+Maven::
++
+[source,xml,role="primary"]
+----
+<dependency>
+    <groupId>org.springframework.security</groupId>
+    <artifactId>spring-security-access</artifactId>
+</dependency>
+----
+
+Gradle::
++
+[source,groovy,role="primary"]
+----
+implementation('org.springframework.security:spring-security-access')
+----
+======
+

+ 13 - 12
docs/modules/ROOT/pages/servlet/appendix/faq.adoc

@@ -138,12 +138,13 @@ If you use hashed passwords, make sure the value stored in your database is _exa
 === My application goes into an "`endless loop`" when I try to log in. What is going on?
 
 A common user problem with infinite loop and redirecting to the login page is caused by accidentally configuring the login page as a "`secured`" resource.
-Make sure your configuration allows anonymous access to the login page, either by excluding it from the security filter chain or marking it as requiring `ROLE_ANONYMOUS`.
-
-If your `AccessDecisionManager` includes an `AuthenticatedVoter`, you can use the `IS_AUTHENTICATED_ANONYMOUSLY` attribute. This is automatically available if you use the standard namespace configuration setup.
-
-From Spring Security 2.0.1 onwards, when you use namespace-based configuration, a check is made on loading the application context and a warning message logged if your login page appears to be protected.
+Make sure your configuration allows anonymous access to the login page.
+You can do so with the xref:servlet/authorization/authorize-http-requests.adoc[`authorizeHttpRequests`] DSL.
 
+[TIP]
+====
+When you use namespace- or DSL-based configuration, a check is made on loading the application context and a warning message logged if your login page appears to be protected.
+====
 
 [[appendix-faq-anon-access-denied]]
 === I get an exception with the message "Access is denied (user is anonymous);". What's wrong?
@@ -382,16 +383,16 @@ You should probably read the chapters on namespace parsing in the standard Sprin
 
 
 [[appendix-faq-role-prefix]]
-=== What does "ROLE_" mean and why do I need it on my role names?
+=== What does "ROLE_" mean?
 
-Spring Security has a voter-based architecture, which means that an access decision is made by a series of `AccessDecisionVoter` instances.
-The voters act on the "`configuration attributes`", which are specified for a secured resource (such as a method invocation). With this approach, not all attributes may be relevant to all voters, and a voter needs to know when it should ignore an attribute (abstain) and when it should vote to grant or deny access based on the attribute value.
-The most common voter is the `RoleVoter`, which, by default, votes whenever it finds an attribute with the `ROLE_` prefix.
-It makes a simple comparison of the attribute (such as `ROLE_USER`) with the names of the authorities that the current user has been assigned.
-If it finds a match (they have an authority called `ROLE_USER`), it votes to grant access. Otherwise, it votes to deny access.
+`ROLE_` is a way to identify the nature of a given authority.
+An authority prefixed by `ROLE_` means that this authority is a role, likely derived from an RBAC authorization model.
 
-You can change the prefix by setting the `rolePrefix` property of `RoleVoter`. If you need only to use roles in your application and have no need for other custom voters, you can set the prefix to a blank string. In that case, the `RoleVoter` treats all attributes as roles.
+Having a prefix allows for clear differentiation from OAuth 2.0 scopes (which use `SCOPE_`) and authorities granted from other sources as well.
 
+You may choose to not prefix your authorities.
+Modern Spring Security authorization components either allow you to supply the entire authority name, rendering the prefix unnecessary.
+An example of this is how xref:servlet/authorization/authorize-http-requests.adoc[`authorizeHttpRequests`] and xref:servlet/authorization/method-security.adoc[`@PreAuthorize`] allow you to call `hasAuthority` or `hasRole`.
 
 [[appendix-faq-what-dependencies]]
 === How do I know which dependencies to add to my application to work with Spring Security?

+ 30 - 2
docs/modules/ROOT/pages/servlet/appendix/namespace/method-security.adoc

@@ -56,6 +56,11 @@ Methods can be secured by the use of annotations (defined at the interface or cl
 [[nsa-global-method-security-attributes]]
 === <global-method-security> Attributes
 
+[NOTE]
+=====
+`<global-method-security>` is deprecated in favor of `<method-security>`.
+If you need to use `<global-method-security>`, please include the `spring-security-access` dependency in your build configuration.
+=====
 
 [[nsa-global-method-security-access-decision-manager-ref]]
 * **access-decision-manager-ref**
@@ -145,6 +150,11 @@ You can define zero or more of these within the `global-method-security` element
 [[nsa-after-invocation-provider-attributes]]
 === <after-invocation-provider> Attributes
 
+[NOTE]
+=====
+`<after-invocation-provider>` is deprecated in favor of `<method-security>` and xref:servlet/authorization/method-security.adoc[`@PostFilter` and `@PostAuthorize`].
+If you need to use `<after-invocation-provider>`, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option.
+=====
 
 [[nsa-after-invocation-provider-ref]]
 * **ref**
@@ -179,6 +189,11 @@ Only applies if these annotations are enabled.
 == <invocation-attribute-factory>
 Defines the PrePostInvocationAttributeFactory instance which is used to generate pre and post invocation metadata from the annotated methods.
 
+[NOTE]
+=====
+`<invocation-attribute-factory>` is deprecated in favor of `<method-security>` and xref:servlet/authorization/method-security.adoc[`@PostFilter` and `@PostAuthorize`].
+If you need to use `<invocation-attribute-factory>`, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option.
+=====
 
 [[nsa-invocation-attribute-factory-parents]]
 === Parent Elements of <invocation-attribute-factory>
@@ -201,6 +216,11 @@ Defines a reference to a Spring bean Id.
 == <post-invocation-advice>
 Customizes the `PostInvocationAdviceProvider` with the ref as the `PostInvocationAuthorizationAdvice` for the <pre-post-annotation-handling> element.
 
+[NOTE]
+=====
+`<post-invocation-advice>` is deprecated in favor of `<method-security>` and xref:servlet/authorization/method-security.adoc[`@PostFilter` and `@PostAuthorize`].
+If you need to use `<post-invocation-advice>`, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option.
+=====
 
 [[nsa-post-invocation-advice-parents]]
 === Parent Elements of <post-invocation-advice>
@@ -223,6 +243,11 @@ Defines a reference to a Spring bean Id.
 == <pre-invocation-advice>
 Customizes the `PreInvocationAuthorizationAdviceVoter` with the ref as the `PreInvocationAuthorizationAdviceVoter` for the <pre-post-annotation-handling> element.
 
+[NOTE]
+=====
+`<pre-invocation-advice>` is deprecated in favor of `<method-security>` and xref:servlet/authorization/method-security.adoc[`@PreFilter` and `@PreAuthorize`].
+If you need to use `<pre-invocation-advice>`, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option.
+=====
 
 [[nsa-pre-invocation-advice-parents]]
 === Parent Elements of <pre-invocation-advice>
@@ -247,7 +272,6 @@ Defines a reference to a Spring bean Id.
 Rather than defining security attributes on an individual method or class basis using the `@Secured` annotation, you can define cross-cutting security constraints across whole sets of methods and interfaces in your service layer using the `<protect-pointcut>` element.
 You can find an example in the xref:servlet/authorization/method-security.adoc#ns-protect-pointcut[namespace introduction].
 
-
 [[nsa-protect-pointcut-parents]]
 === Parent Elements of <protect-pointcut>
 
@@ -293,7 +317,6 @@ Optional AuthorizationManager bean ID to be used instead of the default (superse
 * **access-decision-manager-ref**
 Optional AccessDecisionManager bean ID to be used by the created method security interceptor.
 
-
 [[nsa-intercept-methods-children]]
 === Child Elements of <intercept-methods>
 
@@ -306,6 +329,11 @@ Optional AccessDecisionManager bean ID to be used by the created method security
 == <method-security-metadata-source>
 Creates a MethodSecurityMetadataSource instance
 
+[NOTE]
+=====
+`<method-security-metadata-source>` is deprecated in favor of xref:servlet/authorization/method-security.adoc[`<method-security>`].
+If you need to use `<method-security-metadata-source>`, please include the `spring-security-access` dependency in your build configuration while planning to migrate to a modern option.
+=====
 
 [[nsa-method-security-metadata-source-attributes]]
 === <method-security-metadata-source> Attributes

+ 8 - 3
docs/modules/ROOT/pages/servlet/authorization/acls.adoc

@@ -17,9 +17,9 @@ When you use Spring Security as the foundation, you have several possible approa
 * Write your business methods to enforce the security.
 You could consult a collection within the `Customer` domain object instance to determine which users have access.
 By using `SecurityContextHolder.getContext().getAuthentication()`, you can access the `Authentication` object.
-* Write an `AccessDecisionVoter` to enforce the security from the `GrantedAuthority[]` instances stored in the `Authentication` object.
+* Write an `AuthorizationManager` to enforce the security from the `GrantedAuthority[]` instances stored in the `Authentication` object.
 This means that your `AuthenticationManager` needs to populate the `Authentication` with custom `GrantedAuthority[]` objects to represent each of the `Customer` domain object instances to which the principal has access.
-* Write an `AccessDecisionVoter` to enforce the security and open the target `Customer` domain object directly.
+* Write an `AuthorizationManager` to enforce the security and open the target `Customer` domain object directly.
 This would mean your voter needs access to a DAO that lets it retrieve the `Customer` object.
 It can then access the `Customer` object's collection of approved users and make the appropriate decision.
 
@@ -29,7 +29,7 @@ The main problems with this include the enhanced difficulty of unit testing and
 Obtaining the `GrantedAuthority[]` instances from the `Authentication` object is also fine but will not scale to large numbers of `Customer` objects.
 If a user can access 5,000 `Customer` objects (unlikely in this case, but imagine if it were a popular vet for a large Pony Club!) the amount of memory consumed and the time required to construct the `Authentication` object would be undesirable.
 The final method, opening the `Customer` directly from external code, is probably the best of the three.
-It achieves separation of concerns and does not misuse memory or CPU cycles, but it is still inefficient in that both the `AccessDecisionVoter` and the eventual business method itself perform a call to the DAO responsible for retrieving the `Customer` object.
+It achieves separation of concerns and does not misuse memory or CPU cycles, but it is still inefficient in that both the `AuthorizationManager` and the eventual business method itself perform a call to the DAO responsible for retrieving the `Customer` object.
 Two accesses per method invocation is clearly undesirable.
 In addition, with every approach listed, you need to write your own access control list (ACL) persistence and business logic from scratch.
 
@@ -40,6 +40,11 @@ Fortunately, there is another alternative, which we discuss later.
 Spring Security's ACL services are shipped in the `spring-security-acl-xxx.jar`.
 You need to add this JAR to your classpath to use Spring Security's domain object instance security capabilities.
 
+[NOTE]
+====
+If you need access to the legacy Access API that includes `AclEntryVoter`, please also include `spring-security-access-xxx.jar`.
+====
+
 Spring Security's domain object instance security capabilities center on the concept of an access control list (ACL).
 Every domain object instance in your system has its own ACL, and the ACL records details of who can and cannot work with that domain object.
 With this in mind, Spring Security provides three main ACL-related capabilities to your application:

+ 23 - 1
docs/modules/ROOT/pages/servlet/authorization/architecture.adoc

@@ -10,7 +10,7 @@ This section describes the Spring Security architecture that applies to authoriz
 == Authorities
 xref:servlet/authentication/architecture.adoc#servlet-authentication-authentication[`Authentication`] discusses how all `Authentication` implementations store a list of `GrantedAuthority` objects.
 These represent the authorities that have been granted to the principal.
-The `GrantedAuthority` objects are inserted into the `Authentication` object by the `AuthenticationManager` and are later read by `AccessDecisionManager` instances when making authorization decisions.
+The `GrantedAuthority` objects are inserted into the `Authentication` object by the `AuthenticationManager` and are later read by `AuthorizationManager` instances when making authorization decisions.
 
 The `GrantedAuthority` interface has only one method:
 
@@ -347,6 +347,28 @@ Spring Security contains some legacy components.
 Since they are not yet removed, documentation is included for historical purposes.
 Their recommended replacements are above.
 
+When accessing legacy authorization components, please also include the `spring-security-access` dependency like so:
+
+[tabs]
+======
+Maven::
++
+[source,xml,role="primary"]
+----
+<dependency>
+    <groupId>org.springframework.security</groupId>
+    <artifactId>spring-security-access</artifactId>
+</dependency>
+----
+
+Gradle::
++
+[source,groovy,role="primary"]
+----
+implementation('org.springframework.security:spring-security-access')
+----
+======
+
 [[authz-access-decision-manager]]
 === The AccessDecisionManager
 The `AccessDecisionManager` is called by the `AbstractSecurityInterceptor` and is responsible for making final access control decisions.

+ 7 - 0
docs/modules/ROOT/pages/servlet/authorization/index.adoc

@@ -11,4 +11,11 @@ You should consider attaching authorization rules to xref:servlet/authorization/
 In either case, you can listen and react to xref:servlet/authorization/events.adoc[authorization events] that each authorization check publishes.
 Below there is also wealth of detail about xref:servlet/authorization/architecture.adoc[how Spring Security authorization works] and how, having established a basic model, it can be fine-tuned.
 
+[NOTE]
+====
+As of Spring Security 7, the Access API (`AccessDecisionManager`, `AccessDecisionVoter`, etc.) are moved to a legacy module, `spring-security-access`.
+For new applications, there is no need to include the dependency.
+For older applications that have not yet migrated to the Authorization API, this module is available to assist your continued migration efforts.
+====
+
 

+ 22 - 0
docs/modules/ROOT/pages/servlet/authorization/method-security.adoc

@@ -3089,6 +3089,28 @@ Make sure to read the <<meta-annotations,Meta Annotations Support>> section for
 
 If you are using `@EnableGlobalMethodSecurity`, you should migrate to `@EnableMethodSecurity`.
 
+If you cannot migrate at this time, please include the `spring-security-access` module as a dependency like so:
+
+[tabs]
+======
+Maven::
++
+[source,xml,role="primary"]
+----
+<dependency>
+    <groupId>org.springframework.security</groupId>
+    <artifactId>spring-security-access</artifactId>
+</dependency>
+----
+
+Gradle::
++
+[source,groovy,role="primary"]
+----
+implementation('org.springframework.security:spring-security-access')
+----
+======
+
 [[servlet-replace-globalmethodsecurity-with-methodsecurity]]
 === Replace xref:servlet/authorization/method-security.adoc#jc-enable-global-method-security[global method security] with xref:servlet/authorization/method-security.adoc#jc-enable-method-security[method security]
 

+ 1 - 0
docs/modules/ROOT/pages/whats-new.adoc

@@ -14,6 +14,7 @@ Each section that follows will indicate the more notable removals as well as the
 * Removed `AuthorizationManager#check` in favor of `AuthorizationManager#authorize`
 * Added xref:servlet/authorization/architecture.adoc#authz-authorization-manager-factory[`AuthorizationManagerFactory`] for creating `AuthorizationManager` instances in xref:servlet/authorization/authorize-http-requests.adoc#customizing-authorization-managers[request-based] and xref:servlet/authorization/method-security.adoc#customizing-authorization-managers[method-based] authorization components
 * Added `Authentication.Builder` for mutating and merging `Authentication` instances
+* Moved Access API (`AccessDecisionManager`, `AccessDecisionVoter`, etc.) to a new module, `spring-security-access`
 
 == Config