The Nature of HttpSecurity

Spring Security 5.4 has a new way of configuring HttpSecurity.

1
2
3
4
5
6
7
8
9
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
            .antMatcher("/**")
            .authorizeRequests(authorize -> authorize
                    .anyRequest().authenticated()
            )
            .build();
}

In fact, you can know that HttpSecurity is used to build a filter SecurityFilterChain that contains a series of filter chains, and normally our configuration is based around building SecurityFilterChain.

spring-security SecurityFilterChain

From the above diagram, we can see that the built one has to be handed over to FilterChainProxy to proxy, isn’t it a bit redundant?

The essence of WebSecurity

In some cases this is indeed superfluous, but more often we may need to configure multiple SecurityFilterChains to achieve multiple access control policies.

spring-security SecurityFilterChain

In order to finely manage the life cycle of multiple SecurityFilterChain, it is necessary to have a unified management agent for these SecurityFilterChain, which is the meaning of WebSecurity. Here is the underlying logic of the build method of WebSecurity.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@Override
protected Filter performBuild() throws Exception {
   Assert.state(!this.securityFilterChainBuilders.isEmpty(),
         () -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
               + "Typically this is done by exposing a SecurityFilterChain bean "
               + "or by adding a @Configuration that extends WebSecurityConfigurerAdapter. "
               + "More advanced users can invoke " + WebSecurity.class.getSimpleName()
               + ".addSecurityFilterChainBuilder directly");
    // 被忽略请求的个数 和 httpscurity的个数 构成了过滤器链集合的大小
   int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
   List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);
    // 初始化过滤器链集合中的 忽略请求过滤器链    
    for (RequestMatcher ignoredRequest : this.ignoredRequests) {
      securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
   }
    // 初始化过滤器链集合中的 httpsecurity定义的过滤器链
   for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
      securityFilterChains.add(securityFilterChainBuilder.build());
   }
   FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
   if (this.httpFirewall != null) {
       // 请求防火墙
      filterChainProxy.setFirewall(this.httpFirewall);
   }
   if (this.requestRejectedHandler != null) {
       // 请求拒绝处理器
      filterChainProxy.setRequestRejectedHandler(this.requestRejectedHandler);
   }
   filterChainProxy.afterPropertiesSet();

   Filter result = filterChainProxy;
   if (this.debugEnabled) {
      this.logger.warn("\n\n" + "********************************************************************\n"
            + "**********        Security debugging is enabled.       *************\n"
            + "**********    This may include sensitive information.  *************\n"
            + "**********      Do not use in a production system!     *************\n"
            + "********************************************************************\n\n");
      result = new DebugFilter(filterChainProxy);
   }
   this.postBuildAction.run();
   return result;
}

As you can see from the source code above, WebSecurity is used to build a Spring bean FilterChainProxy called springSecurityFilterChain. Its role is to define those requests that ignore security controls and those that must, clearing SecurityContext when appropriate to avoid memory leaks, and also to define request firewalls and request rejection processors, plus we turn on Spring Seuciry Debug mode which is also configured here.

There is also a role that may not be mentioned in other articles, FilterChainProxy is the only export of Spring Security to the Spring framework application, which is then combined with a Servlet in Spring’s bridge proxy DelegatingFilterProxy. which constitutes Spring’s only export to the Servlet system. This isolates Spring Security, Spring framework and Servlet API.

Summary

We can actually consider that WebSecurity is the only external outlet for Spring Security, while HttpSecurity is just the way internal security policies are defined; WebSecurity is aligned to FilterChainProxy, while HttpSecurity is aligned to SecurityFilterChain. SecurityFilterChain, and their parent class is AbstractConfiguredSecurityBuilder. After mastering these basically you will know what the difference between them is.

Reference https://felord.cn/webSecurity-httpSecurity.html