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、常见跨域场景

协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域不同域之间相互请求资源,就算作“跨域”。常见跨域场景如下图所示:

参考文献:https://segmentfault.com/a/1190000018017118 (九种跨域方式实现原理)

二、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;
        }
    }

关于nginx反向代理的执行流程,可参考:https://blog.csdn.net/qq_36095679/article/details/91358593

访问流程:

  1. 客户端访问地址:http://nginx.test.com/login 或者 http://nginx.test02.com/login
  2. 会被反向代理到:http://127.0.0.1:8080/login 或者 http://127.0.0.1:8081/login 完成跨域

关于nginx反向代理中的负载均衡策略可参考:https://blog.csdn.net/qq_36095679/article/details/89487645

2、配置文件注意点 

proxy_ pass 指令:该指令用来设置被代理服务器的地址,可以是主机名称、IP地址加端口号等形式。

其语法结构为: proxy_pass URL;

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

注意细节:

  1. 如果在配置文件里,我们已经在“upstream”模块定义了“传输协议”,那么在“proxy_pass”就不需要重复定义(二选一即可);
  2. 注意 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;
        }
    }

配置文件分析:

  1. 客户端访问地址:http://nginx.test.com/api/login 
  2. 该请求被配置中显示的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/;
        }

配置文件分析:

  1. 客户端访问地址:http://nginx.test.com/api/login 
  2. 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替换为“/”。

  1. 比如,客户端的请求URL为“http://nginx.test.com/api/login";
  2. 使用配置1的时候,转向的URL为"http://127.0.0.1:8080/api/login",原地址的URI  “/api/" 未被改变;
  3. 但使用配置2时,转向的URL为“http://127.0.0.1:8080/login”,可以看到,原地址的URI“/api/" 被替换为“/"。

      大家在应用过程中,一-定要注意到该指令在配置上的细节问题,分清楚URL和URI的区别与联系,并能够正确使用它们配置出符合需求的Nginx服务器。

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

  1. 如上,示例2:proxy_pass指令的URL变量末尾加上 “ / ”;
  2. 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来标识资源。

4、Location用法总结

详情请查看博客:https://blog.csdn.net/qq_36095679/article/details/101272135

5、 Rewrite 用法总结

详情请查看博客:https://blog.csdn.net/qq_36095679/article/details/101277202

发布了101 篇原创文章 · 获赞 176 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_36095679/article/details/101266415