Spring Oauth2 - 重新加载主体
Posted
技术标签:
【中文标题】Spring Oauth2 - 重新加载主体【英文标题】:Spring Oauth2 - reload principals 【发布时间】:2016-02-21 14:25:36 【问题描述】:我已经使用 spring 安全模块实现了 OAuth2 密码授予。我添加了自己的 UserDetails 和 UserDetailsService (jdbc) 实现。我将 User 注入到我的控制器中:
@AuthenticationPrincipal User user
其中 User 是我的 UserDetails 实现。 现在我想在不刷新令牌的情况下添加更改用户数据的可能性。
我尝试通过以下方式刷新主体:
User updatedUser = ...
Authentication newAuth = new UsernamePasswordAuthenticationToken(updatedUser, updatedUser.getPassword(), updatedUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(newAuth);
但它不起作用,当我调用另一个控制器方法时,它返回旧的用户对象。
有没有办法在不刷新令牌的情况下更改用户数据?是否有任何解决方案可以让 Spring Security 始终从数据库(而不是缓存)加载用户数据?
【问题讨论】:
在应用程序的哪一层刷新principals? 【参考方案1】:我从this answer 找到了实现此目的的方法。我创建了HttpSessionSecurityContextRepository
@Bean
public ReloadUserPerRequestHttpSessionSecurityContextRepository userDetailContextRepository()
return new ReloadUserPerRequestHttpSessionSecurityContextRepository();
并将其从WebSecurityConfigurerAdapter
的类中添加到我的HttpSecurity
中
.and()
.csrf()
.csrfTokenRepository(csrfTokenRepository())
.and()
.securityContext()
.securityContextRepository(userDetailContextRepository())
以下是在每次请求时获取更新的用户信息的示例代码。您可以从您的 API 服务器或 oauth2 配置的 user-info-url
获取。
public class ReloadUserPerRequestHttpSessionSecurityContextRepository extends HttpSessionSecurityContextRepository
@Override
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder)
SecurityContext context = super.loadContext(requestResponseHolder);
Authentication auth = context.getAuthentication();
if (auth != null && auth instanceof OAuth2Authentication)
OAuth2Authentication oldAuth = (OAuth2Authentication) auth;
if (oldAuth.getPrincipal() instanceof LinkedHashMap)
createNewUserDetailsFromPrincipal(oldAuth.getPrincipal());
context.setAuthentication(oldAuth);
return context;
@SuppressWarnings("unchecked")
private void createNewUserDetailsFromPrincipal(Object principal)
LinkedHashMap<String, Object> userDetailInfo = (LinkedHashMap<String, Object>) principal;
// fetch User informations from your API server or your database or
// 'user-info-url' of oauth2 endpoint
userDetailInfo.put("name", "EDITED_USER_NAME");
【讨论】:
【参考方案2】:我不确定,但这只是一个猜测,我认为您还需要清除 SecurityContext
。
首先使用SecurityContextHolder.clearContext();
清除安全上下文,然后使用您的代码设置身份验证
Authentication newAuth = new UsernamePasswordAuthenticationToken(updatedUser, updatedUser.getPassword(), updatedUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(newAuth);
【讨论】:
受 Oauth2 保护的应用程序无法使用UsernamePasswordAuthenticationToken
类型身份验证进行分配。以上是关于Spring Oauth2 - 重新加载主体的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security Oauth2:主体对象未返回扩展的用户详细信息
具有 OAuth2-ResourceServer 的 Spring 微服务仅返回 String 作为主体而不是我的自定义用户
资源服务器获取用户信息,java - Spring Security OAuth2资源服务器无法获取包含详细信息的主体 - 堆栈内存溢出...
资源服务器获取用户信息,java - Spring Security OAuth2资源服务器无法获取包含详细信息的主体 - 堆栈内存溢出...
资源服务器获取用户信息,java - Spring Security OAuth2资源服务器无法获取包含详细信息的主体 - 堆栈内存溢出...