spring - 如何从 OAuth2 授权服务器/用户端点获取自定义用户信息

标签 spring spring-security spring-boot spring-cloud spring-oauth2

我有一个配置了 @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

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/UserInfoTokenServices.java

只需将您的自定义实现作为 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/

相关文章:

java - Spring Security + 容器管理的身份验证问题

spring-security - Spring Boot - Redis 持久化 token

java - Spring 中的华夫饼自定义错误页面

java - 将 Spring boot 应用程序部署到 Heroku

java - 如何使用特定注释将自定义序列化器设置为任意 API 端点(spring 应用程序)?

spring-boot - Spring Boot + Eureka Server + Hystrix with Turbine : empty turbine. 流

java - Spring Boot Tomcat 无法在特定端口上启动

java - Spring忽略@Primary注解

spring - 使用 Spring-Session 时更新 Session 中的主体

java - 每个实体的 Spring Boot 安全角色