JavaScript代码出现CORS错误而Postman不出现的原因及解决办法

JavaScript代码出现CORS错误而Postman不出现的原因及解决办法

技术背景

在前端开发中,当使用JavaScript进行跨域请求时,常常会遇到 "No 'Access-Control-Allow-Origin' header is present on the requested resource" 错误。这是由于浏览器的同源策略(Same-Origin Policy,SOP)和跨域资源共享(Cross-Origin Resource Sharing,CORS)机制导致的。同源策略是一种重要的安全机制,它限制了网页只能访问同源(协议、域名、端口都相同)的资源。而CORS则是一种允许浏览器进行跨域请求的机制,需要服务器端进行相应的配置。然而,使用Postman进行请求时,却不会出现这个错误,这是因为Postman不受同源策略的限制。

实现步骤

分析错误原因

  • 浏览器的同源策略:浏览器会检查请求的源(Origin)和目标资源的源是否相同。如果不同,且服务器没有设置 Access-Control-Allow-Origin 响应头,浏览器会阻止该请求,并抛出CORS错误。
  • Postman的特殊性:Postman是一个开发工具,它不遵循浏览器的同源策略,因此可以直接发送跨域请求。

解决跨域问题

不同后端语言的解决方案

  • PHP:在处理请求的PHP页面开头添加以下代码:
1
<?php header('Access-Control-Allow-Origin: *'); ?>
  • Node-RED:在 node-red/settings.js 文件中取消注释以下代码:
1
2
3
4
httpNodeCors: {
origin: "*",
methods: "GET,PUT,POST,DELETE"
},
  • Flask:首先安装 flask-cors
1
pip install -U flask-cors

然后在应用中引入 flask-cors 包:

1
2
3
4
5
6
7
8
9
from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
  • C# Web API:在 web.config 文件的 <system.webServer> 标签下添加以下代码:
1
2
3
4
5
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>

服务器配置

  • Nginx:在 nginx.conf 文件中添加以下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
location ~ ^/index\.php(/|$) {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
}
  • Apache:在 .htaccess 文件中添加以下配置:
1
2
3
Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"

其他解决办法

  • 临时禁用浏览器的同源策略:在Windows系统中,可以使用以下命令禁用Chrome的Web安全:
1
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
  • 检查网关超时设置:如果网关超时时间过短,而资源处理时间过长,也可能导致类似的错误。可以检查错误代码是否为504,如果是,则尝试增加网关超时时间。
  • 检查数据库表结构:确保远程数据库表和本地数据库表的结构一致,避免因表结构不同导致的CORS错误。
  • 更新ModSecurity设置:如果是 ModSecurity 阻止了请求,可以将请求编码为Base64或更新 ModSecurity 设置。
  • 更换浏览器:有时,不同的浏览器对CORS的处理方式可能不同,可以尝试更换浏览器来解决问题。

核心代码

jQuery的Ajax请求示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$.ajax({
url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
type: "POST", /* or type:"GET" or type:"PUT" */
dataType: "json",
data: {
},
success: function (result) {
console.log(result);
},
error: function () {
console.log("error");
}
});

Python的Flask应用示例

1
2
3
4
5
6
7
8
9
10
11
12
from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"

if __name__ == '__main__':
app.run(debug=True)

最佳实践

  • 谨慎使用 Access-Control-Allow-Origin: *:该设置会允许任何域名访问你的资源,可能会导致跨站请求伪造(CSRF)攻击。建议只允许特定的域名访问,例如:
1
<?php header('Access-Control-Allow-Origin: http://your-allowed-domain.com'); ?>
  • 在开发环境中使用代理服务器:可以使用Webpack Dev Server或其他代理服务器来解决跨域问题,避免在生产环境中进行复杂的配置。
  • 记录和监控CORS错误:在服务器端记录CORS错误信息,以便及时发现和解决问题。

常见问题

  • 使用 Access-Control-Allow-Origin: * 有什么风险?
    使用 Access-Control-Allow-Origin: * 会使你的API或网站容易受到跨站请求伪造(CSRF)攻击。攻击者可以通过诱导用户在已登录的状态下访问恶意网站,从而执行未经授权的操作。因此,在生产环境中应谨慎使用,建议只允许特定的域名访问。
  • 为什么Postman可以正常请求,而浏览器不行?
    Postman是一个开发工具,它不遵循浏览器的同源策略,因此可以直接发送跨域请求。而浏览器为了安全起见,会严格执行同源策略和CORS机制,只有在服务器设置了正确的响应头时,才允许跨域请求。
  • 如何在生产环境中解决CORS问题?
    在生产环境中,建议通过服务器端配置来解决CORS问题,例如在Nginx或Apache中添加相应的配置。同时,要确保只允许特定的域名访问你的资源,以提高安全性。

JavaScript代码出现CORS错误而Postman不出现的原因及解决办法
https://119291.xyz/posts/reasons-and-solutions-for-cors-error-in-js-but-not-in-postman/
作者
ww
发布于
2025年5月9日
许可协议