需要开发一个web应用程序,同时高度依赖于API,但同时不能驻留在与API本身相同的域中,这是相当棘手的绕过"同源策略"时,异步HTTP请求(AJAX)。有一次,有人建议我在我的计算机上安装WAMP(运行Windows 7),并使用Apache配置反向代理。在告诉我为IP 127.0.0.1创建一个名为dev的别名(我在c:windowssystem32driversetchosts
的文件中这样做了)之后,同一个人给了我下面添加到httpd.conf
文件中的Apache指令:
LoadModule headers_module modules/mod_headers.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule ssl_module modules/mod_ssl.so
Listen 127.0.0.1:8080
ProxyRequests off
<Proxy *>
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Proxy>
<VirtualHost dev:8080>
ProxyPass / https://app.somesite.com:5002/
ProxyPassReverse / https://app.somesitecom:5002/
ProxyPassReverseCookieDomain app.somesite.com dev
Header edit Location ^https://dev(:8080)?(.+)$ http://dev$1$2
Header edit Set-Cookie "(^.+); secure; HttpOnly$" "$1; HttpOnly"
SSLProxyEngine on
SSLProxyVerify none
</VirtualHost>
由于在配置服务器方面我是一个完全的新手,所以我只是简单地粘贴了指令,幸运的是,代理工作了。当我使用浏览器的地址栏访问时,它会从API返回正确的响应,例如http://dev:8080/a/w/currencies
。
不幸的是,一个AJAX请求相同的URL(下面的代码)使Chrome给我XMLHttpRequest cannot load http://dev:8080/a/w/currencies. Origin http://dev is not allowed by Access-Control-Allow-Origin.
错误。
$.ajax({
url: "http://dev:8080/a/w/currencies",
type: "GET",
dataType: "json",
data: {
},
success: function(data){
console.log(data);
}
});
那么,为了让这个代理与AJAX一起工作,还必须做些什么呢?有人告诉过我一些关于alias
指令的事情,但不够具体和清楚,所以对我没有经验的大脑来说,它没有多大意义。
PS:另外,我被告知"问题是你从dev:80获取文件并ajax到dev:8080"。鉴于我缺乏经验,这两件事都说不通。
您有一个具有公共IP的服务器,并且apache正在其上运行。现在你想在局域网上托管你的应用程序,也希望它们可以在互联网上访问,重要的是这些应用程序仍然在局域网上的机器上运行。
|--------------192.168.1.3
| (internal3.example.com)
|
|--------------192.168.1.4
| (internal4.example.com)
(Public IP ) |
A--------------|
(reverse proxy server) |
(192.168.1.25) |
example.com |
|--------------192.168.1.1
| (internal1.example.com)
|
|--------------192.168.1.2
| (internal2.example.com)
我使用Ubuntu来托管Apache,在基于Debian系统的情况下,vhost定义网站的定义是在
/etc/输入/sites-enabled/* . conf
其中*conf对应
internal1.conf internal2.conf internal3.conf internal4.conf
这些站点的vhost定义如下
/etc/输入/sites-enabled/internal1.example.conf
<virtualhost *:80>
ServerAdmin webmaster@localhost
ServerName internal1.example.com
ProxyRequests off
<proxy *>
Order deny,allow
Allow from all
</proxy >
ProxyPass / http://192.168.1.1/
ProxyPassReverse / http://192.168.1.1/
</VirtualHost>
/etc/输入/sites-enabled/internal2.example.conf
<virtualhost *:80>
ServerAdmin webmaster@localhost
ServerName internal2.example.com
ProxyRequests off
<proxy *>
Order deny,allow
Allow from all
</proxy >
ProxyPass / http://192.168.1.2/
ProxyPassReverse / http://192.168.1.2/
</VirtualHost >
/etc/输入/sites-enabled/internal3.example.conf
<virtualhost *:80>
ServerAdmin webmaster@localhost
ServerName internal3.example.com
ProxyRequests off
<proxy *>
Order deny,allow
Allow from all
</proxy >
ProxyPass / http://192.168.1.3/
ProxyPassReverse / http://192.168.1.3/
</VirtualHost >
/etc/输入/sites-enabled/internal4.example.conf
<virtualhost *:80>
ServerAdmin webmaster@localhost
ServerName internal4.example.com
ProxyRequests off
<proxy *>
Order deny,allow
Allow from all
</proxy>
ProxyPass / http://192.168.1.4/
ProxyPassReverse / http://192.168.1.4/
</VirtualHost>
注意,在上面的所有vhost定义中,我都删除了日志文件的选项。因此,如果应用到生产服务器,请将它们添加到每个vhost文件中。以上只是给你一个清晰的例子,说明它是如何工作的。我运行一个非常复杂的Apache设置,所以上面只是一个小的例子来帮助你。
现在回到问题的Ajax部分
在chrome中按Ctrl+Shift+I你会看到确切的应用程序被打破的地方,它会给你一些提示,(从不同于开发web应用程序的机器发出请求)另外,如果你可以查看apache日志,如果来自http://sample
页面的ajx api的请求实际上到达了你的apache服务器,这将给你更多的提示,如果代理正确转发你的请求,在没有请求和应用程序发出请求的情况下,使用firefox中的一些工具(如live_http)发布HTTP标头,这样观察标头可以帮助您是否请求到达反向代理后面的服务器,还可以检查运行反向代理的服务器的日志,如果来自web的请求到达了它,如果请求到达了请求的URL是什么。这会给你一个提示,
和出于开发目的,在你的.conf文件中禁用重写规则一段时间来测试,一个一个地做。
这里的问题是浏览器试图保护您免受放置在某些网页上的随机javascript的攻击。如果它会让所有的javascript在相同的上下文中运行,你会失去你的Facebook会话cookie或其他一些数据给坏人。
在这种情况下,罪魁祸首可能是一些简单的东西,因为Chrome不认为'dev'是一个完全合格的域名,所以它将失败的同源测试。另一个原因可能是,有时你从app。somesite。dev获取东西有时你向dev发送请求
服务器不关心他们发送的是什么,你需要欺骗的是浏览器,让它相信所有的东西都来自同一个主机
- 我将把hosts文件中的dev替换为dev.example.com 127.0.0.1
- 我将确保Apache代理的所有内容只引用dev.example.com,无论它来自哪个服务器
- 只在代码中使用dev.example.com
如果这些都失败了,你可以添加一个HTTP头'Access-Control-Allow-Origin: *'来允许任何来源,但我不会使用这个,除非只是在开发环境。
p。即使你从example.com:80得到javascript, javascript甚至不能调用example.com:443或javascript从example.com不能使xmlhttprequest到dev.example.com
在127.0.0.1,你的html代码应该是:
$.ajax({
url: "http://127.0.0.1/a/w/currencies",
type: "GET",
dataType: "json",
data: {
},
success: function(data){
console.log(data);
}
});
在127.0.0.1上,你的apache配置应该是:
...
<VirtualHost dev:8080>
...
ProxyPass / https://app.somesite.com:5002/
ProxyPassReverse / https://app.somesitecom:5002/
...
</VirtualHost>
在这种情况下,您的浏览器将不会跨域,因为您的url和ajax使用相同的域。但确切地说,ajax请求https://app.somesite.com:5002/,我不知道它是否是一个反向代理,但它似乎为我工作。有一个尝试:)
我将尝试同样的事情我自己很快,这就是我如何发现这个线程。
我想知道您在AJAX请求中使用的实际url是否错误。实际上,您正在连接到代理。它正在把你转发到8080端口地址。然后尝试直接向8080地址发出AJAX请求?相对链接可以使AJAX调用沿着相同的路径转发,以便javascript知道它是相同的来源。
另一种选择是使用PHP后端。这门在线课程的第7讲涵盖了AJAX,并用PHP做了一个例子来完全规避同源限制。http://academicearth.org/courses/building-dynamic-websites/
我刚发现这个,它似乎是一个更好的解决方案。http://darius.kruythoff.net/blog/2011/xss-with-apache/