笔者在前几天遇到一个跨域问题,请求一个地图瓦片服务,但是地图瓦片服务地址由另一个地图服务商提供的,按照传统的后端解决跨域的手段,主要有两种:
(1)后端设置CORS(这个需要第三方CORS的jar包)
(2)对后端设置跨域访问(即在get或者post等方法中设置 response.setHeader(“Access-Control-Allow-Origin”, “*”);)
具体可以参考:
那么,什么是跨域呢?
跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对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;
# }
#}
}