Ajax,fetch等http请求跨域产生的原因及其解决

跨域产生的原因

第一种: 浏览器的限制

浏览器会对请求进行安全的信息校验。

第二种: 跨域

调用方于被调用方的协议, 域名, 端口,任何一个不一样,都会产生跨域问题。

第三种: XHR (XMLHttpRequest)

只要发出去的请求类型(type), 不是xhr就不会产生跨域

解决思路

  1. 从浏览器限制入手, 只要更改相关的参数, 不让浏览器做相关的限制, 就可以解决跨域的问题。

  2. 只要发出去的请求不是Type是XHR,就行。所以更改成,json即可,也就是JSONP,但是此方法不推荐,因为要在用户端进行很多相关的操作,才能解决。

注意点:使用JSONP,不仅仅是修改前端的代码,后端的代码也需要相关的修改

  1. 从支持的跨域的角度来解决。

方法1:设置被调用方允许跨域。但是很多时候,服务器不是我们自己的,无从修改。

方法2:调用方做修改。(也就是,隐藏跨域: 通过一个代理,在浏览器里发出去的都是同一个域名(A)的请求, 但是到代理服务器之后,将指定的URL转到需要跨域的域名(B)里)

此次主要讲解,第三个思路来解决跨域问题。

解决方法

在这里插入图片描述

服务器端(被调用方)适配跨域

实现原理: 图中红色虚线部分

运行以下的代码方法: node 简单服务器文件名.js

  1. 解决: 两端不在同一个域中
//这个只是一个, 简单服务器的实现代码
const http = require('http');
http.createServer( (request, response) => {
  response.writeHead(200, {
    'Access-Control-Allow-Origin': '*' // 意思为允许所有域来访问此接口 设置这个便可以解决
  })
}).listen(8888);//服务器分配的端口号

console.log("开始运行服务端 PORT: 8888")
  1. 解决: 浏览器带Cookie访问服务器
    注意: 带Cookie访问, 服务端不能设置 ‘Access-Control-Allow-Origin’ 为 ‘*’
//这个只是一个, 简单服务器的实现
const http = require('http');
http.createServer( (request, response) => {
  if (request.headers['origin] != undefined ) { //如果为跨域请求, request中会有origin属性, 所以此种判断方法, 解决带Cookie跨域的情况
  	response.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://localhost:8887', // 意思为http://localhost:8887可以访问此接口
    'Access-Control-Allow-Credentials': 'true' //允许携带, Cookie访问的设置
  })
  } else {	//解决不带cookie的跨域
	response.writeHead(200, {
    'Access-Control-Allow-Origin': '*', // 意思为允许所有域来访问此
  	})
  }
}).listen(8888);//服务器分配的端口号

console.log("开始运行服务端 PORT: 8888")
  1. 解决: 带自定义头, 如果服务端没有事先设置允许携带相header,会出现跨域问题
//这个只是一个, 简单服务器的实现
const http = require('http');
http.createServer( (request, response) => {
	//先获取, 放出请求方中携带的自定义请求头的信息
  let headers_keys = () => {
	  let headers_keys = '';
	  for (let key in request.headers) {
	  	header_keys = header_keys + ',' + key;
	   }
	   return headers_keys;
  }
  //跨域响应头解决
  if (request.headers['origin] != null) { //如果为跨域请求, request中会有origin属性, 所以此种判断方法, 解决带Cookie跨域的情况
  	response.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://localhost:8887', // 意思为http://localhost:8887可以访问此接口
    'Access-Control-Allow-Credentials': 'true' //允许携带, Cookie访问的设置
    'Access-Control-Allow-Headers': headers_keys	//添加允许用户端自定义的头
  })
  } else {	//解决不带cookie的跨域
	response.writeHead(200, {
    'Access-Control-Allow-Origin': '*', // 意思为允许所有域来访问此
  	})
  }
}).listen(8888);//服务器分配的端口号

console.log("开始运行服务端 PORT: 8888")

用户端(调用方)隐藏跨域

原理: 图中黑色的虚线
过程: 用户端 --访问–> 本地代理服务器 --转发请求–> 真正需要请求的服务器
在这里插入图片描述

Nginx 方法 实现隐藏跨域

  1. 找到hosts文件
    在这里插入图片描述
  2. 打开文件增加本地虚拟域名b.com
    在这里插入图片描述
  3. 找到nginx下,以下图中的目录,创建文件 b.com.conf
    在这里插入图片描述
  4. 在 b.com.conf 文件中,输入以下代码
server{
	listen:80;
	server_name b.com
	location/{			
		proxy_pass http://localhost:8081/;        //把所有对.b.com的请求转发到此url
		}
	location/cors_server{		//这里为, 中转路径, 将访问 /cors_server 的请求, 转发到  http://localhost:8080/test/ 
		proxy_pas http://localhost:8080/test/;			//这里为, 需要跨域访问的url
		}
}
  1. 重启Nginx

总结

被调用方解决跨域问题, 需要修改被调用方的响应头中的内容, 达到跨域的目的, 但是这个方法有局限性, 当服务器不是自己的, 或者没有办法修改时, 比如腾讯, 百度的服务器, 你是无法修改的, 那么就要用调用方的解决方案的了, 也就是反向代理, 通过隐藏跨域, 浏览器看到的都是本域内的请求, 我们用户端的请求也的确时请求本域内的, 但是请求的不是, 最终需要请求的服务器, 而是访问本地代理的服务器, 通过代理服务器, 将我们的请求发出, 并返回相应的结果。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值