• 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最新实战

  • 相关阅读:
    多线程与高并发常见面试题(1)
    LoadRunner 多用户并发 登录,上传数据,登出的脚本教程
    windows cmd 链接远程mysql服务器
    Ubuntu 16.04添加阿里云源
    sqlite 数据库与mysql 数据库使用区别记录
    jdk源码之 hashmap 与hashtable 的区别
    通过构造器启动线程的实现方式及其缺点记录。
    eclipse 中过滤空包,目录树中不显示。
    javascript中正则实现读取当前url中指定参数值方法。
    Reactjs+Webpack+es2015 入门HelloWord(一)
  • 原文地址:https://www.cnblogs.com/cinlap/p/16295214.html
Copyright © 2020-2023  润新知