如何使用Apache正确配置反向代理,以用于跨域AJAX?

时间:2013-01-06 19:50:34

标签: ajax apache cross-domain wampserver

需要开发一个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指令的事情,但不够具体和清楚,所以对我没有经验的大脑没有多大意义。

PS:另外,我被告知“问题是你从dev:80获取文件,ajaxing到dev:8080 ”。鉴于我的经验不足,这都没有多大意义。

4 个答案:

答案 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'发送请求

服务器并不关心它们发送的内容,而是您需要欺骗的浏览器才能相信所有内容都来自同一主机

  1. 我会用dev.example.com 127.0.0.1
  2. 替换hosts文件中的'dev'
  3. 我会确保从Apache代理发出的所有内容仅指dev.example.com,无论它来自哪个服务器
  4. 仅在代码中使用dev.example.com
  5. 如果所有其他方法都失败了,你可以添加一个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/