Spring Boot控制器测试中无ADMIN权限用户访问/users/{id}接口返回200而非预期403的问题排查
看起来你遇到了一个典型的Spring Security权限校验失效问题,我帮你梳理几个最可能的原因和解决办法:
方法级安全注解未启用
这是最容易踩的坑!你在控制器方法上加了@PreAuthorize("hasRole('ADMIN')"),但如果没开启方法级安全支持,这个注解根本不会生效。
解决办法:在你的Spring Security配置类上添加对应启用注解:- 如果你用的是Spring Boot 3.x/Spring Security 6.x,添加
@EnableMethodSecurity - 如果你用的是旧版本(Spring Boot 2.x/Spring Security 5.x),添加
@EnableGlobalMethodSecurity(prePostEnabled = true)
这个注解会让Spring识别并处理@PreAuthorize这类方法级安全注解。
- 如果你用的是Spring Boot 3.x/Spring Security 6.x,添加
SecurityFilterChain配置未被正确加载
检查你的Security配置类是否加了@Configuration和@EnableWebSecurity注解?如果没加@Configuration,Spring不会扫描到这个配置类,你写的/users/**权限拦截规则就不会生效,导致普通用户也能直接访问接口。
另外还要确认这个配置类在Spring的扫描路径下(比如和启动类同包或子包),否则也不会被加载生效。测试代码中的冗余配置
你的测试里同时用了@WithMockUser("USER")和.with(user("user").roles("USER")),这两个都是设置测试用的认证用户,虽然不会直接导致权限失效,但容易造成混淆,建议保留一个即可,比如改成:@Test @WithMockUser(username = "user", roles = "USER") void editUserTest() throws Exception { User modifiedUser = new User("lisa1", "pw", "email@test-mail.com"); Mockito.when(userAdministrationService.getUserById(modifiedUser.getId())).thenReturn(Optional.of(modifiedUser)); modifiedUser.setId("randomId"); modifiedUser.setRole(Role.ROLE_USER); mockMvc.perform(put("/users/{id}", "randomId") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(modifiedUser))) .andExpect(status().isForbidden()); }另外你之前加了
.with(csrf()),但你的Security配置里已经禁用了csrf,所以这个也可以去掉。角色权限一致性验证
虽然你的角色配置看起来没问题,但再确认一下细节:- 用
User.withUsername().roles("ADMIN")创建用户时,Spring会自动给角色加上ROLE_前缀,所以admin用户的实际权限是ROLE_ADMIN @PreAuthorize("hasRole('ADMIN')")会自动匹配ROLE_ADMIN权限,这个逻辑是正确的;如果用hasAuthority才需要写全ROLE_ADMIN
你的User实体里的Role枚举是ROLE_USER、ROLE_ADMIN,和Security的权限体系是一致的,这块应该没问题。
- 用
按照你的描述,Postman里用普通user也能访问成功,说明你的Security拦截规则确实没有生效,优先检查前两点(方法级安全启用和配置类加载),应该就能解决问题。
备注:内容来源于stack exchange,提问作者rwd762

