NGINX 配置跨域支持的正确方式

2020-10-20 11:44:18 +08:00
 xiaochong0302

这两天在搞 酷瓜云网课 的 app,采用 uni-app 做全端支持,现学现卖,目前算是入门了。

在做 H5 的时候难免会跨域请求后端 API,虽然用 HBuilder 内置的浏览器不会有跨域问题(这个应该是做了内部处理),但是那个内置浏览器真尼妈坑爹,过一会就会卡死,导致 HBuilder 无响应,杀进程也是无济于事,只能重启,重复几次谁受的了。后来发现用外部的浏览器不会有这个问题,但是又面临跨域。

这里采用配置 nginx 来支持 CORS,这样的话就不用动任何代码了。正确的配置如下:

location ~ \.php$ {

    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE' always;
        add_header 'Access-Control-Allow-Headers' '*' always;
        add_header 'Access-Control-Max-Age' 1728000 always;
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        return 204;
    }

    if ($request_method ~* '(GET|POST|DELETE|PUT)') {
        add_header 'Access-Control-Allow-Origin' '*' always;
    }

}

PS:网上很多都是采集,粘贴复制的垃圾文章,完全没有去验证的,碰到了会浪费还多时间,还会把你带坑里去。

5599 次点击
所在节点    NGINX
21 条回复
eudore
2020-10-20 11:53:10 +08:00
顶一个,逻辑正确。

在跨越时,options 请求需要返回全部相关 header 和 204,非 option 必须返回 Access-Control-Allow-Origin 然后继续处理;origin 是请求必要的 header 。

[https://github.com/eudore/eudore/blob/master/middleware/cors.go]( https://github.com/eudore/eudore/blob/master/middleware/cors.go)
KuroNekoFan
2020-10-20 11:57:19 +08:00
cors 跨域挺烦人的,如果非必要,直接把页面和后端置同域是个更好的选择
个人认为 cors 跨域的场景应该是一些提供一些第三方公共资源
xiaochong0302
2020-10-20 12:38:08 +08:00
@eudore 是的,很多人都是一股脑的全部返回
@KuroNekoFan 我的开发环境是 linux, 弄 app 用到了 uni-app,它的开发工具 hbuilder 又没有 linux 版本的,没办法在虚拟机里面搭了个 windows 环境
renmu123
2020-10-20 13:22:16 +08:00
嫌麻烦其实可以直接找个跨域的中间件,配置什么也比较多,基本也不会出什么 bug
356693212
2020-10-20 14:39:17 +08:00
你这理论上也不对,*不能满足 cookie 携带的问题,勉强够用吧,等遇到问题再说吧
raysonlu
2020-10-20 15:05:46 +08:00
对比这种*号方案,在实际生产环境上,我觉得有仅仅支持二级域名跨域的方案,会有意义些。
est
2020-10-20 15:08:47 +08:00
Access-Control-Allow-Origin: 不能加账号密码。。。得指定具体 origin 。。。


For requests without credentials, the literal value "*" can be specified, as a wildcard; the value tells browsers to allow requesting code from any origin to access the resource. Attempting to use the wildcard with credentials will result in an error.


https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin


所以可以通过 $http_origin 来代替 *
est
2020-10-20 15:09:35 +08:00
然后 add_header 还有个问题就是 rewrite 比如 http 升级 https 的不会带上,也会导致跨域失败。
rrfeng
2020-10-20 15:21:53 +08:00
你这相当于废掉了 CORS 。
人家给你造了一把锁锁你家门,你直接把门拆了说我不要……还『正确方式』呢。
xiaochong0302
2020-10-20 16:13:21 +08:00
@356693212
@raysonlu
@est
@rrfeng
走的 API 请求,所以不用 COOKIE,上面只是示例,具体的要按自己的需求来调整

自然是在后端代码里面支持更可控,nginx 也只是一个方案而已
zpfhbyx
2020-10-20 16:16:48 +08:00
更倾向于中间件.后端接口来控制..你这每次加个 origin 都要 reload 一次服务器..单机问题不大..集群的话会疯..
PonysDad
2020-10-20 17:50:50 +08:00
这样配置,那 CORS 还有啥子意义,来者不拒啊.
bigNewsMaker
2020-10-20 18:13:02 +08:00
梭哈编程,能跑就行
xiaochong0302
2020-10-20 19:29:08 +08:00
已经在后端代码里做控制了,各位别再 DUI 我了,手动哭脸!!!

```
public function setCors()
{
/**
* @var Config $config
*/
$config = Di::getDefault()->getShared('config');

$enabled = $config->path('cors.enabled');

if (!$enabled) return;

$allowOrigin = $config->path('cors.allow_origin');
$allowHeaders = $config->path('cors.allow_headers');
$allowMethods = $config->path('cors.allow_methods');

/**
* @var HttpResponse $response
*/
$response = Di::getDefault()->getShared('response');

/**
* @var HttpRequest $request
*/
$request = Di::getDefault()->getShared('request');

$response->setHeader('Access-Control-Allow-Origin', $allowOrigin);

if ($request->isOptions()) {
$response->setHeader('Access-Control-Allow-Headers', $allowHeaders);
$response->setHeader('Access-Control-Allow-Methods', $allowMethods);
}
}
```
tingyunsay
2020-10-20 19:47:03 +08:00
我是截取 Referer 和 Origin 两个来判断是否跨域,基本上 pc 端全兼容..
ivanshaoaz
2020-10-20 20:34:44 +08:00
@xiaochong0302 #14 phalcon 啊
xiaochong0302
2020-10-20 20:44:10 +08:00
@ivanshaoaz 大佬,这都能看出来呀
just1
2020-10-20 20:54:57 +08:00
如果你是问问题,那么你在代码里写了不告诉大家这没问题,反正解决了就好。
你放个半吊子在这告诉大家是正确方式,还不说明,不 dui 你 dui 谁
ivanshaoaz
2020-10-20 21:02:58 +08:00
@xiaochong0302 #17 我可不是大佬,最近在用 phalcon4 写项目
fumichael
2020-10-21 09:24:35 +08:00
@est #8 我昨天用楼主的方案想代理 smms 的上传接口,结果失败了,还没弄清楚原因

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/716652

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX