При попытке загрузить данные в формате 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 данными для аутентификации на рабочем сервере и как это исправить?


Ответы (0 шт):