@AuthenticationPrincipal对象返回存储在会话中的上一个值。
Spring boot + spring security oauth REST Server。 https://github.com/legshort/spring-boot-sample
这两个REST方法都在控制器中。问题是,当我运行测试代码时,deleteUser()的最后一个参数userDetailsImpl与updateUser()中的userDetailsImpl值相同。
@RequestMapping(method = RequestMethod.PUT, value = "/users/{userId}")
public ResponseEntity updateUser(@PathVariable Long userId,
@AuthenticationPrincipal UserDetailsImpl userDetailsImpl,
@Valid @RequestBody UserUpdateForm userUpdateForm,
BindingResult bindingResult) {
logger.info("UserUpdate: " + userUpdateForm);
User updatedUser = userService.updateUser(userUpdateForm
.createUser(userId));
return new ResponseEntity(updatedUser, HttpStatus.OK);
}
@RequestMapping(method = RequestMethod.DELETE, value = "/users/{userId}")
public ResponseEntity deleteUser(@PathVariable Long userId,
@AuthenticationPrincipal UserDetailsImpl userDetailsImpl) {
logger.info("UserDelete: " + userId);
User requestedUser = new User(userId);
userService.deleteUser(requestedUser);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
以下是控制器测试代码
我不知道第二个请求是testDeleteUser()是如何具有会话值的,而且它是使用先前测试的同一个用户。因此,即使在deleteUser()的开头验证访问令牌并加载新用户,但在userDetailsImpl的某些实际值在testUpdateUser()的开头创建了错误的用户。
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(filterChainProxy).build();
}
@Test
public void testUpdateUser() throws Exception {
User savedUser = signUpUser();
// @formatter:off
mockMvc.perform(
put("/users/" + savedUser.getId())
.header(HeaderUtil.AUTHORIZATION, getAuthorizationWithAccessToken())
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(UserUpdateFormFactory.newInstance())))
.andExpect(status().isOk())
.andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.id", is(greaterThan(NumberUtils.INTEGER_ZERO))))
.andExpect(jsonPath("$.name", is(equalTo(StringUtil.NEW + UserFactory.NAME))));
// @formatter:on
}
@Test
public void testDeleteUser() throws Exception {
User savedUser = signUpUser();
String authorization = getAuthorizationWithAccessToken();
// @formatter:off
mockMvc.perform(
delete("/users/" + savedUser.getId())
.header(HeaderUtil.AUTHORIZATION, authorization)
.contentType(TestUtil.APPLICATION_JSON_UTF8))
.andDo(print())
.andExpect(status().isNoContent());
// @formatter:on
}
这是UserDetailService实现,当涉及到loadUserByUserName()以验证访问令牌时,它从数据库加载适当的用户并返回刚在每个测试方法开头创建的新用户(signUpUser())。
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserService userService;
@Override
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
User requestedUser = new User();
requestedUser.setEmail(email);
User savedUser = userService.findByEmail(requestedUser);
return new UserDetailsImpl(savedUser);
}
}
我试图禁用我失败的会话,配置和测试代码似乎很好。 spring-security-oauth有什么好的实用例子吗?
已更新
据我了解mockMvc,它清除所有设置,每次使用setUp()方法创建几乎全新的模拟服务器。因此,每次都应该清除访问令牌存储,但不知何故,令牌存储会维护经过身份验证的令牌。
在测试过程中询问使用“/ oauth / token”请求的访问令牌,下面是InMemoryTokenStore的调用方式。
测试流程日志
testUpdateUser() - > POST:/ oauth / token - >商店令牌
令牌:50b10897-9e15-4859-aeb0-43d0802ba42c
user:id = 2
testUpdateUser() - > PUT:/ users / 2 - >读令牌
令牌:50b10897-9e15-4859-aeb0-43d0802ba42c
user:id = 2
testUpdateUserWithWrongUserId() - > GET:/ oauth / token - >商店令牌
标记:50b10897-9e15-4859-aeb0-43d0802ba42c - >已经存在于令牌中
user:id = 2 - > id = 4:用新的
testUpdateUserWithWrongUserId() - > PUT:/ users / 0 - >读令牌
令牌:50b10897-9e15-4859-aeb0-43d0802ba42c
user:id = 2
testDeleteUser() - > GET:/ oauth / token - >没有存储令牌,应该存储令牌
testDeleteUser() - >删除:/ users / 5 - >读令牌
令牌:50b10897-9e15-4859-aeb0-43d0802ba42c
user:id = 2 - > user应该是id = 5,它是使用userSignUp()
问题
如何使用mockMvc清除InMemoryTokenStore的每个测试方法?
答案 0 :(得分:0)
// ignore spring security session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);