#c# #asp.net-core #blazor-server-side
#c# #asp.net-core #blazor-на стороне сервера
Вопрос:
У меня есть проект .NET Core, в котором размещены WebAPI и серверное приложение Blazor. Приложение использует аутентификацию и авторизацию по умолчанию через an IdentityDbContext
и использует значение по умолчанию AuthenticationStateProvider
для Blazor. Поскольку я хочу, чтобы это приложение в какой-то момент в будущем могло перейти на клиентский Blazor, я сохранил логику на стороне сервера в API и вызывал ее, через HttpClient
которую я вручную ввел при запуске с помощью services.AddScoped<HttpClient>();
Проблема, с которой я сталкиваюсь, заключается в том, что пользовательские утверждения (т. Е. HttpContext.User
) Пусты в контроллерах API при выполнении вызовов API. Когда я говорю empty, HttpContext.User
объект не равен null, но все значения по умолчанию. Ожидаемое поведение заключается в том, что утверждения будут заполнены идентификационной информацией для вошедшего в систему пользователя.
Как ни странно, идентификационный файл cookie .AspNetCore.Identity.Application
присутствует в браузере, и все значения в AuthenticationStateProvider
сервисе соответствуют ожидаемым для вошедшего в систему пользователя. Для меня это указывает на то, что все настроено правильно с точки зрения аутентификации и идентификации и что проблема каким-то образом связана с HttpClient
контроллерами API.
Я пробовал:
- Установка
HttpOnly
значения false в конфигурации файлов cookie и извлечение файла cookie вручную через JsInterop для прикрепленияHttpClient
заголовков. Это не удалось из-за того, что вызовы API начинались до того, как JsInterop закончил захват файлов cookie. - Вручную вводим
HttpClient
в мойApiService
viaservices.AddHttpClient<IApiService, ApiService>();
- Копирование конфигурации запуска из рабочего проекта и перезапись моего
- Изменение порядка настроенных служб различными способами
- Несколько разных конфигураций файлов cookie
- Создание и использование пользовательского
AuthenticationStateProvider
- Следуя нескольким различным руководствам из официальной документации Microsoft
- Просмотр бесчисленных статей и вопросов Stackoverflow по аналогичным вопросам и проверка их предложений
Я также попытался вручную добавить файл 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;
});
Это решение не удалось, так как httpContextAccessor
при вызове делегата возвращалось значение null. Я понимаю, что нет HttpContext с подключением SignalR, однако я все равно ожидал бы HttpContext при первой загрузке приложения, обновлении страницы или вызове API. Я также попробовал нулевую версию проверки, где она будет выполняться только в том случае, если HttpContext
значение не равно нулю, но это также не удалось, поскольку HttpContext
никогда не было ненулевым.
Ответ №1:
Я смог решить эту проблему, передав токен аутентификации непосредственно в приложение Blazor, а затем добавив его HttpClient
таким образом.
Хотя мое приложение размещено в представлении MVC, я понимаю, что наиболее распространенный способ размещения приложения Blazor — это страница Razor. Для всех, кто еще сталкивается с этой проблемой, изменение страницы Razor будет следующим.
_Host.cshtml
@{
var token = HttpContext.Request.Cookies[".AspNetCore.Identity.Application"];
}
<app>
<component type="typeof(App)" param-Token="token" render-mode="ServerPrerendered" />
</app>
Решение MVC включает в себя получение токена на уровне контроллера и передачу его вниз. Код для этого следующий.
HomeController.cs
[HttpGet]
public IActionResult Index()
{
var token = HttpContext.Request.Cookies[".AspNetCore.Identity.Application"];
return View(token);
}
Index.cshtml
@model string
...
<app>
<component type="typeof(App)" param-Token="@Model" render-mode="ServerPrerendered" />
</app>
И, наконец, независимо от того, какой метод использовался выше, приложение Blazor будет изменено, чтобы добавить токен к HttpClient
следующему.
App.razor
@inject HttpClient HttpClient
...
@code
{
[Parameter] public string Token { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
HttpClient.DefaultRequestHeaders.Add("Cookie", $".AspNetCore.Identity.Application={Token}");
}
}