Skip to content

Commit 9bc38ed

Browse files
marcusdacoregiojzheaux
authored andcommitted
Register FilterChainProxy for All Dispatcher Types Migration Steps
Closes gh-12186
1 parent b81fbf0 commit 9bc38ed

File tree

1 file changed

+141
-1
lines changed

1 file changed

+141
-1
lines changed

docs/modules/ROOT/pages/migration.adoc

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,7 @@ http {
13741374
----
13751375
====
13761376

1377+
[[switch-filter-all-dispatcher-types]]
13771378
==== Switch to filter all dispatcher types
13781379

13791380
Spring Security 5.8 and earlier only xref:servlet/authorization/architecture.adoc[perform authorization] once per request.
@@ -1384,7 +1385,7 @@ As such, in 6.0, Spring Security changes this default.
13841385

13851386
So, finally, change your authorization rules to filter all dispatcher types.
13861387

1387-
To do this, change:
1388+
To do this, you should change:
13881389

13891390
====
13901391
.Java
@@ -1464,6 +1465,145 @@ http {
14641465
----
14651466
====
14661467

1468+
And, the `FilterChainProxy` should be registered for all dispatcher types as well.
1469+
If you are using Spring Boot, https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.security.spring.security.filter.dispatcher-types[you have to change the `spring.security.filter.dispatcher-types` property] to include all dispatcher types:
1470+
1471+
====
1472+
.application.properties
1473+
[source,properties,role="primary"]
1474+
----
1475+
spring.security.filter.dispatcher-types=request,async,error,forward,include
1476+
----
1477+
====
1478+
1479+
If you are xref::servlet/configuration/java.adoc#_abstractsecuritywebapplicationinitializer[using the `AbstractSecurityWebApplicationInitializer`] you should override the `getSecurityDispatcherTypes` method and return all dispatcher types:
1480+
1481+
====
1482+
.Java
1483+
[source,java,role="primary"]
1484+
----
1485+
import org.springframework.security.web.context.*;
1486+
1487+
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
1488+
1489+
@Override
1490+
protected EnumSet<DispatcherType> getSecurityDispatcherTypes() {
1491+
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.FORWARD,
1492+
DispatcherType.FORWARD, DispatcherType.INCLUDE);
1493+
}
1494+
1495+
}
1496+
----
1497+
====
1498+
1499+
===== Permit `FORWARD` when using Spring MVC
1500+
1501+
If you are using {spring-framework-reference-url}/web.html#mvc-viewresolver[Spring MVC to resolve view names], you will need to permit `FORWARD` requests.
1502+
This is because when Spring MVC detects a mapping between view name and the actual views, it will perform a forward to the view.
1503+
As we saw on the <<switch-filter-all-dispatcher-types,previous section>>, Spring Security 6.0 will apply authorization to `FORWARD` requests by default.
1504+
1505+
Consider the following common configuration:
1506+
1507+
====
1508+
.Java
1509+
[source,java,role="primary"]
1510+
----
1511+
@Bean
1512+
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
1513+
http
1514+
.authorizeHttpRequests((authorize) -> authorize
1515+
.shouldFilterAllDispatcherTypes(true)
1516+
.requestMatchers("/").authenticated()
1517+
.anyRequest().denyAll()
1518+
)
1519+
.formLogin((form) -> form
1520+
.loginPage("/login")
1521+
.permitAll()
1522+
));
1523+
return http.build();
1524+
}
1525+
----
1526+
====
1527+
1528+
and one of the following equivalents MVC view mapping configurations:
1529+
1530+
====
1531+
.Java
1532+
[source,java,role="primary"]
1533+
----
1534+
@Controller
1535+
public class MyController {
1536+
1537+
@GetMapping("/login")
1538+
public String login() {
1539+
return "login";
1540+
}
1541+
1542+
}
1543+
----
1544+
====
1545+
1546+
====
1547+
.Java
1548+
[source,java,role="primary"]
1549+
----
1550+
@Configuration
1551+
public class MyWebMvcConfigurer implements WebMvcConfigurer {
1552+
1553+
@Override
1554+
public void addViewControllers(ViewControllerRegistry registry) {
1555+
registry.addViewController("/login").setViewName("login");
1556+
}
1557+
1558+
}
1559+
----
1560+
====
1561+
1562+
With either configuration, when there is a request to `/login`, Spring MVC will perform a *forward* to the view `login`, which, with the default configuration, is under `src/main/resources/templates/login.html` path.
1563+
The security configuration permits requests to `/login` but every other request will be denied, including the `FORWARD` request to the view under `/templates/login.html`.
1564+
1565+
To fix this, you should configure Spring Security to permit `FORWARD` requests:
1566+
1567+
====
1568+
.Java
1569+
[source,java,role="primary"]
1570+
----
1571+
http
1572+
.authorizeHttpRequests((authorize) -> authorize
1573+
.shouldFilterAllDispatcherTypes(true)
1574+
.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
1575+
.anyRequest().denyAll()
1576+
)
1577+
// ...
1578+
----
1579+
1580+
.Kotlin
1581+
[source,kotlin,role="secondary"]
1582+
----
1583+
http {
1584+
authorizeHttpRequests {
1585+
shouldFilterAllDispatcherTypes = true
1586+
authorize(DispatcherTypeRequestMatcher(DispatcherType.FORWARD), permitAll)
1587+
authorize(anyRequest, denyAll)
1588+
}
1589+
}
1590+
----
1591+
1592+
.Xml
1593+
[source,xml,role="secondary"]
1594+
----
1595+
<http filter-all-dispatcher-types="true" use-authorization-manager="true">
1596+
<intercept-url request-matcher-ref="forwardRequestMatcher" access="permitAll()" />
1597+
<!-- ... -->
1598+
<intercept-url pattern="/**" access="denyAll"/>
1599+
</http>
1600+
1601+
<bean name="forwardRequestMatcher" class="org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher">
1602+
<constructor-arg value="FORWARD"/>
1603+
</bean>
1604+
----
1605+
====
1606+
14671607
==== Replace any custom filter-security ``AccessDecisionManager``s
14681608

14691609
Your application may have a custom {security-api-url}org/springframework/security/access/AccessDecisionManager.html[`AccessDecisionManager`] or {security-api-url}org/springframework/security/access/AccessDecisionVoter.html[`AccessDecisionVoter`] arrangement.

0 commit comments

Comments
 (0)