You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Blazor WASM调用需授权第三方REST API遇403错误求助

解决Blazor WASM中调用需授权第三方API返回403的问题

首先,Postman能正常请求但Blazor里返回403,核心差异在于浏览器的CORS安全限制Blazor WASM中HttpClient的行为特性,下面给你拆解问题并给出解决方案:

一、先排查最常见的CORS问题

Postman不受浏览器CORS政策约束,但Blazor在浏览器中运行,所有跨域请求都会触发浏览器的预检(OPTIONS)请求。如果第三方API没有正确配置CORS规则,比如:

  • 未允许你的Blazor应用域名(比如http://localhost:5000)作为合法来源
  • 未允许Authorization自定义请求头
  • 未允许OPTIONS方法

浏览器就会直接拦截请求,返回403。你可以通过浏览器开发者工具的Network标签,查看是否有失败的OPTIONS请求,来确认这一点。

解决办法:

  • 如果能联系第三方API提供者,让他们更新CORS配置,添加你的域名、允许Authorization头和OPTIONS方法
  • 如果无法修改第三方配置,建议搭建一个后端代理(比如ASP.NET Core Web API):Blazor请求你的代理API,代理再转发请求到第三方API。服务器端请求不受CORS限制,完美绕过这个问题。

二、修正Basic Auth的设置方式

你当前直接修改TestClient.DefaultRequestHeaders.Authorization的方式,在Blazor WASM中可能存在两个问题:

  1. HttpClient实例复用导致的头污染:Blazor中注入的HttpClient默认是单例,修改默认头后,后续所有请求都会带上这个凭证,可能引发冲突或被浏览器安全策略拦截
  2. 编码方式问题:用Encoding.ASCII编码凭证,如果用户名/密码包含非ASCII字符,会导致编码错误,API无法识别凭证

推荐改用HttpRequestMessage单独为每个请求设置授权头,同时改用UTF-8编码,代码修改如下:

@page "/"
@inject HttpClient TestClient
@using System.Net.Http.Headers
@using System.Text
@using System.Web

<h3>Presentations Scheduled</h3>
<form>
  <fieldset class="form-group">
    <div>
      <button type="button" class="btn btn-dark mr-sm-2 mb-2" @onclick=@GetToday>Today </button>
    </div>
  </fieldset>
  @if (!string.IsNullOrWhiteSpace(errorString))
  {
    <div class="h2 text-danger">@errorString</div>
  }
  else if (!string.IsNullOrWhiteSpace(httpResponse))
  {
    <div class="h2">@httpResponse</div>
  }
</form>

@code {
  string errorString;
  string httpResponse;

  private async Task GetToday()
  {
    errorString = null;
    httpResponse = null;
    try
    {
      string todayDate = DateTime.Today.ToString("yyyyMMdd");
      // 构建请求URL和参数
      var uriBuilder = new UriBuilder("https://webservices.XXXAPI.com/ws/run/reservations.json");
      var queryParams = HttpUtility.ParseQueryString(uriBuilder.Query);
      queryParams["resource_query_id"] = "244782";
      queryParams["scope"] = "extended";
      queryParams["start_dt"] = todayDate;
      queryParams["end_dt"] = todayDate;
      uriBuilder.Query = queryParams.ToString();

      // 创建单独的请求消息,设置Basic Auth头
      var request = new HttpRequestMessage(HttpMethod.Get, uriBuilder.Uri);
      var credentials = "user:pass";
      var base64Credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
      request.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64Credentials);

      // 发送请求并验证状态码
      var response = await TestClient.SendAsync(request);
      response.EnsureSuccessStatusCode(); // 状态码非2xx时抛出异常

      httpResponse = await response.Content.ReadAsStringAsync();
    }
    catch (HttpRequestException ex)
    {
      errorString = $"请求失败: {ex.Message}";
      if (ex.StatusCode.HasValue)
      {
        errorString += $" 状态码: {ex.StatusCode}";
      }
    }
    catch (Exception ex)
    {
      errorString = $"发生未知错误: {ex.Message}";
    }
  }
}

三、额外的排查建议

  • 用浏览器开发者工具的Network标签,查看实际发送的请求头,确认Authorization头是否正确携带
  • 确认凭证(user:pass)没有拼写错误,特别是大小写、特殊字符
  • 如果第三方API使用的是其他授权方式(比如Bearer Token),但你误用了Basic Auth,也会返回403,不过你说Postman正常,这个可能性较低

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

火山引擎 最新活动