Spring Security 学习笔记 - 自动配置分析

创建项目

创建一个Springboot web项目,并写一个简单的hello控制器,其行为只需要简单返回一个响应即可,例如:

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public JsonResult hello() {
        return JsonResult.OK();
    }
}

运行它,请求 /hello,会返回响应,注意此时没有任何权限机制对请求进行限制,也就是任何人都可以访问/hello资源。

引入依赖

<dependency>
    <groupId>
        org.springframework.boot
    </groupId>
    <artifactId>
        spring-boot-starter-security
    </artifactId>
    <version>
        2.6.7
    </version>
</dependency>

默认加载

在引入Security后如果不做改动,Spring框架会在运行时自动加载Security并运行默认机制,效果就是Security会将整个项目请求保护起来。重新运行应用并访问/hello,浏览器不再直接返回响应,而是跳转到/login并显示一个默认的登录页面,Security起作用了!

发生了什么

Spring会自动加载Security默认安全机制,在请求发生后和Servlet处理请求前使用各种Filter处理这次请求,其中就包括Security框架所包含的Filter。下面代码告诉了我们默认机制发生了什么

 @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnDefaultWebSecurity
    static class SecurityFilterChainConfiguration {
        SecurityFilterChainConfiguration() {
        }

        @Bean
        @Order(2147483642)
        SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
            ((AuthorizedUrl)http.authorizeRequests().anyRequest()).authenticated();
            http.formLogin();
            http.httpBasic();
            return (SecurityFilterChain)http.build();
        }
    }

http的请求要开启权限保护(authorizaRequests()),哪些请求要保护?任何请求(anyRequest()),这些请求都要是已认证的(authenticated),通过什么方式认证,通过表单认证(formLogin())或Basic认证(httpBasic())——这是我基于教程的理解

注解@ConditionalOnDefaultWebSecurity是对defaultSecurityFilterChain方法在什么条件下生效的声明,进入注解看到

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({DefaultWebSecurityCondition.class})
public @interface ConditionalOnDefaultWebSecurity {
}

@Conditional注解说明ConditionalOnDefaultWebSecurity的使用条件是DefaultWebSecurityCondition,再进入DefaultWebSecurityCondition查看一下

class DefaultWebSecurityCondition extends AllNestedConditions {
    DefaultWebSecurityCondition() {
        super(ConfigurationPhase.REGISTER_BEAN);
    }

    @ConditionalOnMissingBean({WebSecurityConfigurerAdapter.class, SecurityFilterChain.class})
    static class Beans {
        Beans() {
        }
    }

    @ConditionalOnClass({SecurityFilterChain.class, HttpSecurity.class})
    static class Classes {
        Classes() {
        }
    }
}

DefaultWebSecurityCondition在两种条件下生效,在当前类路径中存在某些类定义的时候(@ConditionalOnClass)SecurityFilterChain.classHttpSecurity.class的时候,和(在现有工厂中)当不存在某些Bean的实例时候(@ConditionalOnMissingBean)不存在WebSecurityConfigurerAdapter.classSecurityFilterChain.class的时候。在引入依赖后,并没有自己定义WebSecurityConfigurerAdapterSecurityFilterChain,因此刚才的过滤链满足了条件,起了作用,产生了效果。

总结一下,Security默认使用了defaultSecurityFilterChain(中的配置)进行安全行为,如果希望改变默认行为,需要自行定义WebSecurityConfigurerAdapterSecurityFilterChain。定义的方法是创建自己的类继承并注解,使具体实现类在Spring容器中生效。Spring Security 推荐覆盖WebSecurityConfigurerAdapter

bilibili - 编程不良人 - SpringSecurity最新实战

posted @ 2022-05-21 15:35  试试手气  阅读(319)  评论(0编辑  收藏  举报