Blazor Server(.NET6)调用FCM API多次请求报401未授权问题排查
问题
我正在开发基于.NET 6的Blazor Server应用,需要通过Google Cloud Messaging(FCM)API发送通知。首次HTTP调用正常,但第二次调用时收到“401 Unauthorized”错误。使用Postman调用相同密钥可多次请求无问题,请问该问题的原因是什么?如何解决以实现无需重启页面即可多次调用?
发送通知的函数代码
private async Task SendNotification() { var request = new HttpRequestMessage(HttpMethod.Post, "https://fcm.googleapis.com/fcm/send"); http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", key); string mensajeJSON = $@"{{ ""data"": {{ ""WX_PUSH_EXT_VERSION"":""1.0"", ""WX_PROP_TITRE"":""{NuevosDatos.Titulo}"", ""WX_PROP_MESSAGE"":""{NuevosDatos.Msg}"", ""WX_PROP_PRIORITE"":4, ""WX_PROP_ACTIVEAPPLICATION"":true, ""title"" : ""{NuevosDatos.Titulo}"", ""body"" : ""{NuevosDatos.Msg}"", ""priority"" : ""high"" }}, ""to"": ""/topics/{selelectedId.Name}"" }}"; request.Content = new StringContent(mensajeJSON, Encoding.UTF8, "application/json"); var response = await http.SendAsync(request); response.EnsureSuccessStatusCode(); await response.Content.ReadAsStringAsync(); //NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true); }
表单提交代码(Syncfusion组件)
<EditForm Model="NuevosDatos" OnValidSubmit="@EnviarDatos" OnInvalidSubmit="@MostrarMsgError"> <DataAnnotationsValidator /> <ValidationSummary /> <div class="p-4 rounded-lg shadow-md max-w-md mx-auto"> <div class="mb-4"> <label class="block text-gray-700 font-bold mb-2">Titulo</label> <SfTextBox Placeholder="Introducir Titulo" @bind-Value="@NuevosDatos.Titulo"></SfTextBox> </div> <div class="mb-4"> <label class="block text-gray-700 font-bold mb-2">Mensaje</label> <SfTextBox Placeholder="Introducir mensaje" Multiline="true" @bind-Value="@NuevosDatos.Msg"></SfTextBox> </div> <div class="mb-4"> <label class="block text-gray-700 font-bold mb-2">Elige un tema</label> <InputSelect class="w-40" @bind-Value="NuevosDatos.TopicId"> <option disabled selected>Elige</option> @foreach (var topic in listaTopics) { <option value="@topic.Id">@topic.Name</option> } </InputSelect> </div> <SfToast @ref="ToastObj" CssClass="@toastClass" Content="@toastContent" TimeOut="@toastDuration"> <ToastPosition X="Right" Y="Top"></ToastPosition> </SfToast> <div class="flex justify-end"> <SfButton type="submit" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Submit</SfButton> </div> </div> </EditForm>
原因分析与解决方案
原因
问题出在你将FCM的授权头(Authorization)添加到了**HttpClient的全局默认请求头(DefaultRequestHeaders)**中,而非当前请求的HttpRequestMessage专属头里:
- 如果HttpClient是复用的(比如Scoped/单例注入),第一次调用时成功添加头,第二次调用
TryAddWithoutValidation会因为头已存在而跳过添加。 - Blazor Server的组件生命周期和HttpClient的连接复用机制可能导致全局头出现异常(比如头被意外覆盖、失效),从而触发FCM的401校验。
- 全局添加请求头违反了请求隔离原则,容易引发跨请求的头污染问题。
解决方案
修改SendNotification函数,将授权头添加到当前请求的HttpRequestMessage Headers中,而非HttpClient的全局默认头:
private async Task SendNotification() { var request = new HttpRequestMessage(HttpMethod.Post, "https://fcm.googleapis.com/fcm/send"); // 把授权头添加到当前请求的Headers中,而非HttpClient全局头 request.Headers.TryAddWithoutValidation("Authorization", key); string mensajeJSON = $@"{{ ""data"": {{ ""WX_PUSH_EXT_VERSION"":""1.0"", ""WX_PROP_TITRE"":""{NuevosDatos.Titulo}"", ""WX_PROP_MESSAGE"":""{NuevosDatos.Msg}"", ""WX_PROP_PRIORITE"":4, ""WX_PROP_ACTIVEAPPLICATION"":true, ""title"" : ""{NuevosDatos.Titulo}"", ""body"" : ""{NuevosDatos.Msg}"", ""priority"" : ""high"" }}, ""to"": ""/topics/{selelectedId.Name}"" }}"; request.Content = new StringContent(mensajeJSON, Encoding.UTF8, "application/json"); var response = await http.SendAsync(request); response.EnsureSuccessStatusCode(); await response.Content.ReadAsStringAsync(); }
额外检查项
- 确认你的
key格式符合FCM要求,必须是"key=AAAAXXX..."的形式(前缀key=不能省略)。 - 确保HttpClient的生命周期配置合理:Blazor Server中推荐使用Scoped或Transient生命周期的HttpClient,避免单例带来的状态共享问题。
内容的提问来源于stack exchange,提问作者Gegob
相关产品推荐
相关产品推荐

