前言
最近遇到了跨域问题,结合之前【微信支付开发本地接收异步通知回调】的经验,利用 Nginx 实现了跨域。
公司之前为了解决跨域问题,用的是 iFrame,反正对于只做后端的我而言,觉得很复杂,但是现在利用 nginx 如此简单就实现了跨域,感觉还挺有成就感,哈哈!
为什么会出现跨域问题?
前人已经总结得很好了,就借鉴一下吧!
我们在开发项目中遇到的跨域问题具体是这样的,公司的域名若是 www.domain.com,那么如果是发送的 Ajax 请求就不通过这个域名走了,而是通过 a.domain.com,于是便出现了跨域问题。
比如在 www.domain.com 首页中需要通过 Ajax 获取用户登录信息。
准备工作
下载演示项目
为了演示这个跨域问题,我创建了一个 SpringBoot 项目,便于演示,如果不会 SpringBoot 也没有关系,因为重点在于 Nginx 配置上面。
【点我下载】 提取密码: 8e68
启动演示项目
因为是SpringBoot 项目,因此可以通过 java -jar 的方式直接启动,为了演示跨域,因此需要启动两个项目,这里我们用两个端口来分别启动项目。
## A 项目,端口设置为8080
java -jar -Dserver.port=8080 demo.jar
## B 项目,端口设置为8090
java -jar -Dserver.port=8090 demo.jar
配置本地 Host
为了演示还需要两个域名,不用真正的域名,修改本地的 Host 即可,将两个域名的 Host 都执行本地。可以使用 SwitchHosts 来方便切换。
127.0.0.1 www.domain.com
127.0.0.1 a.domain.com
配置Nginx
编译安装 Nginx后, 修改 nginx.conf 配置文件。
#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;
keepalive_timeout 65;
#gzip on;
upstream webServer {
server 127.0.0.1:8080;
}
upstream ajaxServer {
server 127.0.0.1:8090;
}
server {
listen 80;
server_name a.domain.com;
location / {
proxy_pass http://ajaxServer;
}
}
server {
listen 80;
server_name www.domain.com;
location / {
proxy_pass http://webServer;
}
}
}
这里来详细解释一下这里的配置,a.domain.com 代理到 ajaxServer,即端口设置为 8090 的 B 项目;
server {
listen 80;
server_name a.domain.com;
location / {
proxy_pass http://ajaxServer;
}
}
再看看 www.domain.com 的配置,反向代理到 webServer , 即端口设置为 8080 的 A 项目。
server {
listen 80;
server_name www.domain.com;
location / {
proxy_pass http://webServer;
}
}
测试
访问项目地址 http://www.domain.com/page, 进入以下页面:
当输入框不输入或者输入的是当前域名 http://www.domain.com 时,可以正常提交,不会遇到跨域问题。
当输入 http://a.domain.com 时,点击按钮进行提交,会出现跨域问题。
修改 Nginx 配置文件
修改 www.domain.com 的配置
server {
listen 80;
server_name www.domain.com;
location /proxy/ {
proxy_set_header Host a.domain.com;
proxy_pass http://ajaxServer/;
}
location / {
proxy_pass http://webServer;
}
}
其中这里这处配置是这篇文章的关键点。意思是 http://www.domain.com/proxy/ 开头的请求将会被反向代理到 B 项目 即 http://a.domain.com 域名,proxy_set_header Host 这一行是必须的。需要注意的是,这两行的域名需要保持一致,且第二行后面必须要有一个 /,至于原因,可以参考这篇文章 proxy_pass后的url加不加/的区别
location /proxy/ {
proxy_set_header Host a.domain.com;
proxy_pass http://ajaxServer/;
}
修改之后保存配置文件,重启 Nginx
./nginx -s reload
再次测试
修改提交 URL 为 http://www.domain.com/proxy
点击按钮进行提交,发现此时没有出现跨域问题。虽然提交的URL 域名是 http://www.domain.com,而请求经过 Nginx 的反向代理之后,实际上提交到了 B 项目,即 http://a.domain.com, 也可以看到 B 项目打印了输出语句 userId: 12,由此便解决了跨域问题。
资源下载
文章涉及的jar文件我打成一个压缩包,可以自己下载尝试一下。
【点我下载】 提取密码: 8e68