前端跨域问题各种解决方式及原理

跨域的各种解决方式及原理

因为浏览器有某些安全级别的限制,例如,同源策略,所以在进行浏览器端的web应用开发的时候,经常会遇到跨域问题。

同源策略:只有在同源的情况下(同域名,同协议,同端口)才能进行数据交互

跨域问题报错:XMLHttpRequest cannot load https://api.douban.com/v2/movie/in_theaters. No ‘Access-Control-Allow-Origin‘ header is present on the requested resource. Origin ‘http://127.0.0.1:5500‘ is therefore not allowed access.

当我们在公司开发的时候,很可能因为后端的服务器和我们的本地服务器不同源所以产生跨域问题,还有当我们公司的服务器有很多,其中很可能会有单独的数据服务器,开发应用的时候必然会有跨域,所以解决跨域问题是前端工程师必要的技能。

常用的跨域方式:jsonp,cors,服务端代理

jsonp(JSON with Padding)

jsonp是一种前后端结合的跨域问题解决方式

原理:动态的创建script标签,将script标签的src属性设置成请求的目标地址,和后端商议之后,设置callback回调函数,利用回调函数来接收数据并进行使用

为什么使用script:

依靠html中标签的src属性不受同源策略的影响来实现的,而script标签接收到数据之后可以进行数据的处理,所以一般选用script标签,

为什么要动态的创建script标签:

script只能执行一次或者说只能请求一次,所以说当我们要不断的进行jsonp请求的时候,每一次的请求都需要一个script标签,所以需要动态去创建script标签,script标签能将请求到的字符串数据当成js代码去运行,所以我们可以依靠后端返回一段(执行某个函数,且给此函数传入数据)的这样一段字符串来实现,这样的话,script请求到该字符串之后,就会执行该函数,且该函数能接收到数据。

为什么需要和后端商议之后才能设置callback函数:

因为后端开发者并不知道前端准备来接收数据的函数是哪个函数,所以需要让前端通知后端接收数据的函数名,前端需要将函数名传递给后端,但是传递的时候是以键值对的方式传递过去的,所以需要前端将键值对的键名事先告知后端

注意:获取数据且操作完成后,一定要将创建的script标签去掉,将随机函数的内存给释放

缺点: 只能做get请求

CORS

这是一种纯后端的跨域方式

因为每次请求的时候请求头信息都会被携带到目标服务器,目标服务器经过判断选择是否运行访问,不允许的时候就出现了跨域问题,所以我们可以可以让后端开发人员对后端目标服务器进行设置,使其能识别我们的服务器的请求头并允许访问,这就是cors,cors主要是靠后端设置:Access-Control-Allow-Origin

node:

res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
res.writeHead(200,{‘Content-Type‘:‘application/json; charset=utf-8‘})
let data = {status:1,data:‘hello world‘}
res.end(JSON.stringify(data))

proxy

这也属于服务器代理的跨域处理方式

因为服务端之间的数据请求没有跨域限制,所以我们借助一个中间的代理服务器去像目标服务器发送请求:

前端代码:
let target = ‘https://api.douban.com/v2/book/search‘
let proxy = ‘http://localhost:3000‘
$.ajax({
url:proxy+‘/v2/book/search‘,//向proxy服务器发送请求,后面的path之类的其实是target域的path
data:{
target:‘https://api.douban.com‘,//告诉proxy服务器,我们真正像请求的目标服务器是谁
tag:‘励志‘
},
success(result){
console.log(result)
}
})

代理服务器:

const http = require(‘http‘)
const url_util = require(‘url‘)
const path = require(‘path‘)

const cross = require(‘./module/cross‘)

http.createServer((req,res)=>{
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");

// http://localhost:3000/v2/book/search?target=..params=...
let url_info = url_util.parse(req.url,true)

let {target} = url_info.query

delete url_info.query.target

let params = url_info.query
//向真正的目标服务器发送请求
let real_url = target+url_info.pathname

let method = req.method

cross(real_url,method,params,(result)=>{
res.writeHead(200,{‘Content-Type‘:"application/json;charset=utf8"})
res.end(JSON.stringify(result))
})

}).listen(3000)

cross跨域模块工具:

const url_util = require(‘url‘)
const qs = require(‘querystring‘)
const cross = (url,method,params,cb)=>{
//向url发送请求
//目标源的协议
let url_info = url_util.parse(url)

let protocol = url_info.protocol.replace(‘:‘,‘‘)
//引入到对应的模块
let http = require(protocol)

let data = qs.stringify(params)

let options = {
hostname: url_info.hostname,
port: url_info.port||((protocol)=>{return protocol==‘http‘?80:443})(protocol),
path: url_info.path,
method: method
}

if(method==‘post‘){
options.headers = {
‘Content-Type‘: ‘application/x-www-form-urlencoded‘,
‘Content-Length‘: data.length
}
}else{
let symbol = url_info.path.indexOf(‘?‘)>=0?‘&‘:‘?‘
options.path = url_info.path+symbol+data
console.log(options.path)
}

let req = http.request(options,(res)=>{
let result = ‘‘
res.on(‘data‘,(chunk)=>{result+=chunk})
res.on(‘end‘,(chunk)=>{cb(result)})
})

if(method==‘post‘){
req.write(data)
}

req.end()

}

module.exports = cross

