配置ngrok的CORS头信息

56

我正在运行本地web服务器,它会向一个在我的PC上也运行的ngrok服务器发送XHR请求。

我收到以下错误信息:XMLHttpRequest无法加载http://foo.ngrok.io/。所请求的资源中不存在“Access-Control-Allow-Origin”标头。因此,不允许从源 'http://localhost:3000' 访问。

似乎ngrok的FAQ提到了CORS标头,但只是和基本身份验证有关 - 它没有提到如何设置标头以便我能够在开发过程中测试我的应用程序。

我该如何更改ngrok的CORS选项以允许从localhost加载请求?

更新:不同的用例。寻找此解决方案的赏金:

我收到以下错误信息:

login.php:1 Access to XMLHttpRequest at 'http://localhost/lagin/public/login.php'
from  origin 'http://062b-96-230-240-153.ngrok.io' has been blocked by CORS 
policy: The request client is not a secure context and the resource is in more- 
private address space `local`. 

我查看了配置ngrok的CORS头信息,但仍不确定如何进行。当我尝试运行ngrok http -host-header=rewrite 80时,它会显示未定义的头文件。

我看了10到12个YouTube视频,它们都很好地解释了CORS是什么,但解决方法讲得非常差。

我在Windows 10机器上运行虚拟盒子,并创建一个Linux虚拟机。在Linux侧,我正在运行xampp作为本地服务器。

我可以在ngrok上看到我的网站登录页面,但只要我进行axios调用就会出现上述错误。

另外,我在Chrome浏览器中尝试了//flags/#block-insecure-private-network-requests并禁用它。这样做后,我就不再收到错误信息,但网站也无法正常工作。

额外信息:

我与ngrok交谈,他们说:...听起来你的应用程序在ajax请求中正在尝试调用localhost。您需要调整该调用以确保其通过ngrok路由。

以下是我的操作:

responseData = sendData2('http://localhost/lagin/public/login.php',emailPass);

这里是sendData2(仅为完整性)

function sendData2(url,emailPass){

    let bodyFormData = new FormData()
    for (const [key, value] of Object.entries(emailPass)) {
       //console.log(key,value)
       bodyFormData.append(key,value)
    }

    return axios({
            method: 'POST',
            url: url,
            data: bodyFormData,
            headers: {'Content-Type': 'multipart/form-data'}
            })
                .then(function(response){
                    return response.data
                })
                .catch(function(response){
                    return response
                })
}

更新:每次我们隧道连接到ngrok时,我们都会获得一个地址,例如https://2634-96-230-240-153.ngrok.io如果我们将send2()调用更改为

sendData2('http://96-230-240-153.ngrok.io/lagin/public/login.php',emailPass);

它有效,但这需要我每次有新的隧道时更改代码。调整CORS策略是否可以解决这个问题?

10个回答

53

今天我偶然发现了这个问题,并通过启动ngrok并包含--host-header标志来解决它。

ngrok http --host-header=rewrite 3000

从文档中得知:

使用--host-header开关重写传入的HTTP请求。

如果指定了rewrite,则Host头将被重写以匹配转发地址的主机名部分。


这是要启动服务器还是客户端? - Venkataramanan
10
最新版本的ngrok选项是--host-header=rewrite - HarlemSquirrel
4
在此记录一下,因为这让我很烦恼:如果不设置ngrok-skip-browser-warning,可能会导致问题,这些问题看起来是CORS问题,特别是在GET请求中(预检OPTIONS请求将成功,但ngrok返回一个浏览器警告页面作为对GET的响应,当然,这不是你想要的,也不包括Access-Control-Allow-Origin头部)。 - mway

10
对我来说,除了设置服务器之外,您还需要在客户端发送的每个请求的标头中添加以下内容:
"ngrok-skip-browser-warning": true

3
如果您的服务器CORS设置正确,但仍然看到CORS错误,那可能是由于ngrok。当我们第一次通过ngrok发送请求时,它会重定向到浏览器警告页面。因此,如果您关闭浏览器的CORS并打印API响应,则会看到警告页面的HTML。CORS来自此页面,而不是您的服务器。只需发送一个标题以跳过此页面,一切都将没问题。 - allenyllee

