Skip to content

Commit 32ee30e

Browse files
committed
Extract FilterSecurityInterceptor Docs
Closes gh-8001
1 parent b8d4f33 commit 32ee30e

File tree

7 files changed

+97
-95
lines changed

7 files changed

+97
-95
lines changed

docs/manual/src/docs/asciidoc/_includes/servlet/architecture/core-filters.adoc

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3,72 +3,6 @@
33
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.
44
We won't cover every feature, so be sure to look at the Javadoc for them if you want to get the complete picture.
55

6-
[[filter-security-interceptor]]
7-
=== FilterSecurityInterceptor
8-
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.
9-
Now we'll see how to explicitly configure it for use with a `FilterChainProxy`, along with its companion filter `ExceptionTranslationFilter`.
10-
A typical configuration example is shown below:
11-
12-
[source,xml]
13-
----
14-
<bean id="filterSecurityInterceptor"
15-
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
16-
<property name="authenticationManager" ref="authenticationManager"/>
17-
<property name="accessDecisionManager" ref="accessDecisionManager"/>
18-
<property name="securityMetadataSource">
19-
<security:filter-security-metadata-source>
20-
<security:intercept-url pattern="/secure/super/**" access="ROLE_WE_DONT_HAVE"/>
21-
<security:intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
22-
</security:filter-security-metadata-source>
23-
</property>
24-
</bean>
25-
----
26-
27-
`FilterSecurityInterceptor` is responsible for handling the security of HTTP resources.
28-
It requires a reference to an `AuthenticationManager` and an `AccessDecisionManager`.
29-
It is also supplied with configuration attributes that apply to different HTTP URL requests.
30-
Refer back to <<tech-intro-config-attributes,the original discussion on these>> in the technical introduction.
31-
32-
The `FilterSecurityInterceptor` can be configured with configuration attributes in two ways.
33-
The first, which is shown above, is using the `<filter-security-metadata-source>` namespace element.
34-
This is similar to the `<http>` element from the namespace chapter but the `<intercept-url>` child elements only use the `pattern` and `access` attributes.
35-
Commas are used to delimit the different configuration attributes that apply to each HTTP URL.
36-
The second option is to write your own `SecurityMetadataSource`, but this is beyond the scope of this document.
37-
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.
38-
39-
It should be noted that the `FilterSecurityInterceptor.setSecurityMetadataSource()` method actually expects an instance of `FilterInvocationSecurityMetadataSource`.
40-
This is a marker interface which subclasses `SecurityMetadataSource`.
41-
It simply denotes the `SecurityMetadataSource` understands `FilterInvocation` s.
42-
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.
43-
44-
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.
45-
This behaves in the same way as it does for namespace configuration.
46-
The default is to treat all expressions as Apache Ant paths and regular expressions are also supported for more complex cases.
47-
The `request-matcher` attribute is used to specify the type of pattern being used.
48-
It is not possible to mix expression syntaxes within the same definition.
49-
As an example, the previous configuration using regular expressions instead of Ant paths would be written as follows:
50-
51-
[source,xml]
52-
----
53-
<bean id="filterInvocationInterceptor"
54-
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
55-
<property name="authenticationManager" ref="authenticationManager"/>
56-
<property name="accessDecisionManager" ref="accessDecisionManager"/>
57-
<property name="runAsManager" ref="runAsManager"/>
58-
<property name="securityMetadataSource">
59-
<security:filter-security-metadata-source request-matcher="regex">
60-
<security:intercept-url pattern="\A/secure/super/.*\Z" access="ROLE_WE_DONT_HAVE"/>
61-
<security:intercept-url pattern="\A/secure/.*\" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
62-
</security:filter-security-metadata-source>
63-
</property>
64-
</bean>
65-
----
66-
67-
Patterns are always evaluated in the order they are defined.
68-
Thus it is important that more specific patterns are defined higher in the list than less specific patterns.
69-
This is reflected in our example above, where the more specific `/secure/super/` pattern appears higher than the less specific `/secure/` pattern.
70-
If they were reversed, the `/secure/` pattern would always match and the `/secure/super/` pattern would never be evaluated.
71-
726
[[exception-translation-filter]]
737
=== ExceptionTranslationFilter
748
The `ExceptionTranslationFilter` sits above the `FilterSecurityInterceptor` in the security filter stack.

docs/manual/src/docs/asciidoc/_includes/servlet/architecture/index.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ Below is a comprehensive list of Spring Security Filter ordering:
162162
* OAuth2AuthorizationCodeGrantFilter
163163
* SessionManagementFilter
164164
* ExceptionTranslationFilter
165-
* FilterSecurityInterceptor
165+
* <<servlet-authorization-filtersecurityinterceptor,`FilterSecurityInterceptor`>>
166166
* SwitchUserFilter
167167

168168
include::technical-overview.adoc[]

docs/manual/src/docs/asciidoc/_includes/servlet/authorization/architecture.adoc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
// from the original documentation
12

