Spring Security 入门:过滤器链与核心组件

安全是 Web 应用绕不开的课题:谁在访问(认证)、能干什么(授权)、如何防伪造与跨域攻击。Spring Security 是 Spring 官方安全框架,Spring Boot 3.x 对应 Security 6.x(jakarta 体系)。本章先把它的架构骨架讲清楚。

引入即全站保护

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

什么都不配,应用立刻:所有请求需认证;启动日志打印随机生成的默认密码(用户名为 user);提供表单登录页与 httpBasic。先跑通再改造。

过滤器链模型(核心)

安全逻辑以过滤器链形式接入 Servlet 容器:

请求 → DelegatingFilterProxy → FilterChainProxy(代理入口)
     → 按顺序匹配第一条 SecurityFilterChain
     → 链内过滤器依次执行(认证、授权、异常翻译…)→ 业务 Servlet
  • SecurityFilterChain:一组规则 + 一串安全过滤器;可以有多个链,先匹配先生效;
  • UsernamePasswordAuthenticationFilter:解析表单/基础认证,调用认证管理器;
  • ExceptionTranslationFilter:把认证/授权失败翻译成 401/403 响应;
  • AuthorizationFilter:按规则做最终授权判断。

核心组件名词

  • Authentication:认证结果对象(主体 principal、凭据 credentials、权限 authorities);
  • SecurityContextHolder:存放当前线程的 Authentication(ThreadLocal),业务代码从此取"我是谁";
  • AuthenticationManager(实现为 ProviderManager):编排多个 AuthenticationProvider 依次尝试认证;
  • UserDetailsService:按用户名加载用户;UserDetails:用户模型(用户名、密文密码、权限列表);
  • PasswordEncoder:密码单向加密与比对(推荐 BCrypt,见下一章);
  • 认证成功后框架把 Authentication 写入 SecurityContext,授权过滤器据此放行。

最小自定义配置

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/public/**").permitAll()   // 匿名可访问
                .requestMatchers("/admin/**").hasRole("ADMIN")    // 需 ADMIN 角色
                .anyRequest().authenticated())                    // 其余一律要登录
            .formLogin(Customizer.withDefaults())                 // 保留表单登录
            .logout(Customizer.withDefaults());
        return http.build();
    }
}

注意 Security 6 起用 requestMatchers(...) 取代旧版 antMatchers(...)。定义出 SecurityFilterChain Bean 后 Boot 即采用自定义配置(类上 @EnableWebSecurity 非必需)。若做前后端分离的纯接口,可关掉表单登录并改用 JWT 过滤器(第 31 章)。

业务里获取当前用户

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// 输出:admin [ROLE_ADMIN, ROLE_USER]
log.info("当前用户 {},权限 {}", auth.getName(), auth.getAuthorities());

Controller 方法参数用 @AuthenticationPrincipal UserDetails user 更解耦,避免直接依赖 ThreadLocal。

小结:Security 本质是一条按顺序匹配的过滤器链;认准 SecurityFilterChain、Authentication、SecurityContextHolder、AuthenticationManager、UserDetailsService 这组核心对象,后面的章节都围绕它们展开。

笔记加载中…