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是一个开发工具,它不遵循浏览器的同源策略,因此可以直接发送跨域请求。解决跨域问题 不同后端语言的解决方案 1 <?php header ('Access-Control-Allow-Origin: *' ); ?>
Node-RED :在 node-red/settings.js
文件中取消注释以下代码:1 2 3 4 httpNodeCors : { origin : "*" , methods : "GET,PUT,POST,DELETE" },
1 pip install -U flask-cors
然后在应用中引入 flask-cors
包:
1 2 3 4 5 6 7 8 9 from flask import Flaskfrom 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" , 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 Flaskfrom 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中添加相应的配置。同时,要确保只允许特定的域名访问你的资源,以提高安全性。