7
首先,ngrok只是一个隧道而不是服务器,因此在ngrok中配置CORS头是不可能的。所以任何类型的CORS配置都需要在服务器级别上完成。
例如,如果您正在使用nginx服务器,则需要在nginx conf文件中配置标题:
location / {
    /*some default configuration here*/
    add_header 'Access-Control-Allow-Origin' '*';
}

通过添加这个头信息,您允许来自任何地址的跨域访问您的地址,因为该头信息的值设置为“*”。您也可以通过替换该值来指定允许访问您的地址的特定地址。

4
这似乎不正确,根据我的经验。我在一个Django应用程序中启用了CORS头,在使用CORS测试器进行测试时,测试通过了。但是,当我启动一个ngrok隧道到我的计算机并通过它运行相同的CORS测试时,测试失败了。 - Mr. Lance E Sloan

1
使用Webpack / react时,我使用了Chrome扩展程序“requestly”,并设置了一个来自Bypass CORS模板的规则。请注意,在选择“模板”>“Bypass CORS”之后,您需要单击对话框右上角的“创建规则”按钮。 然后填写顶部的部分,“如果域名包含<您的域名”,并进行任何其他配置更改,然后可以保存您的规则。

enter image description here

enter image description here


我已经在使用Requestly了,它确实很强大。我可以看到“修改标头”选项,但没有“绕过CORS模板”的选项。你能否请帮我提供适当的步骤/截图? - Mukul Gupta

1

你应该将以下代码添加到你的头部,这样就可以100%生效了: headers: { Origin: window.location.origin, },


1
对于使用Django和django-cors-headers的朋友们,请确保将该头部添加到允许列表中,因为我在这上面花费了太多时间。当然,如果其他框架限制了头部,也适用于它们。
CORS_ALLOW_HEADERS = (
    "accept",
    "authorization",
    "content-type",
    "user-agent",
    "x-csrftoken",
    "x-requested-with",
    "ngrok-skip-browser-warning"  
)

1
对于那些使用 --host-header=rewrite 选项无效的人,而且他们的使用场景是将资源(例如JS文件)加载到非本地运行的应用程序中,对我来说,设置这个标志是有效的。
ngrok http --response-header-add="Access-Control-Allow-Origin:*" <file path>

我正在使用ngrok v3.3.5。

0
如果你正在使用nodejs/express.js以及ngrok。
请使用以下代码:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "YOUR-DOMAIN.TLD"); // update to match 
the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content- 
Type, Accept");
next();
});

将“YOUR-DOMAIN.TLD”替换为“*”,以允许访问所有URL或您特定的网站URL。

有关更多详细信息,请参阅https://enable-cors.org/server_expressjs.html


我在我的JS中运行axios,我的后端是PHP。我需要做什么? - DCR

0
ngrok http 80 --response-header-add "Access-Control-Allow-Origin: *"
ngrok http 80 --response-header-add "Access-Control-Allow-Origin: *"

-1

让ngrok工作起来需要一点时间来弄清楚,但实际上它非常容易。

In chrome there is an option to turn off CORS.  In the chrome address bar go to
chrome://flags and look for Block insecure private network requests.
This needs to be disabled.

Second, in my ajax request I had used an absolute path and this needed to be changed 
to a relative path.  

注意:这是为了在本地运行并将其暴露到网络上


1
请务必避免在浏览器中禁用CORS保护。 - Mr. Lance E Sloan
为什么?你还有其他解决问题的方法吗?既然我们是在本地主机上进行操作,有什么问题吗? - DCR
2
也许对于您个人作为经验丰富的开发者来说,这是可以接受的。您选择冒这个险。但我强烈建议不要向他人建议这样做。因为很容易忘记已禁用了重要的浏览器安全措施。对于大多数人而言,如果他们想关闭浏览器的CORS保护,我会告诉他们这是他们的应用程序需要发送CORS标头的迹象。通常很容易实现。请参见此问题的其他答案。 - Mr. Lance E Sloan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接