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

Spring授权服务器中使用refresh_token获取用户信息的问题

问题场景与报错详情

我基于Spring新授权服务器实现自定义认证服务,需求是通过CustomAccessTokenResponseHandler在返回的JSON响应中添加额外用户信息。目前已实现AuthenticationSuccessHandler并重写onAuthenticationSuccess方法完成密码模式下的信息补充,同时配置了自定义授权类型(含认证转换器、提供者、令牌)及TokenCustomizer为令牌添加额外声明。

但在refresh_token授权场景下出现异常:使用refresh_token请求新令牌时,未传入用户名密码,不启用自定义响应处理器时令牌可正常生成,启用后报错。当前Authentication对象包含访问令牌,但无法从其Principal中获取用户详情,且不想通过解码JWT(正在实现JWE编码器)的方式获取信息,仅需拿到用户名即可查询数据库补充响应。

报错代码

@Transactional
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) throws IOException, ServletException {
    OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
            (OAuth2AccessTokenAuthenticationToken) authentication;
    OAuth2ClientAuthenticationToken oAuth2ClientAuthenticationToken = (OAuth2ClientAuthenticationToken) accessTokenAuthentication.getPrincipal();
    CustomPasswordUser user = (CustomPasswordUser) oAuth2ClientAuthenticationToken.getDetails();
    // ... 后续补充响应逻辑
}

报错原因

强转后获取的oAuth2ClientAuthenticationToken详情中无用户信息,结构如下:

OAuth2ClientAuthenticationToken [Principal=eQCLrL7JVHw1GRzP, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]]

同时SecurityContextHolder.getContext().getAuthentication().getDetails()仅返回WebAuthenticationDetails,不含用户数据。


解决方案

方案1:从OAuth2RefreshTokenAuthenticationToken获取原始用户认证信息

refresh_token流程中,当前Authentication实际是OAuth2RefreshTokenAuthenticationToken,内部包含了生成refresh_token时对应的原始OAuth2AccessTokenAuthenticationToken,可从中提取用户信息:

@Transactional
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                    Authentication authentication) throws IOException, ServletException {
    OAuth2AccessTokenAuthenticationToken accessTokenAuth;

    // 区分refresh_token模式与其他授权模式
    if (authentication instanceof OAuth2RefreshTokenAuthenticationToken) {
        OAuth2RefreshTokenAuthenticationToken refreshTokenAuth = 
            (OAuth2RefreshTokenAuthenticationToken) authentication;
        // 获取生成refresh_token时的原始访问令牌认证信息
        accessTokenAuth = refreshTokenAuth.getAccessTokenAuthentication();
    } else {
        // 处理密码模式等其他场景
        accessTokenAuth = (OAuth2AccessTokenAuthenticationToken) authentication;
    }

    // 从原始认证信息中提取用户详情(需根据你自定义认证的实际存储结构调整)
    Authentication userAuth = accessTokenAuth.getPrincipal();
    if (userAuth instanceof UsernamePasswordAuthenticationToken) {
        CustomPasswordUser user = (CustomPasswordUser) userAuth.getPrincipal();
        // 用user对象补充响应信息
    }
}

方案2:通过OAuth2AuthorizationService查询refresh_token关联的用户信息

若原始认证信息未保留用户数据,可借助授权服务查询refresh_token对应的授权记录,从中获取用户名后查询数据库:

@Autowired
private OAuth2AuthorizationService authorizationService;
@Autowired
private UserRepository userRepository; // 你的用户数据访问层

@Transactional
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                    Authentication authentication) throws IOException, ServletException {
    String refreshToken = request.getParameter("refresh_token");
    if (refreshToken != null) {
        // 根据refresh_token查询授权记录
        OAuth2Authorization authorization = authorizationService.findByToken(
            refreshToken, OAuth2TokenType.REFRESH_TOKEN);
        if (authorization != null) {
            // 获取用户名,再查询用户详情
            String username = authorization.getPrincipalName();
            CustomPasswordUser user = userRepository.findByUsername(username);
            // 用user对象补充响应信息
        }
    } else {
        // 处理非refresh_token模式的原有逻辑
        OAuth2AccessTokenAuthenticationToken accessTokenAuth = 
            (OAuth2AccessTokenAuthenticationToken) authentication;
        OAuth2ClientAuthenticationToken clientAuth = (OAuth2ClientAuthenticationToken) accessTokenAuth.getPrincipal();
        CustomPasswordUser user = (CustomPasswordUser) clientAuth.getDetails();
        // ... 后续逻辑
    }
}

内容的提问来源于stack exchange,提问作者Abhishek Mishra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 22:48:35