NGINX 配置跨域支持的正确方式 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaochong0302
V2EX    NGINX

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

  •  
  •   xiaochong0302 2020-10-20 11:44:18 +08:00 5933 次点击
    这是一个创建于 1821 天前的主题,其中的信息可能已经有所发展或是发生改变。

    NGINX 配置跨域 CORS 支持

    这两天在搞 酷瓜云网课 的 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='; return 204; } if ($request_method ~* '(GET|POST|DELETE|PUT)') { add_header 'Access-Control-Allow-Origin' '*' always; } } 

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

    第 1 条附言    2020-10-20 19:31:59 +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); } } 
    21 条回复    2020-10-21 10:01:51 +08:00
    eudore
        1
    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
        2
    KuroNekoFan  
       2020-10-20 11:57:19 +08:00
    cors 跨域挺烦人的,如果非必要,直接把页面和后端置同域是个更好的选择
    个人认为 cors 跨域的场景应该是一些提供一些第三方公共资源
    xiaochong0302
        3
    xiaochong0302  
    OP
       2020-10-20 12:38:08 +08:00
    @eudore 是的,很多人都是一股脑的全部返回
    @KuroNekoFan 我的开发环境是 linux, 弄 app 用到了 uni-app,它的开发工具 hbuilder 又没有 linux 版本的,没办法在虚拟机里搭了个 windows 环境
    renmu123
        4
    renmu123  
       2020-10-20 13:22:16 +08:00 via Android
    嫌麻烦其实可以直接找个跨域的中间件,配置什么也比较多,基本也不会出什么 bug
    356693212
        5
    356693212  
       2020-10-20 14:39:17 +08:00
    你这理论上也不对,*不能满足 cookie 携带的问题,勉强够用吧,等遇到问题再说吧
    raysonlu
        6
    raysonlu  
       2020-10-20 15:05:46 +08:00
    对比这种*号方案,在实际生产环境上,我觉得有仅仅支持二级域名跨域的方案,会有意义些。
    est
        7
    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
        8
    est  
       2020-10-20 15:09:35 +08:00
    然后 add_header 还有个问题就是 rewrite 比如 http 升级 https 的不会带上,也会导致跨域失败。
    rrfeng
        9
    rrfeng  
       2020-10-20 15:21:53 +08:00   1
    你这相当于废掉了 CORS 。
    人家给你造了一把锁锁你家门,你直接把门拆了说我不要……还『正确方式』呢。
    xiaochong0302
        10
    xiaochong0302  
    OP
       2020-10-20 16:13:21 +08:00
    @356693212
    @raysonlu
    @es
    @rrfeng
    走的 API 请求,所以不用 COOKIE,上面只是示例,具体的要按自己的需求来调整

    自然是在后端代码里面支持更可控,nginx 也只是一个方案而已
    justseemore
        11
    justseemore  
       2020-10-20 16:16:48 +08:00
    更倾向于中间件.后端接口来控制..你这每次加个 origin 都要 reload 一次服务器..单机问题不大..集群的话会疯..
    PonysDad
        12
    PonysDad  
       2020-10-20 17:50:50 +08:00
    这样配置,那 CORS 还有啥子意义,来者不拒啊.
    bigNewsMaker
        13
    bigNewsMaker  
       2020-10-20 18:13:02 +08:00
    梭哈编程,能跑就行
    xiaochong0302
        14
    xiaochong0302  
    OP
       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
        15
    tingyunsay  
       2020-10-20 19:47:03 +08:00
    我是截取 Referer 和 Origin 两个来判断是否跨域,基本上 pc 端全兼容..
    ivanshaoaz
        16
    ivanshaoaz  
       2020-10-20 20:34:44 +08:00
    @xiaochong0302 #14 phalcon 啊
    xiaochong0302
        17
    xiaochong0302  
    OP
       2020-10-20 20:44:10 +08:00
    @ivanshaoaz 大佬,这都能看出来呀
    just1
        18
    just1  
       2020-10-20 20:54:57 +08:00
    如果你是问问题,那么你在代码里写了不告诉大家这没问题,反正解决了就好。
    你放个半吊子在这告诉大家是正确方式,还不说明,不 dui 你 dui 谁
    ivanshaoaz
        19
    ivanshaoaz  
       2020-10-20 21:02:58 +08:00
    @xiaochong0302 #17 我可不是大佬,最近在用 phalcon4 写项目
    fumichael
        20
    fumichael  
       2020-10-21 09:24:35 +08:00
    @est #8 我昨天用楼主的方案想代理 smms 的上传接口,结果失败了,还没弄清楚原因
    justseemore
        21
    justseemore  
       2020-10-21 10:01:51 +08:00
    在 dui 一下.. 你这 origin 多个时候不生效啊. 应该是配置那是数组判断是不是在数组,
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5441 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 22ms UTC 08:04 PVG 16:04 LAX 01:04 JFK 04:04
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86