@WithMockUser 到底做了什么?为什么 @WebMvcTest 里的授权测试是绿的、线上却是 403?POST 请求为什么总是 403?测异步代码时用户去哪了?这篇在 Spring Boot 4.0.8、Spring Security 7 上跑 25 个真实的测试用例逐个验证。
匿名 GET /public(真实配置里是 permitAll) → HTTP 401 WWW-Authenticate Basic realm="Realm" @WithMockUser GET /admin(真实配置里需要 ADMIN) → HTTP 200 admin
@WebMvcTest 不扫描 @Configuration,生效的是 Boot 默认规则,测试结果和线上不一致。
匿名 GET /public → HTTP 200 public
匿名 GET /me → HTTP 401 WWW-Authenticate Basic realm="Realm"
@WithMockUser GET /me → HTTP 200 UsernamePasswordAuthenticationToken,name=user,authorities=[ROLE_USER]
@WithMockUser GET /admin → HTTP 403
@WithMockUser(roles = ADMIN) GET /admin → HTTP 200 admin
@WithMockUser(authorities = ADMIN) GET /admin → HTTP 403
@WithMockUser(roles = ADMIN) GET /me → HTTP 200 UsernamePasswordAuthenticationToken,name=user,authorities=[ROLE_ADMIN]
@WithMockUser POST /items(不带 CSRF) → HTTP 403
@WithMockUser POST /items(.with(csrf())) → HTTP 200 created
httpBasic(alice, pw) GET /me → HTTP 200 UsernamePasswordAuthenticationToken,name=alice,authorities=[FactorGrantedAuthority [authority=FACTOR_PASSWORD, issuedAt=2026-10-22T00:45:11.858085Z], ROLE_USER]
httpBasic(alice, 错误) GET /me → HTTP 401 WWW-Authenticate Basic realm="Realm"
@WithUserDetails(root) GET /admin → HTTP 200 admin
@WithUserDetails(root) GET /me → HTTP 200 UsernamePasswordAuthenticationToken,name=root,authorities=[ROLE_ADMIN]
user("x").roles("ADMIN") GET /admin → HTTP 200 admin
@WithMockUser(ADMIN) 同时 anonymous() GET /me → HTTP 401 WWW-Authenticate Basic realm="Realm"
@WithAnonymousUser GET /me → HTTP 401 WWW-Authenticate Basic realm="Realm"@WithMockUser、httpBasic、@WithUserDetails、user()、csrf() 各自的行为。
@WithMockUser GET /svc(Service 上有 @PreAuthorize ADMIN) → HTTP 403 @WithMockUser(ADMIN) GET /svc → HTTP 200 secret @WithMockUser 直接调 svc.secret() → 抛 AuthorizationDeniedException 没有任何用户直接调 svc.secret() → 抛 AuthenticationCredentialsNotFoundException @WithMockUser(ADMIN) 直接调 svc.secret() → secret 测试线程里的用户 = tester;新开的线程里的用户 = null
@PreAuthorize 的异常类型;SecurityContext 只在测试线程里。
匿名 GET /admin → HTTP 200 admin 结果:tests successful 25, tests failed 0, containers failed 0
没有过滤器链,验证不了任何安全规则。