返回

解决 Bing 搜索 API 401 错误: 订阅密钥疑难解答

java

Bing 搜索 API 401 错误:正确订阅密钥的困境

使用 Bing 搜索 API 时,经常遇到的一种情况是返回 HTTP 401 错误,提示“Access Denied”,即使使用了看似正确的订阅密钥。这个问题的出现往往令人困惑,因为API文档通常只强调了密钥的正确性。下面分析一些可能的原因并提供相应的解决方案。

密钥未生效或未激活

一个常见的误区是,在 Azure 门户创建认知服务资源后,其关联的密钥并不会立即激活。新创建的密钥可能需要一些时间才能在全球的服务器网络中完成同步。 如果立即使用,则很可能出现 401 错误。 另一个原因是,订阅密钥可能处于禁用状态。在Azure门户,检查密钥的状态非常必要,保证它是激活的。

解决方案:

  1. 耐心等待: 创建密钥后,请稍等一段时间再尝试调用API,建议至少等待五到十分钟。
  2. 验证密钥状态: 访问Azure门户,导航到认知服务资源,并查看“密钥”部分,确认密钥处于“启用”状态。
  3. 使用新密钥: 如果怀疑密钥有任何问题,在Azure门户中重新生成新的密钥,并耐心等待生效。

请求头错误配置

Bing 搜索 API 要求在请求头中包含正确的订阅密钥。 常见的错误包括,密钥没有在正确的位置或以正确的格式进行传递。 常见的做法是将 Ocp-Apim-Subscription-Key作为请求头。 大小写错误和额外字符都会导致验证失败, 从而导致出现 401 错误。

解决方案:

确保 HTTP 请求头 Ocp-Apim-Subscription-Key 中包含了订阅密钥, 且无多余空格或其他特殊字符。

代码示例 (Java):

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class BingSearch {

    public static void main(String[] args) {
        String apiKey = "YOUR_SUBSCRIPTION_KEY";  // 替换为你的订阅密钥
        String apiUrl = "https://api.bing.microsoft.com/v7.0/search?q=test"; //测试请求,将test替换为实际查询

        try {
            URL url = new URL(apiUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Ocp-Apim-Subscription-Key", apiKey);


            int responseCode = connection.getResponseCode();
            System.out.println("响应代码:" + responseCode);


            if (responseCode == 200) {
                 BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                StringBuilder responseContent = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                  responseContent.append(line);
                  }
               reader.close();
              System.out.println(responseContent.toString());

                }
            else{
              BufferedReader errorReader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
              String line;
                StringBuilder errorResponse = new StringBuilder();
                while ((line = errorReader.readLine()) != null) {
                  errorResponse.append(line);
                   }
              errorReader.close();

               System.out.println("请求失败!错误内容: " + errorResponse.toString());
           }



           connection.disconnect();



        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

步骤:

  1. 将代码中的 "YOUR_SUBSCRIPTION_KEY" 替换为你真实的密钥。
  2. 将apiUrl中的"test"替换为你的搜索。
  3. 运行此 Java 程序。如果成功,将看到 200 响应和结果; 如果失败,控制台输出401错误或其他的错误信息。

命令行示例 (cURL):

curl -H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY" "https://api.bing.microsoft.com/v7.0/search?q=test"

步骤:

  1. "YOUR_SUBSCRIPTION_KEY" 替换为实际密钥。
  2. "test"替换为实际搜索查询。
  3. 执行此命令,查看响应是否成功,失败则为 401 或其他错误。

网络连接和代理

网络配置问题,尤其是使用了代理,可能会导致无法成功连接到 API 服务器。代理服务器可能没有正确配置,或者存在某种网络安全策略导致连接失败。 使用 VPN 也可能出现类似的连通性问题。

解决方案:

  1. 直接连接: 尽量在没有代理的环境下尝试调用API,确认是否是代理配置导致的问题。
  2. 检查代理设置: 如果必须使用代理,请确认代理的配置正确。确保在代码中正确配置代理地址和端口。
  3. 临时关闭VPN: 测试时暂时关闭VPN, 如果没有问题,可以尝试更换其他的VPN线路。

代码示例 (Java 启用代理):

        // 配置代理
       System.setProperty("http.proxyHost", "YOUR_PROXY_ADDRESS"); //替换成代理地址
       System.setProperty("http.proxyPort", "YOUR_PROXY_PORT");  //替换成代理端口
       System.setProperty("https.proxyHost", "YOUR_PROXY_ADDRESS"); //替换成代理地址
       System.setProperty("https.proxyPort", "YOUR_PROXY_PORT"); //替换成代理端口
       
       // 之后的网络请求将会使用配置的代理

步骤:

  1. 将上述代理设置代码添加到 connection = (HttpURLConnection) url.openConnection();之前。
  2. "YOUR_PROXY_ADDRESS" 替换成你的代理服务器地址, YOUR_PROXY_PORT 替换成代理服务器的端口。
  3. 尝试运行程序,看是否能正常连接到API。

配额和速率限制

Bing 搜索 API 对请求量和频率有限制。达到配额上限或触碰到速率限制可能会导致临时的访问拒绝。错误信息有时不会明确说明是配额或速率限制问题,仍会显示为 401 错误。

解决方案:

  1. 检查 Azure Portal 配额: 访问Azure 门户的认知服务资源,查看已使用和可用的配额情况。
  2. 减少请求频率: 如果是频繁地访问 API, 尝试减少请求频率, 每次访问之后引入小的延迟,或设置等待时间。
  3. 请求配额调整: 如果经常达到配额上限, 需要在 Azure 门户提出增加配额的请求。

代码示例(Java 引入等待):

        // ... 其他代码 ...
            try {
               Thread.sleep(1000); // 请求后延迟 1 秒 (可调整)
            } catch (InterruptedException e) {
                e.printStackTrace();
             }
       //... 后续请求逻辑 ...

步骤:

  1. 在需要延迟的代码后加入 Thread.sleep(1000), 调整 1000 可以更改延迟时长,单位是毫秒。
  2. 观察减少访问频率后,请求是否成功。

排查 401 错误,必须仔细检查以上提到的各个方面。确保密钥有效、请求头正确、网络畅通、配额充足,这样就能提高 API 请求的成功率。