Blazor WASM调用API返回401,如何验证access_token已附加?
解决Blazor WASM + Azure AD B2C调用API时401未携带Token的问题
一、配置Azure AD B2C的API权限范围
- 在Azure AD B2C控制台注册后端API应用,记录其Application (client) ID
- 为该API添加自定义权限范围(例如
access_as_user),设置范围名称、显示名称,勾选“允许管理员和用户同意” - 回到Blazor WASM的应用注册页面,添加API权限:选择刚才注册的API,勾选创建的delegated权限,点击“授予管理员同意”
二、修改Blazor WASM的Program.cs配置
需确保身份验证配置包含API权限范围,同时正确关联HttpClient的消息处理器:
builder.Services.AddMsalAuthentication(options => { builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication); // 添加API权限范围,格式为 "api://{API_CLIENT_ID}/{SCOPE_NAME}" options.ProviderOptions.DefaultAccessTokenScopes.Add("api://xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/access_as_user"); }); // 配置HttpClient,指定需要附加Token的API地址前缀 builder.Services.AddHttpClient("MyApiClient", client => client.BaseAddress = new Uri("https://api.test.com")) .AddHttpMessageHandler(sp => { var handler = sp.GetRequiredService<BaseAddressAuthorizationMessageHandler>(); handler.AuthorizedUrlPrefixes.Add("https://api.test.com"); return handler; }); // 注册Scoped的HttpClient实例 builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("MyApiClient"));
三、修正API调用代码的HttpClient使用
避免重复创建HttpClient实例,直接注入DI容器中注册的Scoped客户端:
private readonly HttpClient _httpClient; // 构造函数注入HttpClient public YourService(HttpClient httpClient) { _httpClient = httpClient; } public async Task<User> GetUser() { var url = "/account/info"; var user = await GetAsync<User>(url); return user; } private async Task<T> GetAsync<T>(string url) { if (string.IsNullOrWhiteSpace(url)) return default; // 直接使用注入的HttpClient var result = await _httpClient.GetAsync(url); if (!result.IsSuccessStatusCode) throw new Exception($"My API GET call failed. URL: {url}, Status: {result.StatusCode}"); var json = await result.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); }
四、验证Token是否附加的方法
- 浏览器开发者工具验证:打开F12开发者工具,切换到“网络”标签,发起API请求后查看请求头,确认存在
Authorization: Bearer {token} - 代码内调试验证:在API调用前添加代码检查请求头:
var authHeader = _httpClient.DefaultRequestHeaders.Authorization; Console.WriteLine($"Authorization Header: {authHeader?.Scheme} {authHeader?.Parameter}"); - 自定义处理器日志验证:添加日志处理器打印请求头:
public class LoggingHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { Console.WriteLine($"Request Headers: {string.Join(", ", request.Headers.Select(h => $"{h.Key}: {string.Join(", ", h.Value)}"))}"); return await base.SendAsync(request, cancellationToken); } } // 在Program.cs的HttpClient配置中添加该处理器 builder.Services.AddHttpClient("MyApiClient", client => client.BaseAddress = new Uri("https://api.test.com")) .AddHttpMessageHandler<LoggingHandler>() .AddHttpMessageHandler(sp => { var handler = sp.GetRequiredService<BaseAddressAuthorizationMessageHandler>(); handler.AuthorizedUrlPrefixes.Add("https://api.test.com"); return handler; });
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

