Spring Security 教程(09)、验证请求

permitAll():完全公开的资源

request-authorization 配图
request-authorization 配图
request-authorization 配图

1
.requestMatchers("/public/**", "/assets/**", "/favicon.ico").permitAll()

permitAll() 表示这些资源不需要任何认证或授权。任何人都可以访问,包括未登录用户。

适合用于:静态资源、公开 API、登录页面、注册页面、健康检查端点。

authenticated():必须登录才能访问

1
.requestMatchers("/api/**").authenticated()

authenticated() 表示用户必须通过认证才能访问。但未登录用户会被重定向到登录页,而不是直接返回 403。

hasRole() vs hasAuthority()

这是两个容易混淆的方法:

1
2
3
4
5
// hasRole() 会自动添加 "ROLE_" 前缀
.requestMatchers("/admin/**").hasRole("ADMIN") // 实际检查 ROLE_ADMIN

// hasAuthority() 检查完整的权限字符串
.requestMatchers("/api/admin/**").hasAuthority("ROLE_ADMIN")

区别:hasRole() 会自动在传入的角色名前加上 ROLE_ 前缀,而 hasAuthority() 直接使用传入的字符串作为权限标识。

最佳实践:在 UserDetailsService 中返回的权限应该使用完整的 ROLE_ 前缀格式(如 ROLE_ADMIN),然后在配置中使用 hasAuthority() 进行精确匹配。

复杂表达式:and() 和 or()

当同一个 URL 需要满足多种条件时,可以使用 and() 和 or():

1
2
3
4
5
6
7
8
9
10
11
.requestMatchers("/api/v1/**")
.authenticated()
.and()
.requestMatchers("/api/v2/**")
.hasRole("ADMIN")
.or()
.requestMatchers("/api/public/**")
.permitAll()
.and()
.anyRequest()
.authenticated();

注意 and() 和 or() 的优先级:and() 的优先级高于 or(),所以上面的配置实际上是将 /api/v1/** 和 /api/v2/** 作为两个独立的规则,最后一个 or() 连接了第三个规则。

基于 HTTP 方法的访问控制

1
2
3
.requestMatchers(HttpMethod.GET, "/api/users/**").hasRole("USER")
.requestMatchers(HttpMethod.POST, "/api/users/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.DELETE, "/api/users/**").hasRole("ADMIN")

同一个 URL 路径,不同 HTTP 方法可以有不同的访问权限。这是 RESTful API 设计的常见需求。