23
[[authz-arch]]
3-
== Authorization Architecture
4+
= Authorization Architecture
45

56

67
[[authz-authorities]]
7-
=== Authorities
8+
== Authorities
89
As we saw in the <<tech-granted-authority,technical overview>>, all `Authentication` implementations store a list of `GrantedAuthority` objects.
910
These represent the authorities that have been granted to the principal.
1011
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();
1920
----
2021

2122
This method allows
22-
`AccessDecisionManager` s to obtain a precise `String` representation of the `GrantedAuthority`.
23+
`AccessDecisionManager` s to obtain a precise `String` representation of the `GrantedAuthority`.
2324
By returning a representation as a `String`, a `GrantedAuthority` can be easily "read" by most `AccessDecisionManager` s.
2425
If a `GrantedAuthority` cannot be precisely represented as a `String`, the `GrantedAuthority` is considered "complex" and `getAuthority()` must return `null`.
2526

@@ -33,13 +34,13 @@ All `AuthenticationProvider` s included with the security architecture use `Simp
3334

3435

3536
[[authz-pre-invocation]]
36-
=== Pre-Invocation Handling
37+
== Pre-Invocation Handling
3738
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.
3839
A pre-invocation decision on whether the invocation is allowed to proceed is made by the `AccessDecisionManager`.
3940

4041

4142
[[authz-access-decision-manager]]
42-
==== The AccessDecisionManager
43+
=== The AccessDecisionManager
4344
The `AccessDecisionManager` is called by the `AbstractSecurityInterceptor` and is responsible for making final access control decisions.
4445
the `AccessDecisionManager` interface contains three methods:
4546

@@ -63,7 +64,7 @@ The `supports(ConfigAttribute)` method is called by the `AbstractSecurityInterce
6364
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.
6465

6566
[[authz-voting-based]]
66-
==== Voting-Based AccessDecisionManager Implementations
67+
=== Voting-Based AccessDecisionManager Implementations
6768
Whilst users can implement their own `AccessDecisionManager` to control all aspects of authorization, Spring Security includes several `AccessDecisionManager` implementations that are based on voting.
6869
<<authz-access-voting>> illustrates the relevant classes.
6970

@@ -105,7 +106,7 @@ For example, votes from a particular `AccessDecisionVoter` might receive additio
105106

106107

107108
[[authz-role-voter]]
108-
===== RoleVoter
109+
==== RoleVoter
109110
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.
110111

111112
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.
115116

116117

117118
[[authz-authenticated-voter]]
118-
===== AuthenticatedVoter
119+
==== AuthenticatedVoter
119120
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.
120121
Many sites allow certain limited access under remember-me authentication, but require a user to confirm their identity by logging in for full access.
121122

@@ -124,14 +125,14 @@ See the Javadoc for this class for more information.
124125

125126

126127
[[authz-custom-voter]]
127-
===== Custom Voters
128+
==== Custom Voters
128129
Obviously, you can also implement a custom `AccessDecisionVoter` and you can put just about any access-control logic you want in it.
129130
It might be specific to your application (business-logic related) or it might implement some security administration logic.
130131
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.
131132

132133

133134
[[authz-after-invocation-handling]]
134-
=== After Invocation Handling
135+
== After Invocation Handling
135136
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.
136137
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.
137138

@@ -153,7 +154,7 @@ This latter (recommended) approach is usually achieved through a `ROLE_USER` or
153154

154155

155156
[[authz-hierarchical-roles]]
156-
=== Hierarchical Roles
157+
== Hierarchical Roles
157158
It is a common requirement that a particular role in an application should automatically "include" other roles.
158159
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.
159160
To achieve this, you can either make sure that all admin users are also assigned the "user" role.
Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,96 @@
1-
[[jc-authorize-requests]]
2-
== Authorize Requests
3-
Our examples have only required users to be authenticated and have done so for every URL in our application.
4-
We can specify custom requirements for our URLs by adding multiple children to our `http.authorizeRequests()` method.
5-
For example:
1+
[[servlet-authorization-filtersecurityinterceptor]]
2+
= Authorize HttpServletRequest with FilterSecurityInterceptor
3+
:figures: images/servlet/authorization
4+
:icondir: images/icons
65

6+
This section builds on <<servlet-architecture,Servlet Architecture and Implementation>> by digging deeper into how <<authorization>> works within Servlet based applications.
77

