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

Spring Boot中通过自定义认证服务器验证JWT及空指针问题排查

问题分析与解决方案

一、当前实现的核心问题

你的整体思路是对的:通过过滤器拦截请求、提取JWT、调用认证服务器完成验证,但代码存在多处错误,不仅会触发空指针,还会导致请求无法正常流转:

  • 未处理请求头缺失的情况:如果请求没带AUTHORIZATION头,token会是null,直接调用trim()会触发空指针
  • 未实例化tokenValidateRequest:代码里直接调用tokenValidateRequest.setToken(token),但这个对象根本没创建,必然抛出空指针
  • 未执行过滤器链:doFilter方法最后没调用chain.doFilter(request, response),拦截后请求不会继续往下走,服务B的API永远无法被访问
  • RestTemplate可能未正确注入:如果Spring容器里没有配置RestTemplate的Bean,@Autowired注入的restTemplate会是null,调用exchange时触发空指针

二、空指针异常的具体诱因

你遇到的RestTemplate空指针,大概率是以下某一种情况:

  1. RestTemplate未被Spring管理:如果项目里没有通过@Bean配置RestTemplate实例,@Autowired无法注入有效对象,restTemplate为null
  2. token为空时调用trim():请求未携带AUTHORIZATION头,req.getHeader("AUTHORIZATION")返回null,执行token.trim()直接抛出空指针(这个异常可能被你误以为是RestTemplate抛出的)
  3. tokenValidateRequest未初始化:代码中直接调用tokenValidateRequest.setToken(token),但这个对象没有通过new TokenValidateRequest()实例化,调用set方法时触发空指针

三、修正后的代码示例

@Autowired
private RestTemplate restTemplate;

// 务必在Spring配置类中添加RestTemplate的Bean声明,否则@Autowired会失败
// @Bean
// public RestTemplate restTemplate() {
//     return new RestTemplate();
// }

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    // 1. 处理请求头缺失的情况
    String token = req.getHeader("AUTHORIZATION");
    if (token == null || token.trim().isEmpty()) {
        res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        res.getWriter().write("Missing authorization token");
        return;
    }
    token = token.trim();

    // 2. 初始化token验证请求对象
    TokenValidateRequest tokenValidateRequest = new TokenValidateRequest();
    tokenValidateRequest.setToken(token);

    // 3. 构造请求URI
    URI myURI;
    try {
        myURI = new URI("http://localhost:8092/auth-user/validate");
    } catch (URISyntaxException e) {
        res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        res.getWriter().write("Failed to construct validation URI");
        throw new RuntimeException(e);
    }

    // 4. 调用认证服务器验证
    HttpHeaders headers = new HttpHeaders();
    HttpEntity<TokenValidateRequest> requestEntity = new HttpEntity<>(tokenValidateRequest, headers);
    try {
        restTemplate.exchange(myURI, HttpMethod.POST, requestEntity, String.class);
        // 验证通过,继续执行过滤器链,让请求到达目标API
        chain.doFilter(request, response);
    } catch (Exception e) {
        // 验证失败,返回未授权
        res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        res.getWriter().write("Invalid or expired token");
    }
}

额外注意事项

  • 建议给AUTHORIZATION头做格式校验(比如是否以Bearer 开头),符合JWT的标准传递格式
  • 可以给RestTemplate添加超时配置,避免认证服务器响应慢导致服务B请求阻塞
  • 生产环境中建议把认证服务器地址配置到配置文件中,不要硬编码

内容的提问来源于stack exchange,提问作者D.Anush

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:31:35