mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-25 13:32:30 +00:00
Extract FilterSecurityInterceptor Docs
Closes gh-8001
This commit is contained in:
parent
b8d4f33004
commit
32ee30e8a1
@ -3,72 +3,6 @@
|
||||
There are some key filters which will always be used in a web application which uses Spring Security, so we'll look at these and their supporting classes and interfaces first.
|
||||
We won't cover every feature, so be sure to look at the Javadoc for them if you want to get the complete picture.
|
||||
|
||||
[[filter-security-interceptor]]
|
||||
=== FilterSecurityInterceptor
|
||||
We've already seen `FilterSecurityInterceptor` briefly when discussing <<tech-intro-access-control,access-control in general>>, and we've already used it with the namespace where the `<intercept-url>` elements are combined to configure it internally.
|
||||
Now we'll see how to explicitly configure it for use with a `FilterChainProxy`, along with its companion filter `ExceptionTranslationFilter`.
|
||||
A typical configuration example is shown below:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<bean id="filterSecurityInterceptor"
|
||||
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-security-metadata-source>
|
||||
<security:intercept-url pattern="/secure/super/**" access="ROLE_WE_DONT_HAVE"/>
|
||||
<security:intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
`FilterSecurityInterceptor` is responsible for handling the security of HTTP resources.
|
||||
It requires a reference to an `AuthenticationManager` and an `AccessDecisionManager`.
|
||||
It is also supplied with configuration attributes that apply to different HTTP URL requests.
|
||||
Refer back to <<tech-intro-config-attributes,the original discussion on these>> in the technical introduction.
|
||||
|
||||
The `FilterSecurityInterceptor` can be configured with configuration attributes in two ways.
|
||||
The first, which is shown above, is using the `<filter-security-metadata-source>` namespace element.
|
||||
This is similar to the `<http>` element from the namespace chapter but the `<intercept-url>` child elements only use the `pattern` and `access` attributes.
|
||||
Commas are used to delimit the different configuration attributes that apply to each HTTP URL.
|
||||
The second option is to write your own `SecurityMetadataSource`, but this is beyond the scope of this document.
|
||||
Irrespective of the approach used, the `SecurityMetadataSource` is responsible for returning a `List<ConfigAttribute>` containing all of the configuration attributes associated with a single secure HTTP URL.
|
||||
|
||||
It should be noted that the `FilterSecurityInterceptor.setSecurityMetadataSource()` method actually expects an instance of `FilterInvocationSecurityMetadataSource`.
|
||||
This is a marker interface which subclasses `SecurityMetadataSource`.
|
||||
It simply denotes the `SecurityMetadataSource` understands `FilterInvocation` s.
|
||||
In the interests of simplicity we'll continue to refer to the `FilterInvocationSecurityMetadataSource` as a `SecurityMetadataSource`, as the distinction is of little relevance to most users.
|
||||
|
||||
The `SecurityMetadataSource` created by the namespace syntax obtains the configuration attributes for a particular `FilterInvocation` by matching the request URL against the configured `pattern` attributes.
|
||||
This behaves in the same way as it does for namespace configuration.
|
||||
The default is to treat all expressions as Apache Ant paths and regular expressions are also supported for more complex cases.
|
||||
The `request-matcher` attribute is used to specify the type of pattern being used.
|
||||
It is not possible to mix expression syntaxes within the same definition.
|
||||
As an example, the previous configuration using regular expressions instead of Ant paths would be written as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<bean id="filterInvocationInterceptor"
|
||||
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="runAsManager" ref="runAsManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-security-metadata-source request-matcher="regex">
|
||||
<security:intercept-url pattern="\A/secure/super/.*\Z" access="ROLE_WE_DONT_HAVE"/>
|
||||
<security:intercept-url pattern="\A/secure/.*\" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
|
||||
Patterns are always evaluated in the order they are defined.
|
||||
Thus it is important that more specific patterns are defined higher in the list than less specific patterns.
|
||||
This is reflected in our example above, where the more specific `/secure/super/` pattern appears higher than the less specific `/secure/` pattern.
|
||||
If they were reversed, the `/secure/` pattern would always match and the `/secure/super/` pattern would never be evaluated.
|
||||
|
||||
[[exception-translation-filter]]
|
||||
=== ExceptionTranslationFilter
|
||||
The `ExceptionTranslationFilter` sits above the `FilterSecurityInterceptor` in the security filter stack.
|
||||
|
@ -162,7 +162,7 @@ Below is a comprehensive list of Spring Security Filter ordering:
|
||||
* OAuth2AuthorizationCodeGrantFilter
|
||||
* SessionManagementFilter
|
||||
* ExceptionTranslationFilter
|
||||
* FilterSecurityInterceptor
|
||||
* <<servlet-authorization-filtersecurityinterceptor,`FilterSecurityInterceptor`>>
|
||||
* SwitchUserFilter
|
||||
|
||||
include::technical-overview.adoc[]
|
||||
|
@ -1,10 +1,11 @@
|
||||
// from the original documentation
|
||||
|
||||
[[authz-arch]]
|
||||
== Authorization Architecture
|
||||
= Authorization Architecture
|
||||
|
||||
|
||||
[[authz-authorities]]
|
||||
=== Authorities
|
||||
== Authorities
|
||||
As we saw in the <<tech-granted-authority,technical overview>>, 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` s when making authorization decisions.
|
||||
@ -19,7 +20,7 @@ String getAuthority();
|
||||
----
|
||||
|
||||
This method allows
|
||||
`AccessDecisionManager` s to obtain a precise `String` representation of the `GrantedAuthority`.
|
||||
`AccessDecisionManager` s to obtain a precise `String` representation of the `GrantedAuthority`.
|
||||
By returning a representation as a `String`, a `GrantedAuthority` can be easily "read" by most `AccessDecisionManager` s.
|
||||
If a `GrantedAuthority` cannot be precisely represented as a `String`, the `GrantedAuthority` is considered "complex" and `getAuthority()` must return `null`.
|
||||
|
||||
@ -33,13 +34,13 @@ All `AuthenticationProvider` s included with the security architecture use `Simp
|
||||
|
||||
|
||||
[[authz-pre-invocation]]
|
||||
=== Pre-Invocation Handling
|
||||
== Pre-Invocation Handling
|
||||
As we've also seen in the <<secure-objects,Technical Overview>> chapter, Spring Security provides interceptors which control access to secure objects such as method invocations or web requests.
|
||||
A pre-invocation decision on whether the invocation is allowed to proceed is made by the `AccessDecisionManager`.
|
||||
|
||||
|
||||
[[authz-access-decision-manager]]
|
||||
==== The AccessDecisionManager
|
||||
=== The AccessDecisionManager
|
||||
The `AccessDecisionManager` is called by the `AbstractSecurityInterceptor` and is responsible for making final access control decisions.
|
||||
the `AccessDecisionManager` interface contains three methods:
|
||||
|
||||
@ -63,7 +64,7 @@ The `supports(ConfigAttribute)` method is called by the `AbstractSecurityInterce
|
||||
The `supports(Class)` method is called by a security interceptor implementation to ensure the configured `AccessDecisionManager` supports the type of secure object that the security interceptor will present.
|
||||
|
||||
[[authz-voting-based]]
|
||||
==== Voting-Based AccessDecisionManager Implementations
|
||||
=== Voting-Based AccessDecisionManager Implementations
|
||||
Whilst users can implement their own `AccessDecisionManager` to control all aspects of authorization, Spring Security includes several `AccessDecisionManager` implementations that are based on voting.
|
||||
<<authz-access-voting>> illustrates the relevant classes.
|
||||
|
||||
@ -105,7 +106,7 @@ For example, votes from a particular `AccessDecisionVoter` might receive additio
|
||||
|
||||
|
||||
[[authz-role-voter]]
|
||||
===== RoleVoter
|
||||
==== RoleVoter
|
||||
The most commonly used `AccessDecisionVoter` provided with Spring Security is the simple `RoleVoter`, which treats configuration attributes as simple role names and votes to grant access if the user has been assigned that role.
|
||||
|
||||
It will vote if any `ConfigAttribute` begins with the prefix `ROLE_`.
|
||||
@ -115,7 +116,7 @@ If no `ConfigAttribute` begins with `ROLE_`, the voter will abstain.
|
||||
|
||||
|
||||
[[authz-authenticated-voter]]
|
||||
===== AuthenticatedVoter
|
||||
==== AuthenticatedVoter
|
||||
Another voter which we've implicitly seen is the `AuthenticatedVoter`, which can be used to differentiate between anonymous, fully-authenticated and remember-me authenticated users.
|
||||
Many sites allow certain limited access under remember-me authentication, but require a user to confirm their identity by logging in for full access.
|
||||
|
||||
@ -124,14 +125,14 @@ See the Javadoc for this class for more information.
|
||||
|
||||
|
||||
[[authz-custom-voter]]
|
||||
===== Custom Voters
|
||||
==== Custom Voters
|
||||
Obviously, you can also implement a custom `AccessDecisionVoter` and you can put just about any access-control logic you want in it.
|
||||
It might be specific to your application (business-logic related) or it might implement some security administration logic.
|
||||
For example, you'll find a https://spring.io/blog/2009/01/03/spring-security-customization-part-2-adjusting-secured-session-in-real-time[blog article] on the Spring web site which describes how to use a voter to deny access in real-time to users whose accounts have been suspended.
|
||||
|
||||
|
||||
[[authz-after-invocation-handling]]
|
||||
=== After Invocation Handling
|
||||
== After Invocation Handling
|
||||
Whilst the `AccessDecisionManager` is called by the `AbstractSecurityInterceptor` before proceeding with the secure object invocation, some applications need a way of modifying the object actually returned by the secure object invocation.
|
||||
Whilst you could easily implement your own AOP concern to achieve this, Spring Security provides a convenient hook that has several concrete implementations that integrate with its ACL capabilities.
|
||||
|
||||
@ -153,7 +154,7 @@ This latter (recommended) approach is usually achieved through a `ROLE_USER` or
|
||||
|
||||
|
||||
[[authz-hierarchical-roles]]
|
||||
=== Hierarchical Roles
|
||||
== Hierarchical Roles
|
||||
It is a common requirement that a particular role in an application should automatically "include" other roles.
|
||||
For example, in an application which has the concept of an "admin" and a "user" role, you may want an admin to be able to do everything a normal user can.
|
||||
To achieve this, you can either make sure that all admin users are also assigned the "user" role.
|
||||
|
@ -1,29 +1,96 @@
|
||||
[[jc-authorize-requests]]
|
||||
== Authorize Requests
|
||||
Our examples have only required users to be authenticated and have done so for every URL in our application.
|
||||
We can specify custom requirements for our URLs by adding multiple children to our `http.authorizeRequests()` method.
|
||||
For example:
|
||||
[[servlet-authorization-filtersecurityinterceptor]]
|
||||
= Authorize HttpServletRequest with FilterSecurityInterceptor
|
||||
:figures: images/servlet/authorization
|
||||
:icondir: images/icons
|
||||
|
||||
This section builds on <<servlet-architecture,Servlet Architecture and Implementation>> by digging deeper into how <<authorization>> works within Servlet based applications.
|
||||
|
||||
[source,java]
|
||||
The {security-api-url}org/springframework/security/web/access/intercept/FilterSecurityInterceptor.html[`FilterSecurityInterceptor`] provides <<authorization>> for ``HttpServletRequest``s.
|
||||
It is inserted into the <<servlet-filterchainproxy>> as one of the <<servlet-security-filters>>.
|
||||
|
||||
.Authorize HttpServletRequest
|
||||
image::{figures}/filtersecurityinterceptor.png[]
|
||||
|
||||
* image:{icondir}/number_1.png[] First, the `FilterSecurityInterceptor` obtains an <<servlet-authentication-authentication>> from the <<servlet-authentication-securitycontextholder>>.
|
||||
* image:{icondir}/number_2.png[] Second, `FilterSecurityInterceptor` creates a {security-api-url}org/springframework/security/web/FilterInvocation.html[`FilterInvocation`] from the `HttpServletRequest`, `HttpServletResponse`, and `FilterChain` that are passed into the `FilterSecurityInterceptor`.
|
||||
// FIXME: link to FilterInvocation
|
||||
* image:{icondir}/number_3.png[] Next, it passes the `FilterInvocation` to `SecurityMetadataSource` to get the ``ConfigAttribute``s.
|
||||
* image:{icondir}/number_4.png[] Finally, it passes the `Authentication`, `FilterInvocation`, and ``ConfigAttribute``s to the `AccessDecisionManager`.
|
||||
** image:{icondir}/number_5.png[] If authorization is denied, an `AccessDeniedException` is thrown.
|
||||
In this case the <<servlet-exceptiontranslationfilter,`ExceptionTranslationFilter`>> handles the `AccessDeniedException`.
|
||||
** image:{icondir}/number_6.png[] If access is granted, `FilterSecurityInterceptor` continues with the <<servlet-filters-review,FilterChain>> which allows the application to process normally.
|
||||
|
||||
// configuration (xml/java)
|
||||
|
||||
By default, Spring Security's authorization will require all requests to be authenticated.
|
||||
The explicit configuration looks like:
|
||||
|
||||
.Every Request Must be Authenticated
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests(authorize -> authorize // <1>
|
||||
.antMatchers("/resources/**", "/signup", "/about").permitAll() // <2>
|
||||
.antMatchers("/admin/**").hasRole("ADMIN") // <3>
|
||||
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") // <4>
|
||||
.anyRequest().authenticated() // <5>
|
||||
)
|
||||
.formLogin(withDefaults());
|
||||
// ...
|
||||
.authorizeRequests(authorize -> authorize
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
}
|
||||
----
|
||||
|
||||
<1> There are multiple children to the `http.authorizeRequests()` method each matcher is considered in the order they were declared.
|
||||
.XML
|
||||
[source,xml,role="secondary"]
|
||||
----
|
||||
<http>
|
||||
<!-- ... -->
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
</http>
|
||||
----
|
||||
====
|
||||
|
||||
We can configure Spring Security to have different rules by adding more rules in order of precedence.
|
||||
|
||||
.Authorize Requests
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
// ...
|
||||
.authorizeRequests(authorize -> authorize // <1>
|
||||
.mvcMatchers("/resources/**", "/signup", "/about").permitAll() // <2>
|
||||
.mvcMatchers("/admin/**").hasRole("ADMIN") // <3>
|
||||
.mvcMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") // <4>
|
||||
.anyRequest().denyAll() // <5>
|
||||
);
|
||||
}
|
||||
----
|
||||
|
||||
.XML
|
||||
[source,xml,role="secondary"]
|
||||
----
|
||||
<http> <!--1-->
|
||||
<!-- ... -->
|
||||
<!--2-->
|
||||
<intercept-url pattern="/resources/**" access="permitAll"/>
|
||||
<intercept-url pattern="/signup" access="permitAll"/>
|
||||
<intercept-url pattern="/about" access="permitAll"/>
|
||||
|
||||
<intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/> <!--3-->
|
||||
<intercept-url pattern="/db/**" access="hasRole('ADMIN') and hasRole('DBA')"/> <!--4-->
|
||||
<intercept-url pattern="/**" access="denyAll"/> <!--5-->
|
||||
</http>
|
||||
----
|
||||
====
|
||||
<1> There are multiple authorization rules specified.
|
||||
Each rule is considered in the order they were declared.
|
||||
<2> We specified multiple URL patterns that any user can access.
|
||||
Specifically, any user can access a request if the URL starts with "/resources/", equals "/signup", or equals "/about".
|
||||
<3> Any URL that starts with "/admin/" will be restricted to users who have the role "ROLE_ADMIN".
|
||||
You will notice that since we are invoking the `hasRole` method we do not need to specify the "ROLE_" prefix.
|
||||
<4> Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA".
|
||||
You will notice that since we are using the `hasRole` expression we do not need to specify the "ROLE_" prefix.
|
||||
<5> Any URL that has not already been matched on only requires that the user be authenticated
|
||||
<5> Any URL that has not already been matched on is denied access.
|
||||
This is a good strategy if you do not want to accidentally forget to update your authorization rules.
|
||||
|
@ -6,13 +6,13 @@ Irrespective of how you choose to authenticate - whether using a Spring Security
|
||||
In this part we'll explore the different `AbstractSecurityInterceptor` implementations, which were introduced in Part I.
|
||||
We then move on to explore how to fine-tune authorization through use of domain access control lists.
|
||||
|
||||
include::architecture.adoc[]
|
||||
include::architecture.adoc[leveloffset=+1]
|
||||
|
||||
include::secure-objects.adoc[]
|
||||
include::authorize-requests.adoc[leveloffset=+1]
|
||||
|
||||
include::expression-based.adoc[]
|
||||
|
||||
include::authorize-requests.adoc[]
|
||||
include::secure-objects.adoc[]
|
||||
|
||||
include::method-security.adoc[]
|
||||
|
||||
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
Loading…
x
Reference in New Issue
Block a user