第九章 自定义 Security Mock 注解
从 第八章 Spring Security 的测试支持
可以看到,如果不使用自定义的身份验证主体,@WithMockUser 是一个很好的选择。
一、@WithMockUser 存在的问题
大部分情况下,我们使用都不是 UserDetails 对象,而是 UserDetails 的自定义实现。
且 @WithUserDetails 注解还需要查询数据库,并且要求用户存在。
二、解决方案
我们可以通过模仿 @WithMockUser 注解,创建自己的 @WithMockSutomUser注解。并通过实现 WithSecurityContextFactory 来使用自己的注解。
1. @WithMockSutomUser
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
public @interface WithMockCustomUser {
String username() default "rob";
String name() default "Rob Winch";
}
2. WithMockCustomUserSecurityContextFactory
final class WithUserDetailsSecurityContextFactory
implements WithSecurityContextFactory<WithUserDetails> {
private UserDetailsService userDetailsService;
@Autowired
public WithUserDetailsSecurityContextFactory(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
public SecurityContext createSecurityContext(WithUserDetails withUser) {
String username = withUser.value();
Assert.hasLength(username, "value() must be non-empty String");
UserDetails principal = userDetailsService.loadUserByUsername(username);
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities());
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
return context;
}
}
现在,我们使用新的注解来测试类或方法,Spring Security 的 WithSecurityContextTestExecutionListener 将确保我们的 SecurityContext 得到了适当的填充。