• SpringSecurity基于源码扩展一套系统多套登录逻辑(二十二)


    在有些项目中一套系统可能有多套登录逻辑

    比如

    /manage/** 管理后台相关接口走后台认证

    /h5/api/** 小程序相关接口走token认证

    spring-security源码-初始化(九)

    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);
        }
    
    
    }
  • 相关阅读:
    salt+jenkins+gitlab+ecs构建公司部署平台
    解决openstack实例主机名后缀问题
    测试CentOS-7-x86_64-Minimal-1708.iso这种光盘安装效果
    dbca建库--linux上使用vnc图形化安装oracle10g版本
    使用mediainfo工具统计每个视频文件(媒体文件)播放时长
    rsync命令简单用法介绍
    winscp工具和xshell连接linux机器时切换到root账户
    zabbix和iptables的nat表结合使用
    adb和机顶盒一些常识
    VirtualBox虚拟机禁止时间同步
  • 原文地址:https://www.cnblogs.com/LQBlog/p/15557457.html
Copyright © 2020-2023  润新知