C# 从服务器端Blazor应用程序调用API时,用户声明始终为空
我有一个.NET核心项目,它托管一个WebAPI和一个服务器端Blazor应用程序。应用程序通过C# 从服务器端Blazor应用程序调用API时,用户声明始终为空,c#,asp.net-core,blazor-server-side,C#,Asp.net Core,Blazor Server Side,我有一个.NET核心项目,它托管一个WebAPI和一个服务器端Blazor应用程序。应用程序通过IdentityDbContext使用默认身份验证和授权,并为Blazor使用默认的AuthenticationStateProvider。由于我希望这个应用在将来某个时候可能会移动到客户端Blazor,我一直在API中保留服务器端逻辑,并通过HttpClient调用它,我在启动时使用services.AddScoped()手动注入了它 我遇到的问题是,在调用API时,用户声明(即HttpContex
IdentityDbContext
使用默认身份验证和授权,并为Blazor使用默认的AuthenticationStateProvider
。由于我希望这个应用在将来某个时候可能会移动到客户端Blazor,我一直在API中保留服务器端逻辑,并通过HttpClient
调用它,我在启动时使用services.AddScoped()手动注入了它代码>
我遇到的问题是,在调用API时,用户声明(即HttpContext.User
)在API控制器中为空。当我说空时,HttpContext.User
对象不是空的,但是所有的值都是默认值。预期的行为是使用登录用户的身份信息填充声明
奇怪的是,浏览器中出现了identity cookie.AspNetCore.identity.Application
,并且AuthenticationStateProvider
服务中的值与登录用户的预期值一致。对我来说,这表明在身份验证和标识方面,所有配置都是正确的,并且问题与HttpClient
或Api控制器有关
我试过:
- 在cookie配置中将
HttpOnly
设置为false,并通过JSInterop手动检索cookie以附加HttpClient
头。这失败了,因为API调用在JSInterop抓取完cookie之前就开始了
- 通过
services.AddHttpClient()将HttpClient
手动注入myApiService
代码>
- 从工作项目复制启动配置并覆盖我的项目
- 以各种不同的方式更改已配置服务的顺序
- 几种不同的cookie配置
- 创建和使用自定义
AuthenticationStateProvider
- 遵循Microsoft官方文档中的几个不同指南
- 回顾无数关于类似问题的文章和问题,尝试他们的建议
我还尝试通过以下方式将身份验证cookie手动添加到HttpClient
:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<HttpClient>(s =>
{
var httpContextAccessor = s.GetRequiredService<IHttpContextAccessor>();
string authToken = httpContextAccessor.HttpContext.Request.Cookies[".AspNetCore.Identity.Application"];
var client = new HttpClient(new HttpClientHandler
{
UseCookies = false
});
if (authToken != null)
{
client.DefaultRequestHeaders.Add("Cookie", $".AspNetCore.Identity.Application={authToken}");
}
var request = httpContextAccessor.HttpContext.Request;
client.BaseAddress = new Uri($"{request.Scheme}://{request.Host}/");
return client;
});
services.AddSingleton();
services.AddScoped(s=>
{
var httpContextAccessor=s.GetRequiredService();
字符串authToken=httpContextAccessor.HttpContext.Request.Cookies[“.AspNetCore.Identity.Application”];
var client=新的HttpClient(新的HttpClientHandler
{
UseCookies=false
});
if(authToken!=null)
{
client.DefaultRequestHeaders.Add(“Cookie”,$”.AspNetCore.Identity.Application={authToken});
}
var request=httpContextAccessor.HttpContext.request;
client.BaseAddress=新Uri($“{request.Scheme}://{request.Host}/”;
返回客户;
});
此解决方案失败,因为调用委托时httpContextAccessor
返回null。我知道没有HttpContext与信号器连接,但是,当应用程序首次加载、页面刷新或进行API调用时,我仍然希望有HttpContext。我还尝试了一个空检查版本,只有当HttpContext
为非空时,它才会继续,但也失败了,因为HttpContext
从来都不是非空的。我能够通过将身份验证令牌直接传递到Blazor应用程序,然后以这种方式将其添加到HttpClient
虽然我的应用程序托管在MVC视图中,但我知道托管Blazor应用程序最常见的方式是通过Razor页面。对于其他遇到此问题的用户,Razor页面修改如下
\u Host.cshtml
@{
var token = HttpContext.Request.Cookies[".AspNetCore.Identity.Application"];
}
<app>
<component type="typeof(App)" param-Token="token" render-mode="ServerPrerendered" />
</app>
@model string
...
<app>
<component type="typeof(App)" param-Token="@Model" render-mode="ServerPrerendered" />
</app>
Index.cshtml
@{
var token = HttpContext.Request.Cookies[".AspNetCore.Identity.Application"];
}
<app>
<component type="typeof(App)" param-Token="token" render-mode="ServerPrerendered" />
</app>
@model string
...
<app>
<component type="typeof(App)" param-Token="@Model" render-mode="ServerPrerendered" />
</app>