用反向代理服务器Nginx解决烦人的前端跨域问题

K
K
擅长邻域:未填写

分类: Java 标签: Nginx跨域

2021-01-07 23:04:19 1572浏览

用反向代理服务器Nginx解决烦人的前端跨域问题
序言
一、跨域是什么?

1、什么是同源策略及其限制内容?

2、常见跨域场景

二、nginx反向代理解决跨域问题

1、nginx配置文件(简单版)

2、配置文件注意点

1)proxy_pass对 URI 的处理(重点)

2)proxy_pass指令的URL变量末尾是否加 “ / ”问题

3、URL与URI的区别与联系

4、Location用法总结

5、 Rewrite 用法总结

前言
前后端数据的交互经常会遇到请求跨域问题,小编最近在工作中就遇到了这个问题,最后通过nginx反向代理解决。

备注:该博客部分概念内容参考自网络。

一、什么是跨域?
1、什么是同源策略及其限制内容?
同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

url的组成


同源策略限制内容有:

Cookie、LocalStorage、IndexedDB 等存储性内容
DOM 节点
AJAX 请求发送后,结果被浏览器拦截了
但是有三个标签是允许跨域加载资源:
<img src=XXX>
<link href=XXX>
<script src=XXX>
2、常见跨域场景
当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。常见跨域场景如下图所示:



二、nginx反向代理解决跨域问题
1、nginx配置文件(简单版)
   #负载均衡:设置代理的服务器列表 可设置多个(目标访问地址)
upstream hellonginx {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}

server {
#监听端口80 也就是直接访问的URL的端口
listen 80;
#设置监听的域名 可设置多个(客户端直接访问的地址)
server_name nginx.test.com nginx.test02.com;
#编码格式
charset utf-8;
#代理配置超时、头信息等参数 可以不配置
proxy_connect_timeout 180;
proxy_send_timeout 180;
proxy_read_timeout 180;
proxy_set_header Host $host;
proxy_set_header X-Forwarder-For $remote_addr;

#反向代理路径(和upstream绑定)
location / {
proxy_pass http://hellonginx;
}
}

访问流程:

客户端访问地址:http://nginx.test.com/login 或者 http://nginx.test02.com/login
会被反向代理到:http://127.0.0.1:8080/login 或者 http://127.0.0.1:8081/login 完成跨域
2、
配置文件注意点
proxy_ pass 指令:该指令用来设置被代理服务器的地址,可以是主机名称、IP地址加端口号等形式。

其语法结构为: proxy_pass URL;

其中,URL为要设置的被代理服务器的地址,包含传输协议、主机名称或IP地址加端口号、URI等要素。传输协议通常是“http” 或者“https" 。

注意细节:

如果在配置文件里,我们已经在“upstream”模块定义了“传输协议”,那么在“proxy_pass”就不需要重复定义(二选一即可);
注意 URL 中是否包含有 URI,Nginx服务器处理的方式是不同的。见如下例子:
1)proxy_pass对 URI 的处理(重点)
#负载均衡:设置代理的服务器列表 可设置多个(目标访问地址)
upstream hellonginx {
server 127.0.0.1:8080;
}

server {
#监听端口80 也就是直接访问的URL的端口
listen 80;
#设置监听的域名 可设置多个(客户端直接访问的地址)
server_name nginx.test.com;
#反向代理路径(和upstream绑定)
location /api/ {
proxy_pass http://hellonginx;
}
}

配置文件分析:

客户端访问地址:http://nginx.test.com/api/login
该请求被配置中显示的location块进行处理,由于proxy_ pass指令的URL变量不含有URI,所以转向的地址为“http://127.0.0.1:8080/api/login”,但我们的目标地址是:http://127.0.0.1:8080/login
新配置文件:

#反向代理路径(和upstream绑定)
location /api/ {
proxy_pass http://hellonginx/myapi/;
}

配置文件分析:

客户端访问地址:http://nginx.test.com/api/login
nginx转向的地址为“http://127.0.0.1:8080/myapi/login”
总结:在使用 Proxy_pass 指令时,如果不想改变客户端访问地址的 URI,就不要在 Proxy_pass 的 URL 变量中配置 URI 。

2)proxy_pass指令的URL变量末尾是否加 “ / ”问题
示例1:location / {
#配置1
proxy_pass http://hellonginx;
#配置2
proxy_pass http://hellonginx/;
}

在该配置中,location 块使用 “/” 作为uri变量的值来匹配不包含URI的请求URL。由于请求URL中不包含URI,因此配置1和配置2的效果是样的。比如,客户端的请求URL为“http://nginx.test.com/api/login",其将会location 块匹配成功并进行处理。不管使用配置1还是配置2,转向的URL都为:“http://127.0.0.1:8080/api/login"。

示例2:location /api/ {
#配置1
proxy_pass http://hellonginx;
#配置2
proxy_pass http://hellonginx/;
}

在该配置中,location 块使用“/api/"作为uri变量的值来匹配包含URI“/api/" 的请求URL。这时,使用配置1和配置2的转向结果就不相同了。使用配置1的时候,proxy_ pass 指令中的URL变量不包含URI, Nginx 服务器将不改变原地址的URI;使用配置2的时候,proxy_ pass 指令中的URL变量包含URI “/”, Nginx服务器会将原地址的URI替换为“/”。

比如,客户端的请求URL为“http://nginx.test.com/api/login";
使用配置1的时候,转向的URL为"http://127.0.0.1:8080/api/login",原地址的URI “/api/" 未被改变;
但使用配置2时,转向的URL为“http://127.0.0.1:8080/login”,可以看到,原地址的URI“/api/" 被替换为“/"。
大家在应用过程中,一-定要注意到该指令在配置上的细节问题,分清楚URL和URI的区别与联系,并能够正确使用它们配置出符合需求的Nginx服务器。

如果我们在实际使用中,希望nginx转发后的地址不包含Location 的 uri (即“/api”) ,我们有两种方式处理:

如上,示例2:proxy_pass指令的URL变量末尾加上 “ / ”;
在proxy_pass指令前添加 Rewrite指令: “rewrite ^/api/(.*)$ /$1 break; ”,proxy_pass的末尾就不用添加“/”;
关于 Rewirte指令的使用,请继续往下阅读。

3、URL与URI的区别与联系




URI包括URL和URN两个类别,URL是URI的子集,所以URL一定是URI,而URI不一定是URL

URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。
URL = Universal Resource Locator 统一资源定位符,一种定位资源的主要访问机制的字符串,一个标准的URL必须包括:protocol、host、port、path、parameter、anchor。
URN = Universal Resource Name 统一资源名称,通过特定命名空间中的唯一名称或ID来标识资源。
有啥不懂的可以在杰凡IT问答平台上提问,https://www.jf3q.com

好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695