利用nginx解决跨域问题
前言
最近遇到了跨域问题,结合之前【微信支付开发本地接收异步通知回调】的经验,利用 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