You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring OAuth中获取嵌套的用户名属性

解决方案

方法1:自定义OAuth2UserService解析嵌套响应

这是兼容性最强的方案,不受Spring Security版本限制,手动解析API返回的嵌套JSON结构:

  • 实现自定义的OAuth2UserService,重写loadUser方法提取嵌套的用户信息:
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;

@Component
public class CustomOAuth2UserService extends DefaultOAuth2UserService {

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);
        // 从原始响应中取出嵌套的data对象
        Map<String, Object> userData = (Map<String, Object>) oAuth2User.getAttributes().get("data");
        // 构建自定义属性集,可按需添加其他字段
        Map<String, Object> customAttributes = new HashMap<>(userData);
        // 指定用户名对应的属性键(这里用email,也可换成username)
        return new DefaultOAuth2User(oAuth2User.getAuthorities(), customAttributes, "email");
    }
}
  • 在Security配置中注入并使用这个自定义服务:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    private final CustomOAuth2UserService customOAuth2UserService;

    public SecurityConfig(CustomOAuth2UserService customOAuth2UserService) {
        this.customOAuth2UserService = customOAuth2UserService;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .oauth2Login(oauth2 -> oauth2
                .userInfoEndpoint(userInfo -> userInfo
                    .userService(customOAuth2UserService)
                )
            );
        return http.build();
    }
}

方法2:升级Spring Security到6.2+使用嵌套属性支持

如果你的项目可以升级依赖,Spring Security 6.2及以上版本已经实现了你提到的Issue功能,支持用点号(.)指定嵌套属性路径:

  • 修改application.properties配置:
spring.security.oauth2.client.provider.my_auth_provider.user-name-attribute=data.email
  • 确保Spring Security版本达标,Maven示例:
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>6.2.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>6.2.0</version>
</dependency>

Gradle示例:

implementation 'org.springframework.security:spring-security-web:6.2.0'
implementation 'org.springframework.security:spring-security-config:6.2.0'

方法3:自定义UserInfoResponseClient直接处理API响应

如果需要完全控制用户信息的获取流程,可以自定义响应客户端:

import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserResponseClient;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;
import java.util.Map;

public class CustomUserInfoResponseClient implements OAuth2UserResponseClient<OAuth2UserRequest, OAuth2User> {

    private final RestTemplate restTemplate = new RestTemplate();

    @Override
    public OAuth2User getResponse(OAuth2UserRequest userRequest) {
        String userInfoUri = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri();
        // 调用/api/me端点获取响应
        Map<String, Object> apiResponse = restTemplate.getForObject(
            userInfoUri, 
            Map.class, 
            userRequest.getAccessToken().getTokenValue()
        );
        // 提取嵌套的用户数据
        Map<String, Object> userData = (Map<String, Object>) apiResponse.get("data");
        // 返回构造好的OAuth2User对象
        return new DefaultOAuth2User(
            Collections.singleton(new OAuth2UserAuthority(userData)),
            userData,
            "email"
        );
    }
}
  • 在Security配置中替换默认的响应客户端:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .oauth2Login(oauth2 -> oauth2
            .userInfoEndpoint(userInfo -> userInfo
                .userResponseClient(new CustomUserInfoResponseClient())
            )
        );
    return http.build();
}

内容的提问来源于stack exchange,提问作者Julius Babies

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:06:32