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

如何自定义Spring Authorization Server令牌端点的异常处理

解决Spring Authorization Server令牌端点自定义异常响应问题

针对授权码交换令牌时需要添加额外校验、自定义错误信息/错误码及非标准HTTP状态码的需求,可通过以下两种方案实现:

方案1:扩展AuthenticationProvider拦截校验逻辑(推荐)

授权码交换的核心校验逻辑由OAuth2AuthorizationCodeAuthenticationProvider处理,我们可以扩展这个类插入自定义校验,并通过全局Filter捕获自定义异常来控制响应。

步骤1:自定义AuthenticationProvider

扩展默认的授权码校验提供者,在父类校验通过后添加自定义逻辑,校验失败时抛出携带自定义信息的异常:

@Component
public class CustomAuthorizationCodeAuthenticationProvider extends OAuth2AuthorizationCodeAuthenticationProvider {

    public CustomAuthorizationCodeAuthenticationProvider(OAuth2AuthorizationService authorizationService,
                                                        OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator) {
        super(authorizationService, tokenGenerator);
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 执行默认授权码校验
        OAuth2AuthorizationCodeAuthenticationToken authToken = 
            (OAuth2AuthorizationCodeAuthenticationToken) super.authenticate(authentication);
        
        // 自定义额外校验逻辑(示例:检查用户状态)
        OAuth2User user = (OAuth2User) authToken.getPrincipal();
        if (!"ACTIVE".equals(user.getAttribute("status"))) {
            throw new CustomOAuth2AuthException("USER_INACTIVE", "用户已禁用", HttpStatus.FORBIDDEN.value());
        }

        return authToken;
    }
}

步骤2:定义自定义异常类

继承AuthenticationException,携带自定义错误码、描述和HTTP状态码:

public class CustomOAuth2AuthException extends AuthenticationException {
    private final String errorCode;
    private final int httpStatus;

    public CustomOAuth2AuthException(String errorCode, String message, int httpStatus) {
        super(message);
        this.errorCode = errorCode;
        this.httpStatus = httpStatus;
    }

    // Getter方法
    public String getErrorCode() { return errorCode; }
    public int getHttpStatus() { return httpStatus; }
}

步骤3:注册自定义AuthenticationProvider

替换默认的提供者,确保自定义逻辑生效:

@Configuration
public class AuthServerConfig {

    @Bean
    public OAuth2AuthorizationCodeAuthenticationProvider customAuthCodeProvider(
            OAuth2AuthorizationService authorizationService,
            OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator) {
        return new CustomAuthorizationCodeAuthenticationProvider(authorizationService, tokenGenerator);
    }
}

步骤4:添加异常捕获Filter

通过Filter捕获自定义异常,直接写入响应体并设置状态码:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class OAuth2ExceptionHandlerFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        try {
            chain.doFilter(request, response);
        } catch (CustomOAuth2AuthException e) {
            // 设置响应参数
            response.setStatus(e.getHttpStatus());
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());

            // 构造自定义响应体
            Map<String, Object> errorBody = new HashMap<>();
            errorBody.put("error", e.getErrorCode());
            errorBody.put("error_description", e.getMessage());
            // 可按需添加其他字段

            new ObjectMapper().writeValue(response.getWriter(), errorBody);
        }
    }

    // 仅对/oauth2/token端点生效
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        return !"/oauth2/token".equals(request.getRequestURI()) || !"POST".equals(request.getMethod());
    }
}

方案2:自定义TokenEndpointFilter替换默认实现

如果需要完全控制端点的异常处理逻辑,可以复制OAuth2TokenEndpointFilter的源码,修改其中的authenticationFailureHandler为自定义实现,再注册到容器中替换默认Filter。注意该方案存在版本兼容性风险,需同步框架源码更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:00:51