过滤web请求

在spring中存在一个DelegatingFilterProxy,是一种特殊的Filter,主要任务就是将工作委托给Filter实现类

使用@EnableWebSecurity注解时引入FilterChainProxy

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
   boolean hasConfigurers = webSecurityConfigurers != null
         && !webSecurityConfigurers.isEmpty();
   if (!hasConfigurers) {
      WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
            .postProcess(new WebSecurityConfigurerAdapter() {
            });
      webSecurity.apply(adapter);
   }
   return webSecurity.build();
}

可以使用WebApplicationInitializer的方式来配置DelegatingFilterProxy,其会自动为每个url注册springSecurityFilterChain过滤器(也就是DelegatingFilterProxy),添加一个ContextLoaderListener来载入WebSecurityConfig

// AbstractSecurityWebApplicationInitializer类实现了WebApplicationInitializer接口,spring会发现,并在web容器中注册DelegatingFilterProxy
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

}

DelegatingFilterProxy会拦截发往应用中的请求,并将请求委托给springSecurityFilterChain,springSecurityFilterChain本身是另一种特殊的Filter,可以连接任意一个或多个其他的Filter

private void insertSpringSecurityFilterChain(ServletContext servletContext) {
  // DEFAULT_FILTER_NAME就是springSecurityFilterChain
   String filterName = DEFAULT_FILTER_NAME;
   DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(
         filterName);
   String contextAttribute = getWebApplicationContextAttribute();
   if (contextAttribute != null) {
      springSecurityFilterChain.setContextAttribute(contextAttribute);
   }
   registerFilter(servletContext, true, filterName, springSecurityFilterChain);
}

<!-- more -->

配置Spring Security

使用@EnableWebSecurity注解来启用web安全功能,需要配置在实现了WebSecurityConfigurer或者继承WebSecurityConfigurerAdapter类的bean上

@Configuration
@EnableWebSecurity // 引入了WebSecurityConfiguration和AuthenticationConfiguration配置
// 继承WebSecurityConfigurerAdapter来自定义配置,只会覆盖修改的配置,不会覆盖不相关的配置
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  // 通过重载,配置userDetail服务,认证相关的配置
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        
    }
  // 通过重载,配置Filter链
  public void configure(WebSecurity web) throws Exception {
    }
  
  // 通过重载,配置如何通过拦截器保护请求
  protected void configure(HttpSecurity http) throws Exception {

        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin().and()
            .httpBasic();
    }
}

用户信息获取

首先来将第一个configure方法,来进行用户信息的获取

// 通过重载,配置userDetail服务
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

使用自定义的用户服务

public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private AdminDao adminDao;

    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
      // 查找用户
        Admin user = adminDao.findByName(username);
        if (user == null) {
            throw new UsernameNotFoundException("Username not found");
        }
      // 创建权限
      List<GrantedAuthority> authorities = new ArrayList<>();
      authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        return new org.springframework.security.core.userdetails.User(user.getUser_name(), user.getPassword(),authorities);
    }
}

详细样例

 // 通过重载,配置如何通过拦截器保护请求
  protected void configure(HttpSecurity http) throws Exception {
        // 对不同的请求进行不同程度的认证
        http
            .formLogin() // 配置登录页
            .loginPage("/login.html")  // 自定义编写登录页面
            .loginProcessingUrl("/user/login") // 登录访问路径
            .defaultSuccessUrl("/index") // 登陆成功之后跳转路径
        .and()
            .logout().logoutUrl("/logout") // 退出登录的路径
            .logoutSuccessUrl("/index") // 退出登录成功的页面
       .and()
            .authorizeRequests() // // 配置请求级别的认证
            .antMatchers("/","/test/").permitAll() // permitAll表示可以直接访问,不需要认证
            .antMatchers("/user").authenticated() //authenticated表示必须已经登录了系统 
            .antMatchers("/admin/").hasAuthority("admin") // hasAuthority用户具备该权限可以访问
            .antMatchers("/teacher/").hasAnyAuthority("admin","teacher")  // hasAnyAuthority用户具备其中一个权限就可以访问
            .antMatchers("/super/").hasRole("admin")  //hasRole用户具备该角色可以访问,会拼接一个ROLE_前缀,使用的是角色是 ROLE_admin
            .antMatchers("/student/").hasAnyRole("admin","teacher","student") // hasAnyRole如果用户具备其中一个角色就可以访问
              .antMatchers("/school/").access("hasRole('admin')") //access使用给定的spel表达式来计算结果 
            .antMatchers("/ss/").anonymous()  // anonymous允许匿名用户访问
              .antMatchers("/supper/").denyAll() // denyAll拒绝所有访问
            .antMatchers("/full/").fullyAuthenticated() //fullyAuthenticated 用户需要是完整认证(不是通过remeber-me功能认证的)允许访问
            .antMatchers("/ip/").hasIpAddress("127.0.0.1") // hasIpAddress 请求来自指定ip可以访问
            .antMatchers("/reme/").rememberMe() // 用户通过remember-me功能认证的允许访问
            .anyRequest().authenticated() // 其他需要认证
       .and()
            .requiresChannel().anyRequest().requiresSecure() //requiresSecure配置需要https来进行访问  requiresInsecure配置需要http来进行访问
       .and()
            .rememberMe().tokenValiditySeconds(3600).key("zhang") // rememberMe功能,保存时间3600s,rememberMe是将token存储在cookie中的,token包括用户名、密码、过期时间和私钥(key)
       .and()
            .csrf().disable() // 关闭csrf跨站请求伪造防护
            .exceptionHandling().accessDeniedPage("/unauth.html"); // 配置没有权限访问的自定义页面
    }
https://zhhll.icu/2021/框架/springSecurity/2.过滤web请求/

bug生产者
20 声望0 粉丝