浏览器不求别人,用nginx反向代理就能搞跨域

Posted 神仙朱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器不求别人,用nginx反向代理就能搞跨域相关的知识,希望对你有一定的参考价值。

面试遇坑

面试官: 你知道跨域有什么解决办法吗?
神仙朱:JSONP 或者 后端修改相应头部 Accept-Control-Allow-Origin ??
面试官:看你还用过 nginx 啊,不知道 nginx 可以反向代理解决跨域吗 ?

我心想还有这种操作 ??于是我很自信地回答他我不知道

素来我是遇到问题一定要解决的,没有什么东西可以一直困扰我。
于是上网查了大量资料(一两篇文章),然后就尝试配置了一下 nginx ,最后真的解决了!!

现在我就来做一份自己的总结!



关键词

先来把几个关键知识点理一下

跨域

浏览器的同源策略 导致跨域! 注意是浏览器,只有在浏览器才存在有跨域。
也就是说 服务器上不存在 跨域 的说法。
所以才存在今天使用 服务器代理解决跨域的方法。

跨域的请求过程

跨域请求一般浏览器是可以发送跨域请求的,只是响应被拦截了。
而 chrome 下会先发一个 options 请求去询问浏览器是否可以跨域,并且对这个请求结果进行缓存。
如果 options 请求得到 跨域不允许,那么下一次跨域的时候不会再发送新的 options 请求 ,而是直接报跨域错误。

代理

正向代理

正向代理是隐藏客户端,服务器不知道真正的请求人。

比如你想访问某个网站,但是没有直接去访问,而是通过一个 代理服务器去访问 这个网站,利用代理服务器帮你发送请求,再把请求返回的信息转发给你。

上面的过程中,那个网站的服务器根本不知道到底是谁访问我。那么就达到了隐藏客户端的目的,这就是正向代理。

应用

科学上网:在国外部署代理服务器,通过这个代理服务器 实现代发请求,就可以科学上网

反向代理

反向代理 是隐藏服务器。客户端不知道真正的服务人。因为服务器会自动分配服务你的服务器,而你不知道真正给你提供服务的是谁。

比如我们访问淘宝,淘宝的服务器有很多。当我们访问淘宝的时候,淘宝服务器会将我们的请求转发给其他服务器。这时,淘宝服务器实现的功能就是 反向代理。



nginx 反向代理解决跨域

配置 window nginx 来测试一下

安装 nginx

  • 访问官网下载:
    http://nginx.org/en/download.html

  • 选择 window 版本
    比如 nginx/Windows-1.12.2

  • 下载成功,解压到某个文件夹,比如 D:/nginx

  • ok

启动 nginx

  • Ctrl+R 打开 CMD

  • 进入到刚刚解压的文件夹

  • 运行命令 ./nginx.exe

  • 正常情况下,启动成功没有任何提示

配置 nginx

进入到解压的文件夹

比如D:/nginx进入 conf 文件夹,看到nginx.conf 就是配置文件,打开它,

修改端口

原来nginx 的端口是80,不过window 下 80端口可能被 System 占用了,所以我们换一个端口 ,比如是 8089

配置服务器请求匹配路径

在 (location / )后面加上另一个自定义路径配置
这里我的路径是 /ho/ 也就是说如果我发送的请求中带有 ho ,那么就会匹配成功。
比如 发送请求是 

http://localhost:8089/ho/xxxx

里面包含 ho,所以匹配成功

1
2
3
4
5
6
7
8
9
10
11
12
13

# 这是原有的,只是为了找个对比位置
location / {
   root   html;
   index  index.html index.htm;
}

# 这是新增的
location /ho/ {
   rewrite ^.+ho/(.*)$ /$1 break;
   proxy_pass https://jingyan.baidu.com/ ;
}

下面照着上面的配置来详细说明一下

rewrite

举例

假设我们现在要在本地网页localhost通过 ajax 访问一个接口
http://jingyan.baidu.com/asyncreq/log?method=getLog&likeNum=39010735291423126980&type1423=6557184

一般情况下,这是会跨域的
而我们的目的就是想可以通过本地网页成功访问服务器接口!!
所以先在本地构建一个接口,通过这个接口去转发到真正的接口上去!!!!
http://localhost:8089/ho/asyncreq/log?method=getLog&likeNum=39010735291423126980&type1423=6557184

回到nginx配置上来,看到 rewrite 设置为 ^.+ho/(.*)$ /$1 break
不急,我们先尝试使用上面的正则去匹配URL测试最后会得到什么

1
2
/^.+ho\/(.*)$/.exec("http://localhost:8089/ho/asyncreq/log?method=getLog&likeNum=39010735291423126980&type1423=6557184") 
// 测试得到了一个数组 ["http://localhost:8089/ho/asyncreq/log?method=getLog&likeNum=39010735291423126980&type1423=6557184", "api/v4/answers/244453931/concerned_upvoters?limit=5&offset=0"]

看到 rewrite 还有一个 $1,就是取数组的第二个的意思
那么得到可以得到
/asyncreq/log?method=getLog&likeNum=39010735291423126980&type1423=6557184
就是这个没错了,我们就要这个

proxy_pass

  • 协议可以是 http 或者 https


既然拿到了 正确的api路径,那么我们现在要做的就是确定要真正发送请求的服务器的域名
比如是 https://jingyan.baidu.com
所以设置 proxy_pass 为 https://jingyan.baidu.com

那么最后我们发出去的请求就是
http://jingyan.baidu.com/asyncreq/log?method=getLog&likeNum=39010735291423126980&type1423=6557184

重启nginx

我们已经修改了配置文件了,现在要做的就是重启nginx
运行命令 nginx -s reload
到这一步,nginx 相关的我们都做完啦,下面就写一个页面测试一下接口反向代理是否成功

写测试页面

新建一个 nginx.html 文件放在 nginx解压目录下的 html 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
   <title>nginx 反向代理解决跨域</title>
</head>
<body>
   <div></div>
   <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
   <script type="text/javascript">
       $(function() {
           $.get("http://localhost:8089/ho/api/v4/answers/244453931/concerned_upvoters?limit=5&offset=0", function(result) {
               console.log(result,3233333333333)
           });
       })
   </script>
</body>
</html>

然后打开这个页面,打开链接 http://localhost:8089/nginx.html


最后我们可以在控制台看到请求返回的信息

我还能说什么?不就是成功了喽


结尾

在做项目的时候,调用后端项目的时候总是会涉及到跨域。
而JSONP需要后端配合根本就是很少用,要不然也只能去求后端爸爸设置一下响应头部
现在,我们不用求别人了!!靠自己,就能解决跨域问题!!!

PS:感觉文章排版还是乱乱的

以上是关于浏览器不求别人,用nginx反向代理就能搞跨域的主要内容,如果未能解决你的问题,请参考以下文章

nginx用反向代理机制解决跨域的问题

Nginx 反向代理解决浏览器跨域问题

Nginx的反向代理跨域

使用nginx代理解决跨域问题

nginx 反向代理请求cookie丢失问题

第362期最简单实现跨域的方法:使用nginx反向代理