安全与风控
用 Spring Security…
在需要快速验证 Spring Security 方法级授权逻辑(RBAC、表达式授权、自定义权限评估器、拒绝访问场景)而无需启动完整 Spring Security 上下文时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
用 Spring Security 测试通用
解决思路
- 在测试依赖中加入 spring-security-test:<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-test</artifactId><scope>test</scope></dependency>
- 在测试配置类上启用方法级安全:@Configuration @EnableMethodSecurity class TestSecurityConfig { }
- 用 @WithMockUser 设置已认证用户上下文来测试允许场景:@Test @WithMockUser(roles = "ADMIN") void shouldAllowAdminAccess() { assertThatCode(() -> service.deleteUser(1L)).doesNotThrowAnyException(); }
- 用 @WithMockUser 测试拒绝场景并断言抛出 AccessDeniedException:@Test @WithMockUser(roles = "USER") void shouldDenyUserAccess() { assertThatThrownBy(() -> service.deleteUser(1L)).isInstanceOf(AccessDeniedException.class); }
- 测试自定义权限评估器时手动构造 Authentication 并直接调用 evaluator.hasPermission:Authentication auth = new UsernamePasswordAuthenticationToken("alice", null, List.of(new SimpleGrantedAuthority("ROLE_USER"))); Document doc = new Document(1L, "Test", new User("alice")); boolean result = evaluator.hasPermission(auth, doc, "WRITE"); assertThat(result).isTrue();
- 若测试意外通过,添加一个断言验证安全确实生效:@Test void shouldRejectUnauthorizedWhenSecurityEnabled() { assertThatThrownBy(() -> service.deleteUser(1L)).isInstanceOf(AccessDeniedException.class); }
- 对表达式安全(如 @PreAuthorize("#userId == authentication.principal.id"))使用 @WithUserDetails 配合自定义 UserDetailsService:@Test @WithUserDetails("alice") void shouldAllowUserToAccessOwnProfile() { assertThatCode(() -> service.getUserProfile(1L)).doesNotThrowAnyException(); }
- 对每条安全规则同时测试允许与拒绝两种场景
- 用不同角色进行测试以验证基于角色的决策
- 全面测试基于表达式的安全逻辑
- Mock 外部依赖(如权限评估器等)
- 将匿名访问与已认证访问分开测试
- 在配置中使用 @EnableGlobalMethodSecurity 启用方法级安全
适用边界 · 注意事项
- 不要测试框架代码本身,而应测试授权逻辑
- 不要在测试中混入不必要的认证与授权测试
- 不要直接调用方法而绕过代理,否则 @PreAuthorize 会被跳过