【问题标题】:CORS issue with one POST request but not another一个 POST 请求但不是另一个 POST 请求的 CORS 问题
【发布时间】:2021-08-22 22:28:17
【问题描述】:

我查看了其他一些问题,但它们与我遇到的问题并不完全相同。我有一个在 localhost:5001 运行的服务器和一个在 localhost:8080 运行的 Vue 网站。当我执行 /inventory/login 发布请求时,我没有收到任何 CORS 问题,但是当我执行 /inventory/computers 请求时,我收到以下内容

Access to XMLHttpRequest at 'https://localhost:5001/inventory/computers' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我做错了什么?这是相关代码。

Startup.cs:

public void ConfigureServices(IServiceCollection services) {
  var connection = Configuration.GetConnectionString("Inventory");
  services.AddDbContextPool<InventoryContext>(options => options.UseSqlServer(connection));
  services.AddControllers().AddNewtonsoftJson(options =>
    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
    options.RequireHttpsMetadata = false;
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters() {
      ValidateIssuer = true,
      ValidateAudience = true,
      ValidAudience = Configuration["Jwt:Audience"],
      ValidIssuer = Configuration["Jwt:Issuer"],
      IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
    };
  });

  services.AddCors(options => {
    options.AddPolicy("AllowSpecificOrigin", builder => {
      builder.WithOrigins("localhost")
            .AllowAnyOrigin()
            .AllowAnyHeader()
            .AllowAnyMethod();
    });
  });
}

// 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();
  }

  app.UseHttpsRedirection();

  app.UseRouting();

  app.UseAuthentication();

  app.UseAuthorization();

  app.UseCors();

  app.UseEndpoints(endpoints => {
    endpoints.MapControllers();
  });
}

}

登录控制器:

[Route("inventory/[controller]")]
[ApiController]
[EnableCors("AllowSpecificOrigin")]
public class LoginController : ControllerBase {
public IConfiguration _configuration;
private readonly InventoryContext _context;

public LoginController(IConfiguration config, InventoryContext context) {
  _configuration = config;
  _context = context;
}

[HttpPost]
public async Task<IActionResult> Post(LoginRequest req) {
  if (req != null && req.Username != null && req.Password != null) {
    User user = await _context.Users.FirstOrDefaultAsync(u => u.Username == req.Username);

    if (user == null || !Crypto.VerifyHashedPassword(user.HashedPassword, req.Password)) {
      return BadRequest("Invalid username or password.");
    }

    var claims = new[] {
      new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]),
      new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
      new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
      new Claim("EmployeeID", user.EmployeeId.ToString()),
      new Claim("Username", user.Username),
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
    var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var token = new JwtSecurityToken(_configuration["Jwt:Issuer"], _configuration["Jwt:Audience"], claims, expires: DateTime.UtcNow.AddDays(1), signingCredentials: signIn);
    return Ok(new JwtSecurityTokenHandler().WriteToken(token));
  }
  else {
    return BadRequest();
  }
}

计算机控制器:

[Authorize]
  [Route("inventory/[controller]")]
  [ApiController]
  [EnableCors("AllowSpecificOrigin")]
  public class ComputersController : ControllerBase {
    private readonly InventoryContext _context;

    public ComputersController(InventoryContext context) {
        _context = context;
    }



    // POST: api/Computers
    // To protect from overposting attacks, enable the specific properties you want to bind to, for
    // more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
    [EnableCors("AllowSpecificOrigin")]
    [HttpPost]
    public async Task<ActionResult<Computer>> PostComputer(ComputerPostRequest req) {
      Item item = new Item("Computer");
      _context.Items.Add(item);
      await _context.SaveChangesAsync();

      Computer computer = new Computer(item.ItemId, req.SelectBankcardSerialNumber, req.ManufacturerSerialNumber, req.Model, req.Name, req.Value, req.EmployeeID, req.DateObtained);
      _context.Computers.Add(computer);

      if (!String.IsNullOrEmpty(req.Notes)) {
        Note note = new Note(computer.ComputerId, req.Notes, DateTime.Now);
        _context.Notes.Add(note);
      }

      await _context.SaveChangesAsync();

      return CreatedAtAction("GetComputer", new { id = computer.ComputerId }, computer);
    }

还有 Vue 代码:

登录.vue

async login() {
      if (this.isEmpty(this.username) || this.isEmpty(this.password)) {
        this.incorrect = true;
        console.log("Something's wrong");
        return false;
      }
      try {
        let res = await axios.post('https://localhost:5001/inventory/login', {
          username: this.username,
          password: this.password
        });
        this.$root.$authToken = "Bearer " + res.data;
      } catch (error) {
        console.log(error);
      }
    }

计算机.vue:

async upload() {
      if (this.isEmpty(this.sbSerialNum) || this.isEmpty(this.mSerialNum) || this.isEmpty(this.compModel) || this.isEmpty(this.compName) ||
      this.value === 0.0 || this.empID === 0 || this.isEmpty(this.dateObtained) || this.isEmpty(this.notes)) {
        this.incorrect = true;
        console.log("Something's wrong");
        return false;
      }
      try {
        const options = {
          headers: {'Authorization': this.$root.$authToken}
        };
        let res = await axios.post('https://localhost:5001/inventory/computers', {
          SelectBankcardSerialNumber: this.sbSerialNum,
          ManufacturerSerialNumber: this.mSerialNum,
          Name: this.compName,
          Model: this.compModel,
          Value: this.value,
          EmployeeID: this.empID,
          DateObtained: this.dateObtained,
          Notes: this.notes
        }, options);
        this.computerAdded = res.data;
      } catch (error) {
        console.log(error);
      }

【问题讨论】:

  • 在推荐的Middleware order中,对UseCors的调用应该放在UseRouting之后,UseAuthorization之前。

标签: vue.js asp.net-core .net-core vuejs2 cors


【解决方案1】:

您可以尝试将 AddCors 移动到 ConfigureServices 方法的顶部,仅用于测试我会使用它

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(o => o.AddPolicy("AllowSpecificOrigin", builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader();
            }));
.....

}

只有当它有效时,我才会尝试使用特定的来源。

您必须在 UseRouting 和 UseAutorization 之间放置 UseCors

app.UseRouting();
app.UseCors("AllowSpecificOrigin");      
app.UseAuthorization();

【讨论】:

  • 第二次编辑解决了我的问题!登录请求不需要授权,但 POST Computer 请求需要授权。它现在正在工作!
  • 很高兴能帮到你。请不要忘记接受答案
猜你喜欢
  • 1970-01-01
  • 2013-02-24
  • 2020-12-20
  • 2023-03-14
  • 2023-03-05
  • 1970-01-01
  • 2023-03-10
  • 2020-12-28
  • 1970-01-01
相关资源
最近更新 更多