Spring @AuthenticationPrincipal对象返回会话值
@AuthenticationPrincipal对象返回会话中存储的上一个值 Spring引导+Spring安全oauth REST服务器 这两种休息方法都在控制器中。问题是,当我运行测试代码时,deleteUser()处的最后一个参数userDetailSiml和updateUser()处的userDetailSiml的值相同Spring @AuthenticationPrincipal对象返回会话值,spring,rest,spring-security,spring-test,spring-security-oauth2,Spring,Rest,Spring Security,Spring Test,Spring Security Oauth2,@AuthenticationPrincipal对象返回会话中存储的上一个值 Spring引导+Spring安全oauth REST服务器 这两种休息方法都在控制器中。问题是,当我运行测试代码时,deleteUser()处的最后一个参数userDetailSiml和updateUser()处的userDetailSiml的值相同 @RequestMapping(method = RequestMethod.PUT, value = "/users/{userId}") public Respon
@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()开始时创建了错误的用户
这是UserDetailService实现,当需要loadUserByUserName()来验证访问令牌时,它会从数据库中加载适当的用户,并返回在每个测试方法(signUpUser())开始时刚刚创建的新用户
我试图禁用我失败的会话,配置和测试代码对我来说似乎没问题。
SpringSecurityOAuth有什么好的实用例子吗
已更新
测试过程日志
代币:50b10897-9e15-4859-aeb0-43d0802ba42c
用户:id=2
代币:50b10897-9e15-4859-aeb0-43d0802ba42c
用户:id=2
令牌:50b10897-9e15-4859-aeb0-43d0802ba42c->已存在于令牌中
用户:id=2->id=4:用户已更新为新用户
代币:50b10897-9e15-4859-aeb0-43d0802ba42c
用户:id=2
代币:50b10897-9e15-4859-aeb0-43d0802ba42c
user:id=2->user应该是id=5,这是用userSignUp()创建的
问题
如何使用mockMvc清除InMemoryTokenStore中的每个测试方法?您只使用wac(WebApplicationContext)的一个实例,因此主体存储在两个测试执行之间。为什么不在每个测试中显式地设置主体,比如
delete(“/users/”+savedUser.getId()).principal(null)
?AuthenticationPrincipal应该是SecurityContextHolder.getContext().getAuthentication().getPrincipal(),所以这是预期的行为。我想我正在努力弄清楚您希望代码做什么。@谢谢您的评论。我想用干净的状态测试每个方法,这样我希望没有会话或主体。每个测试方法,我理解的是每个测试方法都应该干净,以防止任何其他奇怪的行为。@gsolecki感谢您的指导,但是,主体()不接受null,并且很难找到我应该如何调用主体(),你能给我一个更具体的例子吗?@RobWinch我认为SpringSecurityOAuth应该只依赖于每个测试的请求头中的accessToken。如果我在测试代码上出错,请让我指导正确的测试。也许解释一下你必须把代码放在哪里,解释一下为什么它应该解决这个问题,这样你的回答质量会更好。你需要扩展WebSecurity配置适配器并放置http.sessionManagement().sessionCreationPolicy(sessionCreationPolicy.NEVER)在那里。这是因为rest服务是无状态的,会话持有状态,但因为会话中持有的状态与数据无关,而是会话是元数据,谁在乎呢。
// ignore spring security session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
@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);
}
}
// ignore spring security session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);