全新Spring Security安全管理配置使用详解

发表于:2024-2-04 09:50

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Springboot实战案例锦    来源:Spring全家桶实战案例源码

  1. 简介
  Spring Security 是一个提供身份验证、授权和防护常见攻击的框架。它为确保命令式和反应式应用程序的安全提供一流的支持,是确保基于 Spring 的应用程序安全的事实标准。
  Spring Scurity核心分为2大模块:
  认证(Authentication):认证是建立一个他声明的主体的过程(一个主体一般是指用户、设备或一些可以在你的应用程序中执行的其他系统)。常见的身份认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。
  授权(Authorization):当身份认证通过后,去访问系统的资源,系统会判断用户是否拥有访问该资源的权限,只允许访问有权限的系统资源,没有权限的资源将无法访问,这个过程叫用户授权。比如会员管理模块有增删改查功能,有的用户只能进行查询,而有的用户可以进行修改、删除。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。
  从Spring Security5.7开始之前的安全配置方式及Web授权处理方式发生了变化,接下来将详细介绍配置的变化。
  2. 安全配置
  2.1 配置方式
  在5.7之前的版本自定义安全配置通过如下方式:
  @Component
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) throws Exception {
      // ...
    }
  }
  在5.7之后推荐如下配置方式
  @Configuration
  public class SecurityConfig {
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    SecurityFilterChain controllerFilterChain(HttpSecurity http) throws Exception {
      // ...
      return http.build() ;
    }
  }
  通过配置安全过滤器链的方式配置,具体内部的配置细节还都是围绕着HttpSecurity进行配置。
  2.2 配置不同的过滤器链
  在一个配置文件中我们可以非常方便的配置多个过滤器链,针对不同的请求进行拦截。
  @Configuration
  public class SecurityConfig {
    @Bean
    @Order(1)
    SecurityFilterChain controllerFilterChain(HttpSecurity http) {
      // 当前过滤器链只对/demos/**, /login, /logout进行拦截
      http.requestMatchers(matchers -> matchers.antMatchers("/demos/**", "/login", "/logout")) ;
      http.authorizeHttpRequests().antMatchers("/**").authenticated() ;
      http.formLogin(Customizer.withDefaults()) ;
      // ...
      return http.build() ;
    }
    @Bean
    @Order(2)
    SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception {
      // 该过滤器只会对/ac/**的请求进行拦截
      http.requestMatchers(matchers -> matchers.antMatchers("/ac/**")) ;
      // ...
      http.formLogin(Customizer.withDefaults());
      return http.build();
    }
  }
  以上配置了2个过滤器链,根据配置的@Order值,优先级分别:controllerFilterChain,managementSecurityFilterChain。当访问除上面指定的uri模式以为的请求都将自动放行。
  2.3 用户验证配置
  在5.7版本之前,我们通过如下配置配置内存用户
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.inMemoryAuthentication()
        .passwordEncoder(NoOpPasswordEncoder.getInstance())
        .withUser("admin")
        .password("123123")
        .authorities(Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"))) ;
    }
  }
  5.7 只有由于推荐的是通过自定义SecurityFilterChain的方式,所以我们需要通过如下的方式进行配置:
  @Configuration
  public class SecurityConfig {
    @Bean
    @Order(0)
    SecurityFilterChain controllerFilterChain(HttpSecurity http) throws Exception {
      AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class) ;
      builder.inMemoryAuthentication()
        .passwordEncoder(NoOpPasswordEncoder.getInstance())
        .withUser("admin")
        .password("123123")
        .authorities(Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"))) ;
      // ...
    }
  }
  2.4 授权方式
  在5.7之后推荐配置认证授权的方式如下
  @Bean
  public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests().antMatchers("/users/**").hasAnyRole("ADMIN") ;
    // ...
    return http.build() ;
  }
  通过上面的authorizeHttpRequests方式进行授权配置,会向过滤器链中添加AuthorizationFilter过滤器。在该过滤器中会进行权限的验证。
  2.5 自定义授权决策
  如果需要对请求的uri进行更加精确的匹配验证,如:/users/{id},需要验证只有这里的id值为666才方向。
  @Bean
  public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(registry -> {
      registry.antMatchers("/users/{id}").access(new AuthorizationManager<RequestAuthorizationContext>() {
        @Override
        public AuthorizationDecision check(Supplier<Authentication> authentication,
            RequestAuthorizationContext object)
          // 获取路径上的值信息,其中key=id,value=xxx
          Map<String, String> variables 
          // 这里的第一个参数是boolean,确定了授权是否通过
          return new AuthorityAuthorizationDecision(variables.get("id").equals("666"), Arrays.asList(new SimpleGrantedAuthority("D"))) ;
        }
      }) ;
    }) ;
  }
  2.6 全局认证
  如果配置了多个不同的SecurityFilterChain,而每个认证都使用相同的用户体系,那么我们可以定义AuthenticationProvider或者UserDetailsService 类型的Bean即可。
  @Bean
  UserDetailsService userDetailsService() {
    return new UserDetailsService() {
      @Override
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return null;
      }
    } ;
  }
  @Bean
  AuthenticationProvider authenticationProvider() {
    return new AuthenticationProvider() {
      @Override
      public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        return null;
      }
      @Override
      public boolean supports(Class<?> authentication) {
        return false;
      }
    } ;
  }
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号