Ionic 7预检请求未通过CORS检查问题求助(Angular环境)
问题详情
使用Ionic 7(基于Angular)调用登录接口时触发CORS相关错误,前端代码如下:
this.http.post(this.endpoint + "api/auth/signin", {"username": handle, "password": password}).subscribe(r => { // @ts-ignore if (r["status"] === "authorized") { localStorage.setItem("status", "signed_in") // @ts-ignore localStorage.setItem("token", r["token"]) } })
收到的错误信息:
signin:1 Access to XMLHttpRequest at 'apiurl' from origin 'http://localhost:8100' 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.
signin:1 Access to XMLHttpRequest at 'apiurl' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
后端已配置测试用CORS响应头(PHP):
header('HTTP/1.1 200 OK') header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: *'); header('Access-Control-Allow-Headers: *');
特殊情况:浏览器控制台直接用XMLHttpRequest调用该接口可成功,但Ionic框架内调用失败。
解决方法
1. 处理OPTIONS预检请求
浏览器发送POST这类非简单请求时,会先发送OPTIONS预检请求。你的后端代码可能未单独处理该请求,导致响应不符合CORS要求。修改后端PHP代码:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header('HTTP/1.1 200 OK'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type, Authorization'); exit(); // 预检请求无需返回业务内容,直接终止执行 } // 正常POST请求处理逻辑 header('Access-Control-Allow-Origin: *'); // 后续业务代码...
注:Ionic的Angular HttpClient会自动携带Content-Type: application/json等头,触发预检请求;而你在控制台手动写的XHR可能未带这些头,属于简单请求,因此不会触发预检,所以能成功。
2. 校验请求URL完整性
检查this.endpoint的值是否为完整的绝对路径(需包含http://或https://)。如果是相对路径,Ionic会将其拼接到当前页面的origin(http://localhost:8100)后,导致请求地址错误,进而触发CORS问题。
3. 配置Ionic代理(开发环境临时方案)
若后端暂时无法修改,可通过Ionic代理绕过CORS限制:
- 在项目根目录创建
proxy.conf.json:
{ "/api": { "target": "https://你的真实API地址", "secure": false, "changeOrigin": true, "pathRewrite": { "^/api": "/api" } } }
- 修改
angular.json,在architect -> serve -> options中添加:
"proxyConfig": "proxy.conf.json"
- 调整前端请求代码,将
this.endpoint替换为/api:
this.http.post("/api/auth/signin", {"username": handle, "password": password})
重启Ionic服务后,请求会通过代理转发,避免CORS错误。
4. 明确指定允许的请求头
部分浏览器对Access-Control-Allow-Headers: *的支持存在差异,若请求携带自定义头,需在后端明确列出这些头,而非仅使用通配符。
内容的提问来源于stack exchange,提问作者devsimsek

