我有一个使用Spring Social Security进行身份验证和授权的应用程序。不幸的是,我在模拟Spring Security时遇到了一些问题。似乎根本不起作用。
我有一个REST控制器,如果它应返回的实体的标识符不可用,则返回404 Not Found。如果用户未登录,则任何页面都将重定向到我的应用程序的社交登录页面。
我在这里读到,@WithUserDetails注释最适合我。
@WithUserDetails
所以我的测试方法看起来像这样
@Test @SqlGroup({ @Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, statements = "INSERT INTO UserAccount(id, creationtime, modificationtime, version, email, firstname, lastname, role, signinprovider) VALUES (1, '2008-08-08 20:08:08', '2008-08-08 20:08:08', 1, 'user', 'John', 'Doe', 'ROLE_USER', 'FACEBOOK')"), }) @Rollback @WithUserDetails public void ifNoTeamsInTheDatabaseThenTheRestControllerShouldReturnNotFoundHttpStatus() { ResponseEntity<String> response = restTemplate.getForEntity("/getTeamHistory/{team}", String.class, "Team"); Assert.assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); }
但这似乎根本不起作用。看来测试方法是用匿名用户执行的,因为我得到的状态是200 OK。
我的测试课是这样注释的
@RunWith(SpringRunner.class) @ActiveProfiles("dev") @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @Transactional public class TeamRestControllerTest { //... }
有没有人遇到过由Spring Social提供的嘲笑Spring Security这样的问题?
我目前无法测试,但这是一个 可能的 解决方案。
查看@WithUserDetails实现:
@WithSecurityContext(factory = WithUserDetailsSecurityContextFactory.class) public @interface WithUserDetails { ... } final class WithUserDetailsSecurityContextFactory implements WithSecurityContextFactory<WithUserDetails> { private BeanFactory beans; @Autowired public WithUserDetailsSecurityContextFactory(BeanFactory beans) { this.beans = beans; } public SecurityContext createSecurityContext(WithUserDetails withUser) { String beanName = withUser.userDetailsServiceBeanName(); UserDetailsService userDetailsService = StringUtils.hasLength(beanName) ? this.beans.getBean(beanName, UserDetailsService.class) : this.beans.getBean(UserDetailsService.class); 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; } }
您可以按照相同的模式创建您选择的安全上下文:
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @WithSecurityContext(factory = WithoutUserFactory.class) public @interface WithoutUser { } public class WithoutUserFactory implements WithSecurityContextFactory<WithoutUser> { public SecurityContext createSecurityContext(WithoutUser withoutUser) { return SecurityContextHolder.createEmptyContext(); } }
其他可获得的注释:WithAnonymousUser,WithMockUser,WithSecurityContext(和WithUserDetails)
WithAnonymousUser
WithMockUser
WithSecurityContext
WithUserDetails