При попытке загрузить данные в формате JSON на сервер выдает ошибку - 401 Unauthorized
Проект asp.net core 3.1, mvc.
При попытке передать данные в формате JSON на сервер для записи в базу данных, с помощью POST-запроса через API-контроллер из вне, выдает ошибку:
error: [object Object] status: error er:Unauthorized
- 401 Unauthorized
При этом авторизацию пользователь прошел. Заголовки запроса на передачу:
scheme http
host 195.ххххххх
filename /CollectVoters/api/FileApi/uploadDataFromFile
Адрес 195.ххххххх:80
Состояние 401 Unauthorized
Версия HTTP/1.1
Передано 1,07 МБ (размер 0 б)
Политика Referrerstrict-origin-when-cross-origin
Заголовки ответа
Date Thu, 05 Aug 2021 13:49:35 GMT
Location http://195.xxxxxxx/CollectVoters/Account/login?ReturnUrl=%2FCollectVoters%2Fapi%2FFileApi%2FuploadDataFromFile
Server Microsoft-IIS/10.0
Transfer-Encoding
chunked
X-Powered-By
ASP.NET
Заголовки запроса:
Accept application/json
Accept-Encoding
gzip, deflate
Accept-Language ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Connection
keep-alive
Content-Length
1119205
Content-Type
application/json
Host
195.хххххххх
Origin
http://195.ххххххх
Referer
http://195.ххххххх/collectvoters/UploadFiles
RequestVerificationToken
CfDJ8E_6DbN7jdpPgMFyLYN6J0O6ZYgVLlEdaT4gqM17s2tmHcWvkBaOPwi-...
User-Agent Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0
X-Requested-With XMLHttpRequest
Сам контроллер с методом:
[Route("api/[controller]")]
[ApiController]
[Produces("application/json")]
[Authorize(Roles = "admin, user")]
public class FileApiController : ControllerBase
{
private readonly ILogger<FileApiController> _logger;
private readonly VoterCollectorContext _context;
public FileApiController(VoterCollectorContext context, ILogger<FileApiController> logger)
{
_context = context;
_logger = logger;
}
[HttpPost("uploadDataFromFile")]
public async Task<IActionResult> UploadDataFromFile([FromBody] FriendDTO[] friendsDTO)
{
ServiceUser serviceUser = new ServiceUser(_context);
List<FileUploadDTO> notUploadRecords = new List<FileUploadDTO>();
User userSave = _context.User.Where(u => u.UserName.Equals(User.Identity.Name)).FirstOrDefault();
List<Groupu> groupsUser = serviceUser.GetGroupsUser(User.Identity.Name);
ServiceFriends serviceFriends = new ServiceFriends();
//Regex regexTelephone = new Regex(@"(^[+]{0,1}[0-9]{11})");
Regex regexTelephone = new Regex(@"^\+?\d{11}$");
for (int i=1; i< friendsDTO.Length; i++)
{
try
{
//...
_context.Add(newFriend);
}
catch {
//...
}
}
try
{
await _context.SaveChangesAsync();
return Ok(notUploadRecords.ToArray());
}
catch (Exception ex)
{
int i = 0;
_logger.LogError(ex.ToString()); // .Exception(ex).Message("Ошибка записи в БД").Write();
notUploadRecords = friendsDTO.Select(x => new FileUploadDTO
{
//...
notUploadRecords.RemoveAt(0);
return Ok(notUploadRecords.ToArray());
}
}
}
На тесте (IIS Express) все работало норм. Попробовал создал в mvc-контроллере аналогичный метод для записи в БД из JSON c фронта:
[Authorize(Roles = "admin, user")]
public class UploadFilesController : Controller
{
private readonly ILogger<UploadFilesController> _logger;
private readonly VoterCollectorContext _context;
public UploadFilesController(VoterCollectorContext context, ILogger<UploadFilesController> logger)
{
_logger = logger;
_context = context;
}
public IActionResult Index()
{
try
{
return View();
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
return View();
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UploadDataFromFile([FromBody] FriendDTO[] friendsDTO)
{
ServiceUser serviceUser = new ServiceUser(_context);
List<FileUploadDTO> notUploadRecords = new List<FileUploadDTO>();
User userSave = _context.User.Where(u => u.UserName.Equals(User.Identity.Name)).FirstOrDefault();
List<Groupu> groupsUser = serviceUser.GetGroupsUser(User.Identity.Name);
ServiceFriends serviceFriends = new ServiceFriends();
Regex regexTelephone = new Regex(@"^\+?\d{11}$");
for (int i = 1; i < friendsDTO.Length; i++)
{
try
{
friendsDTO[i].UserId = userSave.IdUser;
//Friend newFriend = CreateFreand(friendsDTO[i]);
Friend newFriend = serviceFriends.CreateFreand(friendsDTO[i], regexTelephone, userSave, groupsUser);
_context.Add(newFriend);
}
catch
{
notUploadRecords.Add(new FileUploadDTO
{
NumberStrFile = Convert.ToString(i + 1),
FamilyName = friendsDTO[i].FamilyName,
Name = friendsDTO[i].Name,
PatronymicName = friendsDTO[i].PatronymicName,
DateBirth = friendsDTO[i].DateBirth,
CityName = friendsDTO[i].CityName,
Street = friendsDTO[i].Street,
House = friendsDTO[i].House
});
}
}
try
{
await _context.SaveChangesAsync();
return Ok(notUploadRecords.ToArray());
}
catch (Exception ex)
{
int i = 0;
_logger.LogError(ex.ToString()); // .Exception(ex).Message("Ошибка записи в БД").Write();
notUploadRecords = friendsDTO.Select(x => new FileUploadDTO
{
NumberStrFile = Convert.ToString(i++),
FamilyName = x.FamilyName,
Name = x.Name,
PatronymicName = x.PatronymicName,
DateBirth = x.DateBirth,
CityName = x.CityName,
Street = x.Street,
House = x.House
}).ToList();
notUploadRecords.RemoveAt(0);
return Ok(notUploadRecords.ToArray());
}
}
}
Выдает аналогичную ошибку:
POST
scheme http
host 195.xxx.xxx.40
filename /CollectVoters/UploadFiles/uploadDataFromFile
Адрес 195.xxx.xxx.40:80
POST
http://195.xxx.xxx.40/CollectVoters/UploadFiles/uploadDataFromFile
Состояние 401 Unauthorized
ВерсияHTTP/1.1
Передано8,65 КБ (размер 0 б)
Политика Referrerstrict-origin-when-cross-origin
Заголовки ответа
Date Thu, 05 Aug 2021 15:42:28 GMT
Location http://195.xxx.xxx.40/CollectVoters/Account/login?ReturnUrl=/CollectVoters/UploadFiles/uploadDataFromFile
Server Microsoft-IIS/10.0
Transfer-Encoding chunked
X-Powered-By ASP.NET
Заголовки запроса:
Accept application/json
Accept-Encoding gzip, deflate
Accept-Language ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Connection keep-alive
Content-Length 7872
Content-Type application/json
Host 195.xxx.xxx.40
Origin
http://195.xxx.xxx.40
Referer
http://195.xxx.xxx.40/collectvoters/UploadFiles
RequestVerificationToken
CfDJ8E_6DbN7jdpPgMFyLYN6J0NO5OeznJJCWrd-16Q4mZBqbPlanDq-...
User-Agent
Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0
X-Requested-With
XMLHttpRequest
И ещё в конце выдает следующее:
Ошибка синтаксического анализа XML: корневой элемент не найден Адрес: http://195.xxx.xxx.40/CollectVoters/UploadFiles/uploadDataFromFile Строка 1, символ 1:
Есть важный момент - при данном конкретном запросе на загрузку вообще отсутствуют cookie, поэтому судя по всему и не происходит аутентификация.
При всех остальных запросах cookie есть, они выглядят следующим образом:
.AspNetCore.Mvc.CookieTempDataProvider {…} expires "1970-01-01T00:00:00.000Z" httpOnly true path "/collectvoters" samesite "Lax" value ""
{ ".AspNetCore.Antiforgery.hCiIJBAN4bs": "CfDJ8E_6DbN7jdpPgMFyLYN6J0OzXNlVDlQXAAGQLHvQZT40fBZ3ATVNxQ4 ...", ".AspNetCore.Cookies": "CfDJ8E_6DbN7jdpPgMFyLYN6J0MJ8zAjmvH8ot7AsdqAusmnYZIzGMuRKrb ..." }
{ ".AspNetCore.Antiforgery.hCiIJBAN4bs": "CfDJ8E_6DbN7jdpPgMFyLYN6J0OzXNlVDlQXAAGQLHvQZT40fBZ3ATVNxQ4 rFp2UhszNZ07_Nlq-rtllU49i1z-...", ".AspNetCore.Cookies": "CfDJ8E_6DbN7jdpPgMFyLYN6J0MJ8zAjmvH8ot7AsdqAusmnYZIzGMuRKrb xnXIO9IyW4kWGbnlOnRY6qs4xEF0ECVmod-VHVqQz6I-..." }
В настройках Startup.cs у меня прописана аутентификация по cookie:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//Add
// установка конфигурации подключения
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => //CookieAuthenticationOptions
{
options.LoginPath = new Microsoft.AspNetCore.Http.PathString("/Account/login");
options.AccessDeniedPath = new Microsoft.AspNetCore.Http.PathString("/Account/login");
});
//Add
services.AddDbContext<VoterCollectorContext>();
services.AddControllersWithViews();
//Add
services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 8;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
options.Lockout.MaxFailedAccessAttempts = 7;
options.Lockout.AllowedForNewUsers = true;
// User settings.
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
});
//Add
services.AddControllers().AddNewtonsoftJson();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
//Add
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
//Add
//Метод app.UseAuthentication() встраивает в конвейер компонент AuthenticationMiddleware, который управляет аутентификацией.
app.UseAuthentication();
приложения.
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
//app.UseCors();
}
}
При выполнении данного запроса на IISExpress cookie уходят с запросом, как и положено - те же самые, что были получены при авторизации пользователя. Пример c cookies получаемыми при авторизации переходе на целевую страницу и отправки запроса c JSON на загрузку IISExpress:
Request Login .AspNetCore.Antiforgery.sTgLludoNYM CfDJ8OpqRmzr-59AkS4cNHyMCT1R_ABDUkgfIXGSTnF_NT_clqr2xeAN46jxCce- E5szcj4QlNAC0lWdlymlUwYTf8htzXwBwkgjXALBJSpngbcvRbJv2VosgaZENiKP0I0E2QYK4GWi Hc5UbgzYbCDFF74 localhost
Response Login .AspNetCore.Cookies CfDJ8OpqRmzr-59AkS4cNHyMCT3YSd5slt2PnEQa3gIPJma_cq3M5KhdBFf8dLLM8GU4Xc8w7aKssJD00iXqIra6Re4k_0VXouZtCSnqGfDbTMavEVKI1WYc_Hgz5zAQOoRWRmvNyNP9TzXUTOkrfH0po0JrKiNTtAZr1ZCVswyVl4ifzaJD0MkN5CXPCAbgB6FkHvZDpfxfvuBtCH8Gejq1-U_eNHjr8ep0DQ49aRbDSzo79nvFCPMw0DMpxK9pZqaqxFHZSVU13nQym71V-IgiXyhB-gKkwnYmMpJ7anZ1DO7t4kmN38vEj532Wf2ZrHJLZ-IBPVYkwAHXmiQ42r9qBv8XRteMPmnUMBYIWTXnBBVy4VqXCRX1tikwXAsLUv_Ypz46roCWqbiwIqfhWBh0SmBP41GMxkDBvi5puOVi_tlI localhost
Request UploadFiles - страница с которой отправляется запрос на загрузку (на которой нажимается кнопка) .AspNetCore.Antiforgery.sTgLludoNYM CfDJ8OpqRmzr-59AkS4cNHyMCT1R_ABDUkgfIXGSTnF_NT_clqr2xeAN46jxCce-E5szcj4QlNAC0lWdlymlUwYTf8htzXwBwkgjXALBJSpngbcvRbJv2VosgaZENiKP0I0E2QYK4GWiHc5UbgzYbCDFF74 localhost .AspNetCore.Cookies CfDJ8OpqRmzr-59AkS4cNHyMCT3YSd5slt2PnEQa3gIPJma_cq3M5KhdBFf8dLLM8GU4Xc8w7aKssJD00iXqIra6Re4k_0VXouZtCSnqGfDbTMavEVKI1WYc_Hgz5zAQOoRWRmvNyNP9TzXUTOkrfH0po0JrKiNTtAZr1ZCVswyVl4ifzaJD0MkN5CXPCAbgB6FkHvZDpfxfvuBtCH8Gejq1-U_eNHjr8ep0DQ49aRbDSzo79nvFCPMw0DMpxK9pZqaqxFHZSVU13nQym71V-IgiXyhB-gKkwnYmMpJ7anZ1DO7t4kmN38vEj532Wf2ZrHJLZ-IBPVYkwAHXmiQ42r9qBv8XRteMPmnUMBYIWTXnBBVy4VqXCRX1tikwXAsLUv_Ypz46roCWqbiwIqfhWBh0SmBP41GMxkDBvi5puOVi_tlI localhost
Response UploadFiles - страница с которой отправляется запрос на загрузку (на которой нажимается кнопка) .AspNetCore.Mvc.CookieTempDataProvider localho
Request UploaDataFromdFile - отправка запроса на загрузку .AspNetCore.Antiforgery.sTgLludoNYM CfDJ8OpqRmzr-59AkS4cNHyMCT1R_ABDUkgfIXGSTnF_NT_clqr2xeAN46jxCce-E5szcj4QlNAC0lWdlymlUwYTf8htzXwBwkgjXALBJSpngbcvRbJv2VosgaZENiKP0I0E2QYK4GWiHc5UbgzYbCDFF74 localhost .AspNetCore.Cookies CfDJ8OpqRmzr-59AkS4cNHyMCT3YSd5slt2PnEQa3gIPJma_cq3M5KhdBFf8dLLM8GU4Xc8w7aKssJD00iXqIra6Re4k_0VXouZtCSnqGfDbTMavEVKI1WYc_Hgz5zAQOoRWRmvNyNP9TzXUTOkrfH0po0JrKiNTtAZr1ZCVswyVl4ifzaJD0MkN5CXPCAbgB6FkHvZDpfxfvuBtCH8Gejq1-U_eNHjr8ep0DQ49aRbDSzo79nvFCPMw0DMpxK9pZqaqxFHZSVU13nQym71V-IgiXyhB-gKkwnYmMpJ7anZ1DO7t4kmN38vEj532Wf2ZrHJLZ-IBPVYkwAHXmiQ42r9qBv8XRteMPmnUMBYIWTXnBBVy4VqXCRX1tikwXAsLUv_Ypz46roCWqbiwIqfhWBh0SmBP41GMxkDBvi5puOVi_tlI localhost
Response UploaDataFromdFile
Почему не уходят kookie c данными для аутентификации на рабочем сервере и как это исправить?