2026/6/20 3:23:15
网站建设
项目流程
网站不会更新文章,信息网站设计方案,做网站需要什么花费,公众号怎么做起来一、 背景与痛点
在传统的 Spring Security 开发中#xff08;尤其是单体大应用#xff09;#xff0c;我们往往会在一个主配置类#xff08;如 SecurityConfig#xff09;里写死所有的 URL 权限规则#xff1a;
// 传统写法#xff1a;随着业务增长#xff0c;这个方法…一、 背景与痛点在传统的 Spring Security 开发中尤其是单体大应用我们往往会在一个主配置类如SecurityConfig里写死所有的 URL 权限规则// 传统写法随着业务增长这个方法会变成几百行的“面条代码”http.authorizeHttpRequests().requestMatchers(/admin/**).hasRole(ADMIN).requestMatchers(/order/**).hasRole(USER).requestMatchers(/pay/**).permitAll()// ... 无休止的追加 ...痛点严重耦合基础架构层必须感知所有业务模块的 URL 规则。维护困难多人开发时大家都在修改同一个文件代码冲突不断。扩展性差新增一个业务模块必须去改主工程的代码。二、 核心架构设计为了解决上述问题我们引入了“插拔式”的设计模式。核心由三个部分组成调度中心主配置类只负责调度不负责具体规则。标准协议AuthorizeRequestsCustomizer抽象类定义怎么配。业务实现各模块的 Customizer具体配什么。1. 调度中心主 SecurityFilterChain在主配置类如YudaoWebSecurityConfigurerAdapter中我们不再硬编码规则而是利用 Spring 的自动注入Dependency Injection特性。// 1. 注入所有实现了 Customizer 接口的 BeanResourceprivateListAuthorizeRequestsCustomizerauthorizeRequestsCustomizers;BeanprotectedSecurityFilterChainfilterChain(HttpSecurityhttpSecurity)throwsException{httpSecurity// ... 其他配置 ....authorizeHttpRequests(c-{// 2. 核心逻辑遍历所有注入的 Customizer让它们自己定义规则authorizeRequestsCustomizers.forEach(customizer-customizer.customize(c));// 3. 兜底规则最后执行c.anyRequest().authenticated();});returnhttpSecurity.build();}解析主配置类变成了一个“容器”它根本不知道/order需要什么权限它只负责把话筒交给各个业务模块让模块自己“发言”。2. 标准协议AuthorizeRequestsCustomizer我们需要定义一个抽象类既作为统一的接口类型又可以提供一些通用的工具方法如 API 前缀处理。publicabstractclassAuthorizeRequestsCustomizerimplementsCustomizerAuthorizeHttpRequestsConfigurerHttpSecurity.AuthorizationManagerRequestMatcherRegistry,Ordered{ResourceprivateWebPropertieswebProperties;// 提供通用方法的封装避免各模块硬编码前缀protectedStringbuildAdminApi(Stringurl){returnwebProperties.getAdminApi().getPrefix()url;}protectedStringbuildAppApi(Stringurl){returnwebProperties.getAppApi().getPrefix()url;}// 默认优先级业务模块可以通过重写此方法调整自己在过滤器链中的位置OverridepublicintgetOrder(){return0;}}3. 业务实现模块化的 Customizer假设我们有一个“基础设施模块 (Infra)”它需要开放 Swagger 文档和一些监控断点我们不需要改主工程只需在 Infra 模块内部写一个 BeanConfigurationpublicclassInfraSecurityConfiguration{Bean(infraAuthorizeRequestsCustomizer)publicAuthorizeRequestsCustomizerinfraAuthorizeRequestsCustomizer(){returnnewAuthorizeRequestsCustomizer(){Overridepublicvoidcustomize(AuthorizeHttpRequestsConfigurerHttpSecurity.AuthorizationManagerRequestMatcherRegistry registry){// 定义该模块独有的权限规则registry.requestMatchers(buildAdminApi(/infra/file/**)).permitAll()// 文件下载免登录.requestMatchers(/swagger-ui/**).permitAll()// Swagger 免登录.requestMatchers(/druid/**).hasRole(ADMIN);// 数据库监控需管理员}// 可选如果需要在其他规则之前生效可以调高优先级OverridepublicintgetOrder(){return-10;}};}}三、 工作原理深度解析这个机制之所以能工作依赖于 Spring 容器强大的生命周期管理启动扫描 (Scanning)Spring Boot 启动时扫描所有加了Configuration的类。Bean 注册 (Registration)各个业务模块Infra, Order, Pay定义的AuthorizeRequestsCustomizer被实例化并注册到 Spring 容器中。依赖收集 (Collection)当初始化主配置类YudaoWebSecurityConfigurerAdapter时Resource private ListAuthorizeRequestsCustomizer list这行代码会触发 Spring 去容器里查找所有类型为AuthorizeRequestsCustomizer的 Bean并将它们装进一个 List 集合中。规则应用 (Application)在构建SecurityFilterChain时代码遍历这个 List依次调用customize()方法。最终生效 (Finalization)Spring Security 将这些分散定义的规则合并成一个完整的RequestMatcher链条。四、 优缺点总结优点开闭原则 (Open/Closed Principle)对扩展开放新增模块只需加新 Bean对修改关闭无需动主配置。高内聚业务模块的权限规则写在业务模块内部代码物理距离更近更容易理解。灵活性通过Ordered接口可以精确控制规则的生效顺序例如通用黑名单规则优先级最高普通业务规则优先级居中兜底规则优先级最低。注意事项顺序问题Spring Security 的匹配原则是“先匹配生效First Match Wins”。如果一个优先级高的 Customizer 配置了/**-permitAll那么后面所有模块的规则都会失效。因此使用Ordered进行顺序管理至关重要。