在运行时更新主体的字段

时间:2019-10-01 03:29:56

标签: spring hibernate spring-boot spring-security oauth

我在Spring Boot中对自己的授权和资源服务器使用OAuth2身份验证。我想在运行时代表同一用户或另一用户(管理员/主持人)更改User implements UserDetails(这是我的Principal)对象中的某些字段。例如。 user1(ID = 1)想更改其国家/地区,因此他调用此方法:

@PostMapping("/setMyCountry")
public void setMyCountry(@CurrentUser User user, @RequestParam String newCountry){
    user.setCountry(newCountry);
    userRepository.save(user);
}

但是当我想使用以下方法检查他的国家时:

@GetMapping("/getMyCountry")
public String getMyCountry(@CurrentUser User user){
    return user.getCountry();
}

我回到了原来的国家。

类似地,以管理员身份进行更改:

@PostMapping("/setUserCountry")
public void setUserCountry(@CurrentUser Moderator moderator, @RequestParam String newCountry){
    User user = userRepository.findById(1L).get();
    user.setCountry(newCountry);
    userRepository.save(user);
}

@GetMapping("/getUserCountry")
public String getUserCountry(@CurrentUser Moderator moderator){
    User user = userRepository.findById(1L).get();
    return user.getCountry();
}

它返回相同的国家。但是,当然,数据库显示了新的价值。

我已经看到有关类似问题的问题,但是如果我在setMyCountry()中使用它:

Authentication newAuth = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(newAuth);

然后这仍然行不通。请注意,我使用了自定义令牌,令牌提供者和令牌授予者,但它们都在最后返回UsernamePasswordAuthenticationToken

那么,如何在不注销和登录的情况下更改User的字段并更新当前主体?

1 个答案:

答案 0 :(得分:1)

使用oauth2的常见做法是,身份验证服务器对用户一无所知,而不仅仅是用户名,密码,什么角色和某种密钥,因此它可以查找用户对象。这可以是唯一的UUID,也可以是电子邮件地址中的用户名(主题)。

资源服务器从客户端获取令牌,它使用此令牌,然后调用授权服务器以验证令牌,授权服务器对其进行验证,如果验证通过,则将信息发送回资源​​服务器,以便资源服务器可以填充其UserDetails对象。

如果资源服务器需要知道该用户居住的国家/地区,则它将从Principal / UserDetails对象获取ID,然后调用用户服务,另一个数据库或另一个表,甚至返回授权可能具有/ user端点并将令牌提供给授权服务器的服务器(依次获取主体信息,主题,然后在数据库中查找用户信息),然后将用户对象发回。

我的意思是,您应始终将“身份验证和授权”(角色等)信息与实际的“用户”信息分开。

如果从使用Facebook身份验证更改为github身份验证怎么办。您需要重做所有用户吗?否,因为您将所有用户信息与授权信息分开。