Skip to content

07.3 — 方法安全与 CSRF

定位: 方法级别的权限控制和 CSRF 防护机制 面试高频度: ⭐⭐⭐⭐ 考查方式: @PreAuthorize/@PostAuthorize 使用、CSRF 启用/禁用场景

一、这是什么?为什么需要它?

方法安全让权限控制从 Web 层深入到 Service 层,使用注解声明方法级别的访问规则。CSRF 防护防止跨站请求伪造攻击。

二、原理拆解

2.1 方法安全注解

java
@Configuration
@EnableMethodSecurity  // Spring Security 6+(替代 @EnableGlobalMethodSecurity)
public class MethodSecurityConfig {}

@Service
public class DocumentService {
    
    // 需要 ADMIN 角色
    @PreAuthorize("hasRole('ADMIN')")
    public void deleteAll() { ... }
    
    // 基于 SpEL 的条件
    @PreAuthorize("#document.owner == authentication.name")
    public void updateDocument(Document document) { ... }
    
    // 方法后校验
    @PostAuthorize("returnObject.owner == authentication.name")
    public Document findById(Long id) { ... }
    
    // 过滤返回集合
    @PostFilter("filterObject.visible == true")
    public List<Document> findAll() { ... }
}

注解对比

注解功能执行时机
@PreAuthorize方法执行前权限校验进入方法前
@PostAuthorize方法执行后权限校验返回后
@PreFilter过滤输入集合执行前
@PostFilter过滤返回集合执行后

2.2 CSRF 防护

客户端 -> GET /login -> 返回登录页 + CSRF Token
客户端 -> 提交表单 + CSRF Token -> POST /login
Spring Security -> 校验 Token -> 登录成功

禁用 CSRF(无状态 API 场景)

java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)  // 无状态 API 禁用 CSRF
            .sessionManagement(session -> 
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated()
            );
        return http.build();
    }
}

注意:CSRF 对有状态会话(浏览器表单提交)是必须的,对无状态 API(JWT/Basic Auth)可以禁用。

三、面试视角

追问答案要点
@PreAuthorize 和 @Secured 区别?@PreAuthorize 支持 SpEL(更灵活),@Secured 仅支持角色名
CSRF 什么场景启用/禁用?有状态表单 -> 启用;无状态 JWT API -> 禁用
@PostFilter 性能注意点?在内存中过滤,大数据量时注意性能

📚 相关链接

  • **认证流程与过滤器链** — 过滤器链基础
  • **JWT与OAuth2** — 无状态 JWT 方案
  • ← 返回 **返回 Spring Security 索引**

Knowledge4J — Java 知识库