Spring-Security基于源码扩展-一套系统多套登录逻辑(二十二)
在有些项目中一套系统可能有多套登录逻辑
比如
/manage/** 管理后台相关接口走后台认证
/h5/api/** 小程序相关接口走token认证
1.在"5.WebSecurityConfiguration首先会初始化一个webSecurity管理我们定义的WebSecurityConfigurerAdapter子类"我们可以看到先初始化WebSecurity 并将我们自定义配置SpringSecurity的WebSecurityConfigurerAdapter设置成WebSecurity的configures WebSecurityConfigurerAdapter本质也是一个builder
2.在”org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration#springSecurityFilterChain"处会调用WebSecurity.build方法构建springSecurityFilterChain
3.build内部先调用init,init方法会遍历configures也就是我们的WebSecurityConfiguration的init方法源码处<2>
3.1 WebSecurityConfigurerAdapter的init方法会初始化HttpSecurity 同时也会调用configure方法允许我们自定义HttpSecurityConfig和AuthenticationManagerBuilder源码处<8>
3.2最终将HttpSecurity(本质也是一个build) add到webSecurity的securityFilterChainBuilder源码处<6>
4.调用webSecurity.performBuild方法 会循环调用securityFilterChainBuilder也就是HttpSecurity的build方法构建出SecurityFilterChain add 到securityFilterChains
4.1SecurityFilterChain维护了一批Filter 以及这个SecurityFilterChain的匹配规则 比如/manage/** 或者/h5/api/** 默认是是AnyRequest
通过以上源码知识我们可以定义多个WebSecurityConfigurerAdapter实现生成多个SecurityFilterChain并且定义匹配规则
以下就是处理不同url的不同登录逻辑 HttpSessionSecurityContextRepository是因为源码Spring-security源码-Filter之SecurityContextPersistenceFilter(十一)
默认是HttpSessionSecurityContextRepository来负责读取和写入保存当前会话,但是key如果我们没有定义的话默认都是使用同一个SPRING_SECURITY_CONTEXT
UserSecurityConfig
@Configuration @Order(1) public class UserSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { /** * inMemoryAuthentication 开启在内存中定义用户 * 多个用户通过and隔开 */ auth.inMemoryAuthentication() .withUser("liqiang").password("liqiang").roles("admin") .and() .withUser("admin").password("admin").roles("admin"); } @Override protected void configure(HttpSecurity http) throws Exception { RequestMatcher requestMatcher=new AntPathRequestMatcher("/user/**"); HttpSessionSecurityContextRepository httpSessionSecurityContextRepository= new HttpSessionSecurityContextRepository(); httpSessionSecurityContextRepository.setSpringSecurityContextKey("user"); http.securityContext().securityContextRepository(httpSessionSecurityContextRepository).and(). requestMatcher(requestMatcher) .authorizeRequests() .anyRequest() .authenticated() .and().rememberMe()//记住登录 .tokenRepository(new InMemoryTokenRepositoryImpl()) .and() .formLogin()// rm表单的方式 .loginPage("/user/login")//登录页面路径 .loginProcessingUrl("/user/doLogin") //自定义登录请求地址 .defaultSuccessUrl("/user/hello") .usernameParameter("loginName") .passwordParameter("loginPassword") .permitAll(true)//不拦截 .and() .csrf()//记得关闭 .disable() .sessionManagement(). maximumSessions(1) .maxSessionsPreventsLogin(true); } }
ProductSecurityConfig
@Configuration @Order(0) public class ProductSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { /** * inMemoryAuthentication 开启在内存中定义用户 * 多个用户通过and隔开 */ auth.inMemoryAuthentication() .withUser("liqiang").password("liqiang").roles("admin") .and() .withUser("admin").password("admin").roles("admin"); } @Override protected void configure(HttpSecurity http) throws Exception { RequestMatcher requestMatcher=new AntPathRequestMatcher("/product/**"); HttpSessionSecurityContextRepository httpSessionSecurityContextRepository= new HttpSessionSecurityContextRepository(); httpSessionSecurityContextRepository.setSpringSecurityContextKey("product"); http.requestMatcher(requestMatcher).securityContext().securityContextRepository(httpSessionSecurityContextRepository).and().authorizeRequests() .anyRequest() .authenticated() .and().rememberMe()//记住登录 .tokenRepository(new InMemoryTokenRepositoryImpl()) .and() .formLogin()// rm表单的方式 .loginPage("/product/login")//登录页面路径 .loginProcessingUrl("/product/doLogin") //自定义登录请求地址 .defaultSuccessUrl("/product/hello") .usernameParameter("loginName") .passwordParameter("loginPassword") .permitAll(true)//不拦截 .and() .csrf()//记得关闭 .disable() .sessionManagement(). maximumSessions(1) .maxSessionsPreventsLogin(true); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
2016-11-15 数据库事物导致的脏读 不可重复读 幻读的处理方法