我有一个配置了 @EnableResourceServer
注释的资源服务器,它通过 user-info-uri
参数引用授权服务器,如下所示:
security:
oauth2:
resource:
user-info-uri: http://localhost:9001/user
授权服务器/user 端点返回 org.springframework.security.core.userdetails.User
的扩展,例如一封电子邮件:
{
"password":null,
"username":"myuser",
...
"email":"me@company.com"
}
每当访问某个资源服务器端点时,Spring 通过调用授权服务器的 /user
端点来验证幕后的访问 token ,它实际上会返回丰富的用户信息(其中包含例如电子邮件信息,我已经验证Wireshark)。
所以问题是如何在不显式第二次调用授权服务器的 /user
端点的情况下获取此自定义用户信息。 Spring 是否在授权后将其存储在资源服务器本地的某个位置,或者如果没有开箱即用的可用信息,实现这种用户信息存储的最佳方法是什么?
最佳答案
解决方案是实现一个自定义的UserInfoTokenServices
只需将您的自定义实现作为 Bean 提供,它将被使用而不是默认实现。
在这个 UserInfoTokenServices 中,您可以按照自己的意愿构建 principal
。
此 UserInfoTokenServices 用于从您的授权服务器的 /users
端点的响应中提取 UserDetails。如您所见
private Object getPrincipal(Map<String, Object> map) {
for (String key : PRINCIPAL_KEYS) {
if (map.containsKey(key)) {
return map.get(key);
}
}
return "unknown";
}
默认情况下仅提取 PRINCIPAL_KEYS
中指定的属性。这正是你的问题。您必须提取的不仅仅是用户名或您的属性名称。所以寻找更多的 key 。
private Object getPrincipal(Map<String, Object> map) {
MyUserDetails myUserDetails = new myUserDetails();
for (String key : PRINCIPAL_KEYS) {
if (map.containsKey(key)) {
myUserDetails.setUserName(map.get(key));
}
}
if( map.containsKey("email") {
myUserDetails.setEmail(map.get("email"));
}
//and so on..
return myUserDetails;
}
接线:
@Autowired
private ResourceServerProperties sso;
@Bean
public ResourceServerTokenServices myUserInfoTokenServices() {
return new MyUserInfoTokenServices(sso.getUserInfoUri(), sso.getClientId());
}
!!使用 Spring Boot 1.4 进行更新变得越来越容易!!
使用 Spring Boot 1.4.0 一个 PrincipalExtractor被介绍了。应实现此类以提取自定义主体(参见 Spring Boot 1.4 Release Notes)。
关于spring - 如何从 OAuth2 授权服务器/用户端点获取自定义用户信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35056169/