您现在的位置是:亿华云 > 知识
一点也不复杂!Nginx 可以轻松搞定跨域问题
亿华云2025-10-04 00:18:19【知识】7人已围观
简介当你遇到跨域问题,不要立刻就选择复制去尝试。请详细看完这篇文章再处理 。我相信它能帮到你。 分析前准备: 前端网站地址:
当你遇到跨域问题,点也定跨不要立刻就选择复制去尝试。不复请详细看完这篇文章再处理 。可轻我相信它能帮到你。松搞
分析前准备:
前端网站地址: http://localhost:8080
服务端网址: http://localhost:59200
首先保证服务端是域问没有处理跨域的,其次,点也定跨先用 Postman 测试服务端接口是不复正常的
跨域主要涉及4个响应头:
Access-Control-Allow-Origin:用于设置允许跨域请求源地址 (预检请求和正式请求在跨域时候都会验证)
Access-Control-Allow-Headers:跨域允许携带的点也定跨特殊头信息字段 (只在预检请求验证)
Access-Control-Allow-Methods:跨域允许的请求方法或者说HTTP动词 (只在预检请求验证)
Access-Control-Allow-Credentials:是否允许跨域使用cookies,如果要跨域使用cookies,不复可以添加上此请求响应头,可轻值设为true(设置或者不设置,松搞都不会影响请求发送,域问只会影响在跨域时候是否要携带cookies,但是如果设置,预检请求和正式请求都需要设置)。不过不建议跨域使用(项目中用到过,不过不稳定,源码下载有些浏览器带不过去),除非必要,因为有很多方案可以代替。 网上很多文章都是告诉你直接 Nginx 添加这几个响应头信息就能解决跨域,当然大部分情况是能解决,但是我相信还是有很多情况,明明配置上了,也同样会报跨域问题。 什么是预检请求?当发生跨域条件时候,览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。如下图不过我们的配置没什么问题,问题在Nginx
此时发现报错问题又回到了情况1
官方文档是这样说的:
There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level. 意思就是当前层级无 add_header 指令时,则继承上一层级的add_header。相反的若当前层级有了add_header,就应该无法继承上一层的add_header。配置修改如下:
server { listen 22222; server_name localhost; location / { add_header Access-Control-Allow-Origin http://localhost:8080 always; if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin http://localhost:8080; add_header Access-Control-Allow-Headers authorization; return 204; } proxy_pass http://localhost:59200; } }此时改完发现跨域问题已经解决了,
还没完,继续聊 ↓↓
情况4:
比较早期的API可能只用到了POST和GET请求,而Access-Control-Allow-Methods这个请求响应头跨域默认只支持POST和GET,当出现其他请求类型时候,同样会出现跨域异常。 比如,我这里将请求的API接口请求方式从原来的GET改成PUT,在发起一次试试。在控制台上会抛出错误: Access to XMLHttpRequest at http://localhost:22222/api/Login/TestGet from origin http://localhost:8080 has been blocked by CORS policy: Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.这里注意一下,改成PUT类型后,Access-Control-Allow-Headers请求响应头又会自动校验content-type这个请求头,和情况3是一样的,缺啥补啥就行了。如果不加上content-type,则会报如下错误。
想简单的话,Access-Control-Allow-Headers和Access-Control-Allow-Methods可以设置为*,表示全都匹配。但是Acces s-Control-Allow-Origin就不建议设置成* 了,为了安全考虑,限制域名是很有必要的。情况5:
最后再说一种情况,就是后端处理了跨域,就不需要自己在处理了(这里吐槽下,某些后端工程师自己改服务端代码解决跨域,但是又不理解其中原理,网上随便找段代码黏贴,导致响应信息可能处理不完全,如method没添加全,headers没加到点上,自己用的那个可能复制过来的并不包含实际项目所用到的,没有添加options请求返回状态码等,导致Nginx再用通用的配置就会可能报以下异常) Access to XMLHttpRequest at http://localhost:22222/api/Login/TestGet from origin http://localhost:8080 has been blocked by CORS policy: The Access-Control-Allow-Origin header contains multiple values *, http://localhost:8080, but only one is allowed.意思就是此刻 Access-Control-Allow-Origin 请求响应头返回了多个,而只允许有一个,这种情况当然修改配置去掉 Access-Control-Allow-Origin 这个配置就可以了,不过遇到这种情况,建议Nginx配置和服务端自己解决跨域只选其一。
这里注意如果按我上面的写法, if $request_method = OPTIONS 这个里面的 Access-Control-Allow-Origin 可不能删除,删除!=’OPTIONS’里面的就好了,因为这里如果是预检请求直接就ruturn了,请求不会再转发到59200服务,如果也删除了,就会报和情况1一样的错误。所以为什么说要不服务端代码层面解决跨域,要不就Nginx代理解决,不要混着搞,不然不明白原理的人,网上找一段代码贴就很可能解决不了问题
再贴一份完整配置(*号根据自己‘喜好’填写):
server { listen 22222; server_name localhost; location / { if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin http://localhost:8080; add_header Access-Control-Allow-Headers *; add_header Access-Control-Allow-Methods *; add_header Access-Control-Allow-Credentials true; return 204; } if ($request_method != OPTIONS) { add_header Access-Control-Allow-Origin http://localhost:8080 always; add_header Access-Control-Allow-Credentials true; } proxy_pass http://localhost:59200; } }或者:
server { listen 22222; server_name localhost; location / { add_header Access-Control-Allow-Origin http://localhost:8080 always; add_header Access-Control-Allow-Headers *; add_header Access-Control-Allow-Methods *; add_header Access-Control-Allow-Credentials true; if ($request_method = OPTIONS) { return 204; } proxy_pass http://localhost:59200; } } 最后,这是一篇解决跨域遇到问题解决问题的过程,如果认真看完了,我相信应该都能很容易的理解,并且在实际使用中自己解决该问题,希望能帮助到大家,以上内容都是自己理解自己测试码出来的,如有理解不对的地方,望大家指正。来源:cnblogs.com/fnz0/p/15803011.html
很赞哦!(858)