8-
[source,java]
8+
The {security-api-url}org/springframework/security/web/access/intercept/FilterSecurityInterceptor.html[`FilterSecurityInterceptor`] provides <<authorization>> for ``HttpServletRequest``s.
9+
It is inserted into the <<servlet-filterchainproxy>> as one of the <<servlet-security-filters>>.
10+
11+
.Authorize HttpServletRequest
12+
image::{figures}/filtersecurityinterceptor.png[]
13+
14+
* image:{icondir}/number_1.png[] First, the `FilterSecurityInterceptor` obtains an <<servlet-authentication-authentication>> from the <<servlet-authentication-securitycontextholder>>.
15+
* 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`.
16+
// FIXME: link to FilterInvocation
17+
* image:{icondir}/number_3.png[] Next, it passes the `FilterInvocation` to `SecurityMetadataSource` to get the ``ConfigAttribute``s.
18+
* image:{icondir}/number_4.png[] Finally, it passes the `Authentication`, `FilterInvocation`, and ``ConfigAttribute``s to the `AccessDecisionManager`.
19+
** image:{icondir}/number_5.png[] If authorization is denied, an `AccessDeniedException` is thrown.
20+
In this case the <<servlet-exceptiontranslationfilter,`ExceptionTranslationFilter`>> handles the `AccessDeniedException`.
21+
** image:{icondir}/number_6.png[] If access is granted, `FilterSecurityInterceptor` continues with the <<servlet-filters-review,FilterChain>> which allows the application to process normally.
22+
23+
// configuration (xml/java)
24+
25+
By default, Spring Security's authorization will require all requests to be authenticated.
26+
The explicit configuration looks like:
27+
28+
.Every Request Must be Authenticated
29+
====
30+
.Java
31+
[source,java,role="primary"]
32+
----
33+
protected void configure(HttpSecurity http) throws Exception {
34+
http
35+
// ...
36+
.authorizeRequests(authorize -> authorize
37+
.anyRequest().authenticated()
38+
);
39+
}
40+
----
41+
42+
.XML
43+
[source,xml,role="secondary"]
44+
----
45+
<http>
46+
<!-- ... -->
47+
<intercept-url pattern="/**" access="authenticated"/>
48+
</http>
49+
----
50+
====
51+
52+
We can configure Spring Security to have different rules by adding more rules in order of precedence.
53+
54+
.Authorize Requests
55+
====
56+
.Java
57+
[source,java,role="primary"]
958
----
1059
protected void configure(HttpSecurity http) throws Exception {
1160
http
61+
// ...
1262
.authorizeRequests(authorize -> authorize // <1>
13-
.antMatchers("/resources/**", "/signup", "/about").permitAll() // <2>
14-
.antMatchers("/admin/**").hasRole("ADMIN") // <3>
15-
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") // <4>
16-
.anyRequest().authenticated() // <5>
17-
)
18-
.formLogin(withDefaults());
63+
.mvcMatchers("/resources/**", "/signup", "/about").permitAll() // <2>
64+
.mvcMatchers("/admin/**").hasRole("ADMIN") // <3>
65+
.mvcMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')") // <4>
66+
.anyRequest().denyAll() // <5>
67+
);
1968
}
2069
----
2170
22-
<1> There are multiple children to the `http.authorizeRequests()` method each matcher is considered in the order they were declared.
71+
.XML
72+
[source,xml,role="secondary"]
73+
----
74+
<http> <!--1-->
75+
<!-- ... -->
76+
<!--2-->
77+
<intercept-url pattern="/resources/**" access="permitAll"/>
78+
<intercept-url pattern="/signup" access="permitAll"/>
79+
<intercept-url pattern="/about" access="permitAll"/>
80+
81+
<intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/> <!--3-->
82+
<intercept-url pattern="/db/**" access="hasRole('ADMIN') and hasRole('DBA')"/> <!--4-->
83+
<intercept-url pattern="/**" access="denyAll"/> <!--5-->
84+
</http>
85+
----
86+
====
87+
<1> There are multiple authorization rules specified.
88+
Each rule is considered in the order they were declared.
2389
<2> We specified multiple URL patterns that any user can access.
2490
Specifically, any user can access a request if the URL starts with "/resources/", equals "/signup", or equals "/about".
2591
<3> Any URL that starts with "/admin/" will be restricted to users who have the role "ROLE_ADMIN".
2692
You will notice that since we are invoking the `hasRole` method we do not need to specify the "ROLE_" prefix.
2793
<4> Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA".
2894
You will notice that since we are using the `hasRole` expression we do not need to specify the "ROLE_" prefix.
29-
<5> Any URL that has not already been matched on only requires that the user be authenticated
95+
<5> Any URL that has not already been matched on is denied access.
96+
This is a good strategy if you do not want to accidentally forget to update your authorization rules.

docs/manual/src/docs/asciidoc/_includes/servlet/authorization/index.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ Irrespective of how you choose to authenticate - whether using a Spring Security
66
In this part we'll explore the different `AbstractSecurityInterceptor` implementations, which were introduced in Part I.
77
We then move on to explore how to fine-tune authorization through use of domain access control lists.
88

9-
include::architecture.adoc[]
9+
include::architecture.adoc[leveloffset=+1]
1010

11-
include::secure-objects.adoc[]
11+
include::authorize-requests.adoc[leveloffset=+1]
1212

1313
include::expression-based.adoc[]
1414

15-
include::authorize-requests.adoc[]
15+
include::secure-objects.adoc[]
1616

1717
include::method-security.adoc[]
1818

0 commit comments

Comments
 (0)