【反向代理】跨域解决方式之一——反向代理

来源:互联网 发布:淘宝详情页设计多少钱 编辑:程序博客网 时间:2024/05/01 01:16

笔者在前几天遇到一个跨域问题,请求一个地图瓦片服务,但是地图瓦片服务地址由另一个地图服务商提供的,按照传统的后端解决跨域的手段,主要有两种:

(1)后端设置CORS(这个需要第三方CORS的jar包)
(2)对后端设置跨域访问(即在get或者post等方法中设置 response.setHeader(“Access-Control-Allow-Origin”, “*”);)

具体可以参考:

解决跨域的方法
CORS详解

那么,什么是跨域呢?

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
所谓同源是指,域名,协议,端口相同。浏览器执行javascript脚本时,会检查这个脚本属于那个页面,如果不是同源页面,就不会被执行。
同源策略的目的,是防止黑客做一些做奸犯科的勾当。比如说,如果一个银行的一个应用允许用户上传网页,如果没有同源策略,黑客可以编写一个登陆表单提交到自己的服务器上,得到一个看上去相当高大上的页面。黑客把这个页面通过邮件等发给用户,用户误认为这是某银行的主网页进行登陆,就会泄露自己的用户数据。而因为浏览器的同源策略,黑客无法收到表单数据。

因为笔者遇到的这种情况比较特殊一点,如果是自己写的服务,那么自然可以加上跨域请求的设置,但是如果是请求别的服务商的服务,那么跨域要么和服务商沟通,让他们设置允许来自某域名的跨域访问。要么就需要像本文一样,自己设置一个反向代理的服务器,或者自己编写一个代理服务。

代理服务其实就是把前端的跨域请求,通过代理进行一次转发,代理执行真正的访问另一域名下的服务(因为后端调用另一域名下的服务是不存在跨域问题的),将访问后的结果返回给前端。

本文针对代理,提供两种解决方案,一种是后端自己编码,一种是使用Nginx代理。

(1)编码
笔者采用vertx自己编写代理服务(需要利用vertx的core包)
示例:

package util;import io.vertx.core.AbstractVerticle;import io.vertx.core.Vertx;import io.vertx.core.http.HttpClient;import io.vertx.core.http.HttpClientOptions;import io.vertx.core.http.HttpClientRequest;/** * 代理 * @author KingWang * */public class Proxy extends AbstractVerticle {  @Override  public void start() throws Exception {    HttpClient client = vertx.createHttpClient(new HttpClientOptions());    vertx.createHttpServer().requestHandler(req -> {      System.out.println("Proxying request: " + req.uri());      HttpClientRequest c_req = client.request(req.method(), 25033, "10.73.199.229", req.uri(), c_res -> {        System.out.println("Proxying response!");//        System.out.println("Proxying response:" + c_res.statusCode());        req.response().setChunked(true);        req.response().setStatusCode(c_res.statusCode());        req.response().headers().setAll(c_res.headers());        c_res.handler(data -> {          System.out.println("Proxying response body");//          System.out.println("Proxying response body: " + data.toString("ISO-8859-1"));          req.response().write(data);        });        c_res.endHandler((v) -> req.response().end());      });      c_req.setChunked(true);      c_req.headers().setAll(req.headers());      req.handler(data -> {        System.out.println("Proxying request body ");//        System.out.println("Proxying request body " + data.toString("ISO-8859-1"));        c_req.write(data);      });      req.endHandler((v) -> c_req.end());    }).listen(1001);  }}

(2)使用Nginx代理

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

使用Nginx代理只需要几行配置代码就可以了。

首先下载Nginx并安装(不能安装在中文目录下)

然后在conf目录下的nginx.conf配置相应的反向代理路径

示例(本示例配置的是可以配置多个代理路径,也就是多个server标签):

#user  nobody;worker_processes  1;#error_log  logs/error.log;#error_log  logs/error.log  notice;#error_log  logs/error.log  info;#pid        logs/nginx.pid;events {    worker_connections  1024;}http {    include       mime.types;    default_type  application/octet-stream;    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '    #                  '$status $body_bytes_sent "$http_referer" '    #                  '"$http_user_agent" "$http_x_forwarded_for"';    #access_log  logs/access.log  main;    sendfile        on;    #tcp_nopush     on;    #keepalive_timeout  0;    keepalive_timeout  65;    #gzip  on;    server {        listen       8081;        server_name  localhost;        #charset koi8-r;        #access_log  logs/host.access.log  main;        location / {            root   html;            index  index.html index.htm;        }        #error_page  404              /404.html;        # redirect server error pages to the static page /50x.html        #        error_page   500 502 503 504  /50x.html;        location = /50x.html {            root   html;        }        # proxy the PHP scripts to Apache listening on 127.0.0.1:80        #        #location ~ \.php$ {        #    proxy_pass   http://127.0.0.1;        #}        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000        #        #location ~ \.php$ {        #    root           html;        #    fastcgi_pass   127.0.0.1:9000;        #    fastcgi_index  index.php;        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;        #    include        fastcgi_params;        #}        # deny access to .htaccess files, if Apache's document root        # concurs with nginx's one        #        #location ~ /\.ht {        #    deny  all;        #}    }    # another virtual host using mix of IP-, name-, and port-based configuration    #    #server {    #    listen       8000;    #    listen       somename:8080;    #    server_name  somename  alias  another.alias;    #    location / {    #        root   html;    #        index  index.html index.htm;    #    }    #}    # HTTPS server    #    #server {    #    listen       443 ssl;    #    server_name  localhost;    #    ssl_certificate      cert.pem;    #    ssl_certificate_key  cert.key;    #    ssl_session_cache    shared:SSL:1m;    #    ssl_session_timeout  5m;    #    ssl_ciphers  HIGH:!aNULL:!MD5;    #    ssl_prefer_server_ciphers  on;    #    location / {    #        root   html;    #        index  index.html index.htm;    #    }    #}}
原创粉丝点击