.NET/Angular中CORS仅允许GET请求,PUT请求报错如何解决?
Angular 服务类代码
import { Injectable } from "@angular/core"; import { RectangleCoordinates } from "../models/interfaces/RectangleCoordinates"; import { HttpClient } from "@angular/common/http"; import { Observable } from "rxjs"; @Injectable({ providedIn: "root", }) export class RectangleService { readonly RECTANGLE_API = "https://localhost:7192/api/Rectangle"; constructor(private http: HttpClient) {} getRectangleCoordinates(): Observable<RectangleCoordinates> { return this.http.get<RectangleCoordinates>(this.RECTANGLE_API); } updateRectangleCoordinates(rectangleCoords: RectangleCoordinates) { this.http.put(this.RECTANGLE_API, rectangleCoords).subscribe(); } }
ASP.NET 6 Web API CORS 配置代码
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; var builder = WebApplication.CreateBuilder(args); builder.Services.AddCors(options => { options.AddPolicy(name: MyAllowSpecificOrigins, policy => { policy.WithOrigins("http://localhost:4200"); }); }); .... app.UseCors(MyAllowSpecificOrigins);
错误信息
Access to XMLHttpRequest at 'https://localhost:7192/api/Rectangle' from origin 'http://localhost:4200' has been blocked by CORS policy: Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.
为何会出现这种情况?我似乎已正确配置CORS,为何仅GET请求可用?
原因是你的CORS策略仅指定了允许的请求源,但未显式允许PUT这类非简单HTTP方法。
在CORS规则中,GET、HEAD、POST(仅特定Content-Type)属于「简单请求」,浏览器不会发送预检(OPTIONS)请求;而PUT、DELETE这类方法,或携带自定义头、非标准Content-Type的请求,会触发浏览器发送预检请求,询问服务器是否允许该方法。你的当前配置只开放了请求源,ASP.NET Core默认CORS策略不会自动允许PUT这类非简单方法,导致预检返回的Access-Control-Allow-Methods中没有PUT,浏览器因此拦截请求。
修复方法
修改CORS策略配置,通过WithMethods显式允许需要的HTTP方法:
builder.Services.AddCors(options => { options.AddPolicy(name: MyAllowSpecificOrigins, policy => { policy.WithOrigins("http://localhost:4200") .WithMethods("GET", "PUT"); // 显式开放需要的方法 }); });
如果需要开放所有常用HTTP方法,也可以用.AllowAnyMethod(),但建议仅开放实际需要的方法以保障安全:
policy.WithOrigins("http://localhost:4200") .AllowAnyMethod();
另外,Angular的HttpClient默认发送application/json类型的请求,这类Content-Type不属于简单请求范畴,还需要开放对应请求头。可以添加.WithHeaders("Content-Type")指定允许的头,或用.AllowAnyHeader()开放所有头:
policy.WithOrigins("http://localhost:4200") .WithMethods("GET", "PUT") .WithHeaders("Content-Type");
内容的提问来源于stack exchange,提问作者Dronius

