Java调用Companies House API遇401错误:响应码200但openStream报错
问题排查与修复方案
核心问题分析
这种getResponseCode()返回200但openStream()触发401的情况,大概率和认证头传递、连接状态管理或重定向处理有关,结合Companies House API的认证规则,以下是常见错误点和修复方式:
1. 认证头设置错误
Companies House API要求使用Basic Auth,规则是:
- 用户名:你的API密钥
- 密码:空字符串
- 需将
API_KEY:拼接后做Base64编码,再放入Authorization头
如果代码里没有正确生成这个头,或编码时遗漏冒号,就会导致认证失败。比如错误写法:
// 错误:未加冒号或编码字符集不正确 String auth = Base64.getEncoder().encodeToString(apiKey.getBytes()); conn.setRequestProperty("Authorization", "Basic " + auth);
正确写法:
String authCredentials = apiKey + ":"; String encodedAuth = Base64.getEncoder().encodeToString(authCredentials.getBytes(StandardCharsets.UTF_8)); String authHeader = "Basic " + encodedAuth; conn.setRequestProperty("Authorization", authHeader);
2. 重定向时未携带认证头
HttpURLConnection默认自动跟随重定向,但不会将Authorization头传递到重定向后的请求中。如果API返回重定向,后续请求会因缺少认证头触发401。
解决方法:手动处理重定向,确保每个请求都带上认证头:
// 禁用自动重定向 conn.setInstanceFollowRedirects(false); int responseCode = conn.getResponseCode(); if (responseCode >= 300 && responseCode < 400) { String redirectUrl = conn.getHeaderField("Location"); URL newUrl = new URL(redirectUrl); HttpURLConnection newConn = (HttpURLConnection) newUrl.openConnection(); // 重新设置认证头等必要头信息 newConn.setRequestProperty("Authorization", authHeader); newConn.setRequestProperty("Accept", "application/json"); InputStream in = newConn.getInputStream(); // 后续响应处理逻辑 } else { InputStream in = conn.getInputStream(); // 后续响应处理逻辑 }
3. 连接状态重复读取异常
如果先调用getResponseCode()再调用openStream(),可能因连接状态已被读取,导致后续获取流时异常。建议统一使用getInputStream()或getErrorStream()处理响应,避免混用:
try { InputStream in = conn.getInputStream(); // 处理正常响应 } catch (IOException e) { InputStream errorIn = conn.getErrorStream(); // 处理错误响应(如读取401错误信息) }
4. 缺失Postman默认请求头
Postman会自动添加Accept、User-Agent等默认头,若Java代码未设置这些头,可能被API服务器拒绝。建议补充:
conn.setRequestProperty("Accept", "application/json"); conn.setRequestProperty("User-Agent", "Java HTTP Client");
完整示例代码
import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Base64; public class CompaniesHouseApiClient { public static void main(String[] args) throws Exception { String apiKey = "YOUR_API_KEY"; String companyNumber = "00000001"; String apiUrl = "https://api.company-information.service.gov.uk/company/" + companyNumber; String authCredentials = apiKey + ":"; String encodedAuth = Base64.getEncoder().encodeToString(authCredentials.getBytes(StandardCharsets.UTF_8)); String authHeader = "Basic " + encodedAuth; URL url = new URL(apiUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("Authorization", authHeader); conn.setRequestProperty("Accept", "application/json"); conn.setInstanceFollowRedirects(false); int responseCode = conn.getResponseCode(); InputStream inputStream; if (responseCode >= 300 && responseCode < 400) { String redirectUrl = conn.getHeaderField("Location"); URL newUrl = new URL(redirectUrl); HttpURLConnection newConn = (HttpURLConnection) newUrl.openConnection(); newConn.setRequestMethod("GET"); newConn.setRequestProperty("Authorization", authHeader); newConn.setRequestProperty("Accept", "application/json"); inputStream = newConn.getInputStream(); } else if (responseCode == 200) { inputStream = conn.getInputStream(); } else { inputStream = conn.getErrorStream(); } // 读取响应内容 byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { System.out.print(new String(buffer, 0, bytesRead)); } inputStream.close(); conn.disconnect(); } }
内容的提问来源于stack exchange,提问作者Jagjit Bains
相关产品推荐
相关产品推荐

