У меня есть основной проект .NET с двумя слоями: слой API и слой пользовательского интерфейса, оба в одном решении. Уровень пользовательского интерфейса построен с помощью ASP.NET Core MVC, где контроллеры вызовут службы, а службы используют httpclient , сгенерированные NSWAG Studio для вызова конечных точек API. Он вручную читает файлы cookie из заголовков ответов и хранит их в словаре. Логика состоит в том, что если токен доступа JWT истекает, и я получаю несанкционированный ответ 401 , обработчик извлекает токен обновления из файлов cookie и отправляет его в API обновление . Это отлично работает около двух минут, но после этого сервер перестает отправлять заголовки Set-cookie в ответах API, и их значения становятся нулевыми.
У меня есть основной проект .NET с двумя слоями: слой API и слой пользовательского интерфейса, оба в одном решении. Уровень пользовательского интерфейса построен с помощью ASP.NET Core MVC, где контроллеры вызовут службы, а службы используют httpclient , сгенерированные NSWAG Studio для вызова конечных точек API. Он вручную читает файлы cookie из заголовков ответов и хранит их в словаре. Логика состоит в том, что если токен доступа JWT истекает, и я получаю несанкционированный ответ 401 , обработчик извлекает токен обновления из файлов cookie и отправляет его в API обновление . Это отлично работает около двух минут, но после этого сервер перестает отправлять заголовки Set-cookie в ответах API, и их значения становятся нулевыми.[code]public class ManualCookieHttpClient : DelegatingHandler { private readonly Dictionary _cookies; private readonly ILocalStorageService _localStorage; private readonly IConfiguration _configuration; private readonly IHttpClientFactory _httpClientFactory;
if (response.Headers.TryGetValues("Set-Cookie", out var setCookieHeaders)) { foreach(var cookie in setCookieHeaders) { Console.WriteLine(cookie); }
foreach (var setCookieHeader in setCookieHeaders) { var cookieParts = setCookieHeader.Split(';')[0].Split('='); if (cookieParts.Length == 2) { var name = cookieParts[0].Trim(); var value = cookieParts[1].Trim();
if (string.IsNullOrEmpty(value)) continue;
_cookies[name] = value; } } }
if (_cookies.ContainsKey("RefreshToken")) { var currentToken = _cookies["RefreshToken"]; } else { Console.WriteLine("there is no refreshToken in headers cookies"); } } catch (Exception e) { Debug.WriteLine($"Exception in ProcessResponseCookies: {e.Message}"); } }
if (string.IsNullOrEmpty(userName)) { throw new ApiException( message: "User is not authenticated", statusCode: 401, response: "User not authenticated", headers: null, innerException: null ); }
var refreshToken = _cookies.ContainsKey("refreshToken") ? _cookies["refreshToken"] : null;
if (string.IsNullOrEmpty(refreshToken)) { throw new ApiException( message: "Refresh Token does not exist", statusCode: 401, response: "Refresh token not found", headers: null, innerException: null ); }
var apiAddress = _configuration["ApiAddress"];
var client = _httpClientFactory.CreateClient("RefreshClient"); client.BaseAddress = new Uri(apiAddress!);
var refreshRequest = new HttpRequestMessage(HttpMethod.Post, "api/Account/refreshToken"); AddCookiesToRequest(refreshRequest);
var refreshTokenRequest = new RefreshTokenRequest { UserName = userName, RefreshToken = refreshToken }; refreshRequest.Content = JsonContent.Create(refreshTokenRequest);
var refreshResponse = await client.SendAsync(refreshRequest, cancellationToken);
if (refreshResponse.IsSuccessStatusCode) { string newRefreshToken = null!;
if (refreshResponse.Headers.TryGetValues("Set-Cookie", out var setCookieHeaders)) { foreach (var setCookieHeader in setCookieHeaders) { if (setCookieHeader.StartsWith("refreshToken=")) { var cookieParts = setCookieHeader.Split(';')[0].Split('=');
private string? GetUserNameFromToken() { //Get UserName From Token... } } [/code] my refreshtoken api, который устанавливает обновление cookie после его восстановления: [code][HttpPost("refreshToken")] public async Task RefreshToken([FromBody] RefreshTokenRequest request) { var authenticationResponse = await _authenticationService.RefreshTokenAsync(request.RefreshToken, request.UserName);
if (authenticationResponse == null) return Unauthorized();
return Ok(authenticationResponse); } < /code> DelegatingHandler[/code] Настройки в программе.[code]services.AddTransient();
services.AddHttpClient(c => { c.BaseAddress = new Uri(configuration.GetSection("ApiAddress").Value!); }) .AddHttpMessageHandler() .ConfigurePrimaryHttpMessageHandler(sp => { return new HttpClientHandler { UseCookies = false, AllowAutoRedirect = false }; }); < /code> I tried using SameSite = SameSiteMode.None[/code], но это не решило проблему. Из -за этого я сейчас вручную обрабатываю файлы cookie в моем делегировании и код .