需要开发一个Web应用程序,同时高度依赖于API,但同时不能与API本身驻留在同一个域中,在制作“同源策略”时非常棘手。异步HTTP请求(AJAX)。
有一次,我建议在我的计算机上安装WAMP(运行Windows 7)并使用Apache配置反向代理。
在告诉我为名为 dev 的IP 127.0.0.1创建别名之后,同一个人向我提供了我添加到httpd.conf
文件的Apache指令。 ,在c:\windows\system32\drivers\etc\hosts
的文件中(我做过):
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请求会让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
指令的事情,但不够具体和清楚,所以对我没有经验的大脑没有多大意义。
答案 0 :(得分:10)
您正在使用具有公共IP的服务器并且正在运行apache。现在您希望在LAN上托管您的应用程序并且还希望它们可以在Internet上访问,重要的是这些应用程序仍然在机器上运行LAN。
|--------------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 vhost定义,以防基于Debian的系统确定网站的定义
的/ etc / apache2的/启用的站点 - / *。CONF
其中* conf对应
internal1.conf internal2.conf internal3.conf internal4.conf
每个网站的虚拟主机定义如下
/etc/apache2/sites-enabled/internal1.example.conf
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/apache2/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/apache2/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/apache2/sites-enabled/internal4.example.conf
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应用程序的机器不同的机器发出请求)
如果来自http://sample
页面的具有ajx api的请求实际到达您的apache服务器将提供更多提示,如果代理正在转发您的请求,请通过使用一些来发布HTTP HEADERS firefox中的工具就像live_http那样在没有请求的情况下,当应用程序发出请求的条件时,如果请求到达反向代理后面的服务器,可以帮助你,也检查服务器的日志正在运行反向代理,如果来自Web的请求到达它,并且请求是否达到了所请求的URL。这将为您提供线索,
并且为了在.conf文件中进行开发,禁用重写规则一段时间进行测试,逐个执行。
答案 1 :(得分:1)
这里的问题是浏览器试图保护您免受某些网页上随机javascript的影响。如果它允许所有javascript在相同的上下文中运行,那么你将失去Facebook会话cookie或其他一些数据给坏人。
在这种情况下,罪魁祸首可能是一件非常简单的事情,因为Chrome并不认为'dev'是一个完全合格的域名,所以它将失败相同的原点测试。其他原因可能是在某些时候你从app.somesite.dev获取东西,并且在某些时候你向'dev'发送请求
服务器并不关心它们发送的内容,而是您需要欺骗的浏览器才能相信所有内容都来自同一主机
如果所有其他方法都失败了,你可以添加一个HTTP标头'Access-Control-Allow-Origin:*'来允许任何来源,但我不会在dev环境中使用它。
PS。即使你从example.com:80获得javascript,javascript甚至无法调用example.com:443或者来自example.com的javascript也无法将xmlhttprequests发送到dev.example.com
答案 2 :(得分:0)
在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 conf应该是:
...
<VirtualHost dev:8080>
...
ProxyPass / https://app.somesite.com:5002/
ProxyPassReverse / https://app.somesitecom:5002/
...
</VirtualHost>
在这种情况下,您的浏览器不会跨域,因为您的网址和ajax使用相同的域名。但确切地说,ajax请求https://app.somesite.com:5002/,我不知道它是否是反向代理,但它似乎对我有用。试一试:)
答案 3 :(得分:-1)
我很快就会尝试同样的事情,这就是我找到这个帖子的方式。
我想知道您在AJAX请求中使用的实际网址是否错误。基本上,您正在连接到代理。它将您转发到端口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/