原文地址:https://www.cnblogs.com/lisaShare/p/9007469.html

时间: 2024-10-21 21:35:49

前端跨域问题各种解决方式及原理的相关文章

JQuery的Ajax跨域请求的解决方式

今天在项目中须要做远程数据载入并渲染页面,直到开发阶段才意识到ajax跨域请求的问题,隐约记得Jquery有提过一个ajax跨域请求的解决方式,于是即刻翻出Jquery的API出来研究,发现JQuery对于Ajax的跨域请求有两类解决方式,只是都是仅仅支持get方式. 各自是JQuery的 jquery.ajax jsonp格式和jquery.getScript方式. 什么是jsonp格式呢?API原文:假设获取的数据文件存放在远程server上(域名不同,也就是跨域获取数据).则须要使用jso

前端跨域问题的解决

1.为什么会出现跨域问题 web浏览器中包含JavaScript解释器,也就是说,一旦载入Web页面,就可以任意的JavaScript代码在计算机里执行.安全隐患也就随之而来,所以由Netscape提出了一个著名的安全策略--同源策略,即JavaScript脚本不能读取从不同服务器载入的文档的内容. 2.同源策略的具体情况 一个完整的url地址包括: 协议名://域名:端口号/资源路径 URL 说明 是否允许通信 http://www.a.com/index.html ftp://www.a.c

jquery ajax跨域的完美解决方法(jsonp方式)

ajax跨域请求的问题,JQuery对于Ajax的跨域请求有两类解决方案,不过都是只支持get方式,接下来为大家详细介绍下客户端JQuery.ajax的调用代码 今天在项目中需要做远程数据加载并渲染页面,直到开发阶段才意识到ajax跨域请求的问题,隐约记得Jquery有提过一个ajax跨域请求的解决方式,于是即刻翻出Jquery的API出来研究,发 JQuery对于Ajax的跨域请求有两类解决方案,不过都是只支持get方式.分别是JQuery的 jquery.ajax jsonp格式和jquer

前端跨域几种方式

跨域问题的直接原因是浏览器存在同源策略,浏览器同源指的是:两个页面的协议.端口和主机相同,则两个页面具有相同的源.IE下满足协议.主机相同,就认为是同源. 想象一下,如果没有同源策略,谁都可以修改你站点上的内容,读取你的cookie,后果难以想象 前端跨域的几种方式 修改document.domain document.domain 用来获取当前网页的域名,document.domain可以被赋值 document.domain只能修改成当前域名的主域名或者基础域名,如当前域名是b.360.cn

浏览器禁止跨域访问及解决: No 'Access-Control-Allow-Origin' header is present on the requested resource.

一.出现报错 二.原因: 1.跨域访问是浏览器做的一个保护机制(html5页面需要浏览器渲染) 2.如果页面所访问的后端没有部署在同一个浏览器也会报错 三.跨域问题的解决方式: A.通过后端访问后端的方式解决.     B.通过页面的漏洞来解决--jsonp(不常用) C.现在浏览器支持cors,当然需要我们后端代码也要支持跨域,springMVC是支持cors 写一个配置类:通过接口WebMvcConfigurer来放行跨区域访问 注意事项: 1.跨区域的路径必须是全路径(URL+端口号) 如

解决前端跨域请求的几种方式

利用 JSONP 实现跨域调用 说道跨域调用,可能大家首先想到的或者听说过的就是 JSONP 了. 1.1 什么是JSONP JSONP 是 JSON 的一种使用模式,可以解决主流浏览器的跨域数据访问问题.其原理是根据 XmlHttpRequest 对象受到同源策略的影响,而 <script> 标签元素却不受同源策略影响,可以加载跨域服务器上的脚本,网页可以从其他来源动态产生 JSON 资料.用 JSONP 获取的不是 JSON 数据,而是可以直接运行的 JavaScript 语句. 1.2

.net mvc webapi 解决前端跨域问题

跨域问题的原因不解释了,直接设置两步就可以解决前端跨域问题 1.Gloabel.asax文件中 //解决跨域问题 protected void Application_BeginRequest(object sender, EventArgs e) { RegisterRoutes(RouteTable.Routes); if (HttpContext.Current.Request.HttpMethod == "OPTIONS") { HttpContext.Current.Resp

JAVA解决前端跨域问题。

什么是跨域? 通俗来说,跨域按照我自己的想法来理解,是不同的域名之间的访问,就是跨域.不同浏览器,在对js文件进行解析是不同的,浏览器会默认阻止,所以 现在我来说下用java代码解决前端跨域问题. 用java代码解决前端跨域问题? 找到WEB-INF下面的web.xml文件,输入下面代码,在web.xml文件下面: 1 <!-- 解决跨域访问的问题 --> 2 <filter> 3 <filter-name>cors</filter-name> 4 <

解决vue+springboot前后端分离项目,前端跨域访问sessionID不一致导致的session为null问题

问题: 前端跨域访问后端接口, 在浏览器的安全策略下默认是不携带cookie的, 所以每次请求都开启了一次新的会话. 在后台打印sessionID我们会发现, 每次请求的sessionID都是不同的, 既然每次请求都是一个新的会话, 那我们去获取session的时候自然就是null了. 解决办法如下: 环境: vue 2.0 springboot 2.1.6 一.前端部分 1.  在vue引入axios的位置添加以下代码 import axios from 'axios' axios.defau