.Net Core 2.2 阻止CORS预检请求,Angular调用加拿大邮政API如何解决?
问题根源
CORS是目标资源所在服务的跨域限制规则,你当前前端直接请求加拿大邮政的公开API,跨域限制由加拿大邮政的服务控制,你在自己.NET后端配置的CORS规则仅对你自己后端提供的接口生效,完全解决不了第三方API的跨域问题。
你之前禁用浏览器安全可正常请求,是因为绕过了浏览器自带的CORS校验逻辑,生产环境不可能要求用户关闭浏览器安全,所以该方案不可用。
另外你前端代码中额外添加的Access-Control-Allow-Origin、Access-Control-Allow-Methods属于响应头字段,不应该在前端请求头中携带,额外添加这些字段反而会增加预检请求的校验项,加剧问题。
解决方案
使用后端代理模式,流程如下:
- 前端放弃直接调用加拿大邮政API,改为请求你自己的.NET后端接口
- 后端新增一个转发接口,接收前端传递的参数后,在服务端发起对加拿大邮政API的请求,服务端请求不存在浏览器CORS限制
- 后端拿到加拿大邮政返回的结果后,再返回给前端
前端代码修改
删除请求头中CORS相关的响应头字段,修改请求地址为自己后端的接口:
const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', // 传给自己后端用JSON更方便处理,也可直接传XML 'Accept': 'application/json', 'Accept-language': 'en-CA', }), responseType: 'text' as 'json' }; // 组装参数传给后端 var postData = { weight:5, originPostalCode:'M5V0G1', destPostalCode:'M4R1L8' } // 请求自己的后端接口 this.http.post('/api/CanadaPost/GetRate', postData, httpOptions) .subscribe( result => { console.log(result); }, error => console.log('There was an error: ', error) );
后端修改配置
首先在Startup.cs的ConfigureServices方法中注册HttpClient:
services.AddHttpClient();
后端新增转发接口示例
using Microsoft.AspNetCore.Mvc; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; [Route("api/[controller]")] [ApiController] public class CanadaPostController : ControllerBase { private readonly IHttpClientFactory _httpClientFactory; public CanadaPostController(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } [HttpPost("GetRate")] public async Task<IActionResult> GetRate([FromBody] RateRequest request) { var client = _httpClientFactory.CreateClient(); // 组装加拿大邮政要求的XML请求体 var xmlContent = $@"<mailing-scenario xmlns=""https://www.canadapost.ca/ws/ship/rate-v4""> <customer-number>0009669089</customer-number> <parcel-characteristics> <weight>{request.Weight} </weight> </parcel-characteristics> <origin-postal-code>{request.OriginPostalCode}</origin-postal-code> <destination> <domestic> <postal-code>{request.DestPostalCode}</postal-code> </domestic> </destination> </mailing-scenario>"; // 设置符合加拿大邮政要求的请求头 var content = new StringContent(xmlContent, Encoding.UTF8, "application/vnd.cpc.ship.rate-v4+xml"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.cpc.ship.rate-v4+xml")); // 建议将鉴权密钥放到配置文件中,不要硬编码 client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "YTUxZGQ1MWY2YjJhNjE4ODowODgzOThiZTUxY2Y4Y2RjZTIzM34"); client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("en-CA")); // 服务端发起请求,无CORS限制 var response = await client.PostAsync("https://soa-gw.canadapost.ca/rs/ship/price", content); if (response.IsSuccessStatusCode) { var result = await response.Content.ReadAsStringAsync(); // 可自行解析XML转成JSON返回给前端,也可直接返回XML内容 return Ok(result); } return StatusCode((int)response.StatusCode, await response.Content.ReadAsStringAsync()); } } // 前端传参接收类 public class RateRequest { public decimal Weight { get; set; } public string OriginPostalCode { get; set; } public string DestPostalCode { get; set; } }
你现有的Startup.cs的CORS配置无需修改,本身就可以支持前端调用你自己的后端接口。
内容的提问来源于stack exchange,提问作者nightwolf555
相关产品推荐
相关产品推荐

