> 技术文档 > Nginx — 跨域问题演示以及解决方法_nginx 跨域

Nginx — 跨域问题演示以及解决方法_nginx 跨域


1、跨域问题简介

产生跨域访问的原因

  • 同源策略限制
  • 浏览器的同源策略是一种安全机制,它规定了来自不同源(协议、域名、端口号都相同才是同源)的脚本之间不能相互访问对方的资源。当 Web 应用程序需要与不同源的服务器进行数据交互或资源共享时,就会涉及到跨域访问。例如,一个网站可能需要从另一个域名的 API 服务器获取数据,或者嵌入来自不同域名的视频、图片等资源。

跨域访问的目的

  • 数据共享与交互:在现代 Web 开发中,许多应用需要整合来自多个不同源的数据。例如,一个电商网站可能需要从供应商的服务器获取产品库存信息,而供应商的服务器与电商网站的服务器通常具有不同的域名。通过跨域访问,电商网站可以获取到实时的库存数据,为用户提供准确的商品信息,实现更好的用户体验和业务流程整合。
  • 多平台协作:不同的平台或服务可能由不同的团队或公司开发和维护,它们往往具有不同的域名和部署环境。以社交媒体平台为例,当用户在一个第三方应用中分享内容到社交媒体时,第三方应用需要与社交媒体平台的服务器进行跨域通信,将用户的分享请求和相关数据传递给社交媒体平台,实现多平台之间的协作与互动。
  • 资源复用:一些公共的资源,如字体库、JavaScript 库、图片库等,可能存储在专门的服务器上,这些服务器的域名与使用这些资源的网站域名不同。通过跨域访问,网站可以方便地引用这些公共资源,实现资源的复用,减少开发成本和维护工作量。同时,也有助于提高资源的加载速度和性能优化。

2、什么是同源策略?

同源是指两个 URL 的协议、域名、端口号都相同。例如,以下两个 URL 是同源的:

  • http://www.example.com/index.html
  • http://www.example.com/page.html

因为它们都使用 HTTP 协议,域名都是www.example.com,且端口号都采用了 HTTP 协议的默认端口号 80(在 URL 中未显式指定时默认使用 80 端口)。

而以下几个例子则与上述 URL 不同源:

  • https://www.example.com/index.html:协议为 HTTPS,与前面的 HTTP 协议不同。
  • http://api.example.com/index.html:域名是api.example.com,与www.example.com不同。
  • http://www.example.com:8080/index.html:指定了端口号 8080,与默认的 80 端口不同。

同源策略是浏览器安全的基石,它限制了不同源的文档或脚本之间的交互,防止恶意网站通过脚本访问其他网站的敏感信息,从而保护用户的隐私和数据安全。

一、实验准备

准备一台安装有nginx的机器

二、配置跨域访问

配置访问url为http://192.168.72.130:9999/访问到/opt/nginx目录下的a.html文件,a.html中配置有跨域访问的链接:http://192.168.72.130:8888/getUser。

步骤一: 配置跨域访问链接

a.html文件内容如下:

   跨域问题演示   $(function(){ $(\"#btn\").click(function(){ $.get(\'http://192.168.72.130:8888/getUser\',function(data){ alert(JSON.stringify(data)); }); }); });     
排错步骤:

注意上述的jquery.js文件需要提前放置在与a.html同一个文件目录下,不然会报如下错误:

Uncaught ReferenceError: $ is not defined

解决方法: 将jquery.js文件放在与a.html同一个目录下

 

步骤二、配置两个不同源的server

#配置不同源的两个serverserver { listen 9999; server_name localhost; gzip on; root /opt/nginx; location / { index a.html; }}server { listen 8888; server_name localhost; gzip on; root /opt/nginx; location /getUser { default_type application/json; return 200 \'{\"id\":\"123\",\"name\":\"小明\",\"age\":\"18\"}\'; }}

访问:http://192.168.72.130:8888/getUser

访问:http://192.168.72.130:9999/

三、跨域报错现象分析

Access to XMLHttpRequest at \'http://192.168.72.130:8888/getUser\' from origin \'http://192.168.72.130:9999\' has been blocked by CORS policy: No \'Access-Control-Allow-Origin\' header is present on the requested resource.Understand this error
jquery.js:10109

错误原因

1. 同源策略与 CORS

浏览器遵循同源策略,它会阻止网页从一个源(协议、域名、端口号的组合)加载的脚本去访问另一个不同源的资源。在你的情况中,请求的源是 http://192.168.72.130:9999,而目标资源的源是 http://192.168.72.130:8888,端口号不同,所以属于跨域请求。

2. Access-Control-Allow-Origin 头缺失

当进行跨域请求时,浏览器会检查服务器返回的响应头中是否包含 Access-Control-Allow-Origin 字段。该字段用于指定允许访问该资源的源。如果服务器没有在响应头中设置这个字段,浏览器会认为该请求不被允许,从而阻止脚本访问响应内容,即便服务器实际上已经成功返回了数据(状态码 200)。

错误信息分析

  • Access to XMLHttpRequest at \'http://192.168.72.130:8888/getUser\' from origin \'http://192.168.72.130:9999\' has been blocked by CORS policy: No \'Access-Control-Allow-Origin\' header is present on the requested resource.:明确指出是由于 CORS 策略的限制,请求被阻止,原因是响应头中没有 Access-Control-Allow-Origin 字段。
  • GET http://192.168.72.130:8888/getUser net::ERR_FAILED 200 (OK):这里的 net::ERR_FAILED 是浏览器给出的错误,虽然服务器返回了状态码 200(表示请求成功处理),但由于 CORS 策略的限制,浏览器没有将响应内容提供给脚本。

四、跨域问题解决

1、解决方案说明

使用add_header指令,该指令可以用来添加一些头信息

语法 add_header name value... 默认值 — 位置 http、server、location

此处用来解决跨域问题,需要添加两个头信息,一个是Access-Control-Allow-Origin,Access-Control-Allow-Methods

Access-Control-Allow-Origin: 直译过来是允许跨域访问的源地址信息,可以配置多个(多个用逗号分隔),也可以使用*代表所有源

Access-Control-Allow-Methods:直译过来是允许跨域访问的请求方式,值可以为 GET POST PUT DELETE...,可以全部设置,也可以根据需要设置,多个用逗号分隔

具体配置方式

location /getUser{   add_header Access-Control-Allow-Origin *;   add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE;   default_type application/json;   return 200 \'{\"id\":1,\"name\":\"TOM\",\"age\":18}\';}

2、配置
server { listen 8888; server_name localhost; gzip on; root /opt/nginx; location /getUser { #添加头部允许URL:http://192.168.72.130:9999进行访问 add_header Access-Control-Allow-Origin http://192.168.72.130:9999; #添加头部允许访问的方法 add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE; default_type application/json; return 200 \'{\"id\":\"123\",\"name\":\"小明\",\"age\":\"18\"}\'; }}

3、验证

浏览器输入:http://192.168.72.130:9999/  

跨域访问配置成功如下: