php跨域请求原理,跨域的几种实现方式与原理

在实际工作中,遇到前后端进行数据交互,经常会碰到请求跨域,今天就来探讨一下什么是跨域以及跨域的几种实现方式!

什么是跨域

同源策略(Same origin Policy)

浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。

a0b066c0c976?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

本域指的是?

需要注意的是: 对于当前页面来说页面存放的 JS 文件的域不重要,重要的是加载该 JS 页面所在什么域

请求跨域了,那么请求到底发出去没有?

看一下代码就会明白

HTML

HTML

饥人谷

var xhr = new XMLHttpRequest()

xhr.open('GET','http://127.0.0.1:8080/getWeather', true)

xhr.send()

xhr.onload = function(){

console.log(xhr.responseText)

}

js部分

var http = require('http')

var fs = require('fs')

var path = require('path')

var url = require('url')

http.createServer(function(req, res){

var pathObj = url.parse(req.url, true)

switch (pathObj.pathname) {

case '/getWeather':

res.end(JSON.stringify({beijing: 'sunny'}))

break;

default:

fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){

if(e){

res.writeHead(404, 'not found')

res.end('

404 Not Found

')

}else{

res.end(data)

}

})

}

}).listen(8080)

当前域名

a0b066c0c976?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

当前域名

用AJAX请求数据 是

a0b066c0c976?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

请求域名

请求结果

跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。

a0b066c0c976?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

状态显示已经成功

a0b066c0c976?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

你可能会疑问明明通过表单的方式可以发起跨域请求,为什么 Ajax就不会?因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF,因为请求毕竟是发出去了。

跨域解决方案

jsonp

JSONP是通过script 标签加载数据的方式去获取数据当做 JS代码来执行 提前在页面上声明一个函数,函数名通过接口传参的方式传给后台,后台解析到函数名后在原始数据上「包裹」这个函数名,发送给前端。换句话说,JSONP需要对应接口的后端的配合才能实现。

JSONP和AJAX对比

JSONP和AJAX相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。但AJAX属于同源策略,JSONP属于非同源策略(跨域请求)

JSONP优缺点

JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性,不安全可能会遭受XSS攻击。

实现方式

HTML 中 script标签可以加载其他域下的js,比如我们经常引入一个其他域下线上cdn的jQuery。那如何利用这个特性实现从其他域下获取数据呢?

可以先这样试试:

这时候会向天气接口发送请求获取数据,获取数据后做为 js 来执行。 但这里有个问题, 数据是 JSON 格式的数据,直接作为 JS 运行的话我如何去得到这个数据来操作呢?

这样试试:

这个请求到达后端后,后端会去解析callback这个参数获取到字符串showData,在发送数据做如下处理:

之前后端返回数据:{"city": "hangzhou", "weather": "晴天"} 现在后端返回数据showData({"city": "hangzhou", "weather": "晴天"})前端script标签在加载数据后会把 「showData({“city”: “hangzhou”, “weather”: “晴天”})」做为js来执行,这实际上就是调用showData这个函数,同时参数是 {“city”: “hangzhou”, “weather”: “晴天”}。 用户只需要在加载提前在页面定义好showData这个全局函数,在函数内部处理参数即可。

function showData(ret){

console.log(ret);

}

具体流程如下

声明一个回调函数,其函数名(如showData)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)。

创建一个

服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是showData,它准备好的数据是 show({"city": "hangzhou", "weather": "晴天"})。

最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用执行之前声明的回调函数(showData),对返回的数据进行操作。

以上就是JSONP(JSON with padding)。

CORS

CORS全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。 实现方式很简单,当你使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin(访问控制允许来源); 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的ajax 请求没啥区别,代码完全一样。

其实实现原理很简单

就是加上一句代码指定允许来源

res.setHeader('Access-Control-Allow-Origin','http://localhost:8080')

示例:

html部分

show news

$('.show').addEventListener('click', function(){

var xhr = new XMLHttpRequest()

xhr.open('GET', 'http://127.0.0.1:8080/getNews', true)

xhr.send()

xhr.onload = function(){

appendHtml(JSON.parse(xhr.responseText))

}

})

function appendHtml(news){

var html = ''

for( var i=0; i

html += '

' + news[i] + ''

}

$('.news').innerHTML = html

}

function $(selector){

return document.querySelector(selector)

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值