【问题标题】:CORS error from one component, but not others来自一个组件的 CORS 错误,但不是其他组件
【发布时间】:2020-04-01 06:31:20
【问题描述】:

我有一个带有 React 16 的 .NET Core 3.1.3 应用程序,当我在生产环境(Azure / Firebase)中调用 API 时,我从一个特定组件中收到了 CORS 错误。

在大多数应用程序中,一切正常,所有 axios 调用的基本 url 都设置在一个文件中,所有 post 请求都通过 rootHttp 类的一个方法。

    addItem(model, data){
      return axios.post(
          this.rootUrl + '/' + model, data, {headers: this.headers}
      );
    }
    //Posts new item to API

所有 API 调用似乎都运行良好,除了来自员工组件的 POST 调用:

export function addEmployee(employee, callback){
    employee = prepEmployeeValues(employee);
    return dispatch =>{
        http.addItem("employee", employee)
            .then(addedEmployee =>{
                dispatch(addEmployeeToState(addedEmployee.data));
                callback();
            });
    }
}
//Posts new employee to API

触发这两个错误:

Access to XMLHttpRequest at 'https://procmanagement.azurewebsites.net/api/3/employee' 
    from origin 'https://scheduleanddirection.firebaseapp.com' 
    has been blocked by CORS policy: No 'Access-Control-Allow-Origin' 
    header is present on the requested resource.

createError.js:16 Uncaught (in promise) Error: Network Error
    at e.exports (createError.js:16)
    at XMLHttpRequest.p.onerror (xhr.js:83)

请求标头与来自任何其他组件的成功 POST 调用相同。值得注意的是,来自 Employee 组件的 GET 返回一个空数组,并且最初应该返回一个包含 1 个 Employee 对象的数组,所有者是在注册帐户时添加的(在开发服务器中工作)。

后端应该在这里收到员工的帖子:

        [HttpPost]
        public async Task<IActionResult> AddEmployee(int userId, EmployeeForCreationDto employeeForCreation)
        {
            EmployeeIdIncrement employeeIdIncrement = await _repo.GetEmployeeIdForIncrement(userId);
            employeeIdIncrement.employeeId = employeeIdIncrement.employeeId + 1;

            var creator = await _userRepo.GetUser(userId);

            if (creator.Id != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
                return Unauthorized();

            var employee = _mapper.Map<Employee>(employeeForCreation);

            employee.User = creator;

            employee.EmployeeId = employeeIdIncrement.employeeId;

            _repo.Add(employee);

            if (await _repo.SaveAll())
            {
                var employeeToReturn = _mapper.Map<EmployeeForReturnDto>(employee);
                return CreatedAtRoute("GetEmployee", new {employeeId = employee.EmployeeId, userId = userId }, employeeToReturn);
            }

            throw new Exception("Creation of Employee failed on save");

        }

成功对应的例子:

发送:

export function addDepartment(department, callback){
    department = prepDepartmentValues(department);
    return dispatch =>{
        http.addItem("department", department)
            .then(addedDepartment =>{
                dispatch(addDepartmentToState(addedDepartment.data));
                callback();
            });
    }
}
//Posts new department to API

接收:

        [HttpPost]
        public async Task<IActionResult> AddDepartment(int userId, DepartmentForCreationDto departmentForCreation)
        {
            var creator = await _userRepo.GetUser(userId);

            if (creator.Id != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
                return Unauthorized();

            var department = _mapper.Map<Department>(departmentForCreation);

            department.User = creator;

            _repo.Add(department);

            if (await _repo.SaveAll())
            {
                var jobToReturn = _mapper.Map<DepartmentForCreationDto>(department);
                return CreatedAtRoute("GetDepartment", new {deptName = department.DeptName, userId = userId }, jobToReturn);
            }

            throw new Exception("Creation of Department failed on save");

        }

包括 Employee 组件在内的所有组件都可以在开发服务器中正常运行,而除 Employee 组件之外的所有组件都可以在生产环境中正常运行。

CORS 政策:

            services.AddCors(options =>
            {
                options.AddPolicy("ProdCors",
                    builder =>
                    {
                        builder.WithOrigins("https://scheduleanddirection.firebaseapp.com", "https://scheduleanddirection.web.app")
                            .AllowAnyMethod()
                            .AllowAnyHeader()
                            .AllowCredentials();
                    }
                );
            });

【问题讨论】:

  • 并非所有请求都需要 CORS,有些(如 GET)是“简单的”。参见例如developer.mozilla.org/en-US/docs/Web/HTTP/CORS.
  • 例如,来自其他组件的 PUT 是成功的,并且请求标头中的源 url 相同,传递的令牌也是如此
  • 请提供一个minimal reproducible example,其中包含两个最相似但行为不同的请求,然后显示您服务器的 CORS 配置。
  • 这很难重现,因为它只发生在生产环境中,但是如果你看上面,你会看到 addEmployee 函数,这是一个使用它上面的 addItem 辅助方法的操作, 并由 AddEmployee 控制器方法接收,但未成功给出所示的错误。 addDepartment 函数,它使用相同的 addItem 辅助方法成功,并由 AddDepartment 控制器方法接收。我在底部添加了 CORS 政策

标签: c# .net reactjs firebase azure


【解决方案1】:

所以经过深思熟虑,我发现实际上并不是 CORS 问题导致我出现该错误。

我用 Postman 检查了 API,发现出现内部服务器错误,然后将我的开发服务器 API 连接到生产数据库,我发现问题在于 MS SQL Server 与 SQLite 相比的工作方式.

开发服务器使用 SQLite。 MS SQL Server 在 SQLite 中遇到了两个问题:

  1. 在没有明确许可的情况下一次更新多条数据。已通过在我的连接字符串中添加“MultipleActiveResultSets=True”来解决此问题。

  2. 使用单个主键(与复合键相反)显式定义项目的主键。已通过完全删除 EmployeeIdForIncrement 模型并将 EmployeeIdForIncrement 添加为用户模型的属性来解决此问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-17
    • 2020-07-28
    • 2018-09-30
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多