一、什么是跨域

同源策略是由Netscape提出的著名安全策略,是浏览器最核心、基本的安全功能,它限制了一个源(origin)中加载文本或者脚本与来自其他源(origin)中资源的交互方式
,所谓的同源就是指协议、域名、端口相同。
当浏览器执行一个脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域

二、出现跨域问题的情况

由于在工作中需要使用AJAX请求其他域名下的请求,但是会出现拒绝访问的情况,这是因为基于安全的考虑,AJAX只能访问本地的资源,而不能跨域访问。

比如说你的网站域名是aaa.com,想要通过AJAX请求bbb.com域名中的内容,浏览器就会认为是不安全的,所以拒绝访问。

会出现跨域问题的几种情况:

探讨跨域请求资源的几种方式

四、处理跨域的方法2 -- JSONP

原理
        其本质是利用了标签<img>||<script>具有可跨域的特性, 由服务端返回一个预先定义好的Javascript函数的调用,并且将服务器数据以该函数参数的形式传递过来, 此方法需要前后端配合完成。但是JSONP只支持 “GET” 请求,但不支持 “POST” 请求。

服务端JSONP格式数据

jsonp.php 文件代码

<?php
header('Content-type: application/json');
//获取回调函数名
$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
//json数据
$json_data = '["customername1","customername2"]';
//输出jsonp格式的数据
echo $jsoncallback . "(" . $json_data . ")";
?>

客户端页面完整代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 实例</title>
</head>
<body>
    <div id="divCustomers"></div>
    <script type="text/javascript">
function callbackFunction(result, methodName)
        {
            var html = '<ul>';
            for(var i = 0; i < result.length; i++)
            {
                html += '<li>' + result[i] + '</li>';
            }
            html += '</ul>';
            document.getElementById('divCustomers').innerHTML = html;
        }
</script>
<script type="text/javascript" src="http://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction"></script>
</body>
</html>

 
jQuery 使用 JSONP

缺点:

  1、这种方式无法发送post请求(这里

  2、另外要确定jsonp的请求是否失败并不容易,大多数框架的实现都是结合超时时间来判定。

跨域的几种方式

在项目中可能会需要在一个域名下请求另外一个域名的资源,下面我们来探讨下跨域的几种实现方式

1、jsonp

最常见的一种跨域方式,其背后原理就是利用了script标签不受同源策略的限制,在页面中动态插入了script,script标签的src属性就是后端api接口的地址,并且以get的方式将前端回调处理函数名称告诉后端,后端在响应请求时会将回调返还,并且将数据以参数的形式传递回去。

前端:

//http://127.0.0.1:8888/jsonp.html
var script = document.createElement('script');
script.src = 'http://127.0.0.1:2333/jsonpHandler?callback=_callback'
document.body.appendChild(script); //插入script标签
//回调处理函数 _callback
var _callback = function(obj){
for(key in obj){
console.log('key: ' + key +' value: ' + obj[key]);
}
}

后端:

//http://127.0.0.1:2333/jsonpHandler
app.get('/jsonpHandler', (req,res) => {
let callback = req.query.callback;
let obj = {
type : 'jsonp',
name : 'weapon-x'
};
res.writeHead(200, {"Content-Type": "text/javascript"});
res.end(callback + '(' + JSON.stringify(obj) + ')');
})

在jsonp.html中打开控制台可以看到返回数据的输出:

jsonp.png

2、CORS

Cross-Origin Resource Sharing(跨域资源共享)是一种允许当前域(origin)的资源(比如html/js/web service)被其他域(origin)的脚本请求访问的机制。
当使用XMLHttpRequest发送请求时,浏览器如果发现违反了同源策略就会自动加上一个请求头:origin,后端在接受到请求后确定响应后会在Response
Headers中加入一个属性:Access-Control-Allow-Origin,值就是发起请求的源地址(http://127.0.0.1:8888),浏览器得到响应会进行判断Access-Control-Allow-Origin的值是否和当前的地址相同,只有匹配成功后才进行响应处理。

现代浏览器中和移动端都支持CORS(除了opera mini),IE下需要8+

前端:

//http://127.0.0.1:8888/cors.html
var xhr = new XMLHttpRequest();
xhr.onload = function(data){
var _data = JSON.parse(data.target.responseText)
for(key in _data){
console.log('key: ' + key +' value: ' + _data[key]);
}
};
xhr.open('POST','http://127.0.0.1:2333/cors',true);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send();

后端:

//http://127.0.0.1:2333/cors
app.post('/cors',(req,res) => {
if(req.headers.origin){
res.writeHead(200,{
"Content-Type": "text/html; charset=UTF-8",
"Access-Control-Allow-Origin":'http://127.0.0.1:8888'
});
let people = {
type : 'cors',
name : 'weapon-x'
}
res.end(JSON.stringify(people));
}
})

可以在开发者工具里面看到请求的详细信息,并且在控制台也可以看到返回的数据输出:

response header.png

cors console.png

3、服务器跨域

在前后端分离的项目中可以借助服务器实现跨域,具体做法是:前端向本地服务器发送请求,本地服务器代替前端再向api服务器接口发送请求进行服务器间通信,本地服务器其实就是个中转站的角色,再将响应的数据返回给前端,下面用node.js做一个示例

前端:

//http://127.0.0.1:8888/server
var xhr = new XMLHttpRequest();
xhr.onload = function(data){
var _data = JSON.parse(data.target.responseText)
for(key in _data){
console.log('key: ' + key +' value: ' + _data[key]);
}
};
xhr.open('POST','http://127.0.0.1:8888/feXhr',true); //向本地服务器发送请求
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send("url=http://127.0.0.1:2333/beXhr"); //以参数形式告知需要请求的后端接口

后端:

//http://127.0.0.1:8888/feXhr
app.post('/feXhr',(req,res) => {
let url = req.body.url;
superagent.get(url) //使用superagent想api接口发送请求
.end(function (err,docs) {
if(err){
console.log(err);
return
}
res.end(docs.res.text); //返回到前端
})
}) //http://127.0.0.1:2333/beXhr
app.get('/beXhr',(req,res) => {
let obj = {
type : 'superagent',
name : 'weapon-x'
};
res.writeHead(200, {"Content-Type": "text/javascript"});
res.end(JSON.stringify(obj)); //响应
})

回到 http://127.0.0.1:8888/server 页面打开控制台可以看到数据输出:

五、处理跨域的方法3 -- XHR2

“XHR2” 全称 “XMLHttpRequest Level2” 是HTML5提供的方法,对跨域访问提供了很好的支持,并且还有一些新的功能。

* IE10以下的版本都不支持

* 只需要在服务器端头部加上下面两句代码:

header( "Access-Control-Allow-Origin:*" );

header( "Access-Control-Allow-Methods:POST,GET" );

ajax处理跨域有几种方式的更多相关文章

  1. php跨域的几种方式

    PHP实现跨域的几种形式 1.JSONP(JSON with padding)原理 利用html里面script标签可以加载其他域下的js这一特性,使用script src的形式来获取其他域下的数据, ...

  2. ajax 跨域的几种方式

    网络上跨域的文章大多一样,这里我写下,巩固下自己的知识,顺便做个记录 什么是跨域 这里简单拿百度的网址做个例子:http://www.baidu.com:80 (默认都是80端口.可省略) http ...

  3. AJAX实现跨域的三种方法

    由于在工作中需要使用AJAX请求其他域名下的请求,但是会出现拒绝访问的情况,这是因为基于安全的考虑,AJAX只能访问本地的资源,而不能跨域访问. 比如说你的网站域名是aaa.com,想要通过AJAX请 ...

  4. 深入浅出:了解jsonp跨域的九种方式

    什么是“”跨域”: 跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容.由于安全原因,跨域访问是被各大浏览器所默认禁止的.当一个域与其他域建立了信 ...

  5. SpringBoot 中实现跨域的几种方式

    一.为什么会出现跨域问题 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响. ...

  6. 跨域的几种方式以及call(),apply() bind()方法的作用和区别

    jsonp: jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议. 一个是描述信息的格式,一个是信息传递 ...

  7. Springboot设置跨域的三种方式

    方式一(精细配置) 在需要跨域的整个Controller或者单个方法上添加@CrossOrigin注解 方式二(全局配置) @Configuration public class WebMvcConf ...

  8. SpringBoot设置跨域的几种方式

    什么是跨域? 浏览器从一个域名的网页去请求另一个域名的资源时,域名.端口.协议任一不同,都是跨域 原因: 由于浏览器的同源策略, 即a网站只能访问a网站的内容,不能访问b网站的内容. 注意: 跨域问题 ...

  9. jQuery的ajax jsonp跨域请求

    了解:ajax.json.jsonp.“跨域”的关系 要弄清楚以上ajax.json.jsonp概念的关系,我觉得弄清楚ajax是“干什么的”,“怎么实现的”,“有什么问题”,“如果解决存在的问题”等 ...

随机推荐

  1. UWP:可滚动的PivotHeader

    UWP开发里,Pivot真是个令人又爱又恨的控件.为了实现某些可滚动Header的效果,有些大佬甚至去掉了原本的Header,使用一个ListView或者ListBox自己画Header,不过这样会让 ...

  2. Spring Boot 2.0(五):Docker Compose + Spring Boot + Nginx + Mysql 实践

    我知道大家这段时间看了我写关于 docker 相关的几篇文章,不疼不痒的,仍然没有感受 docker 的便利,是的,我也是这样认为的,I know your felling . 前期了解概念什么的确实 ...

  3. jmeter常见问题汇总

    Aggregate Report 是 JMeter 常用的一个 Listener,中文被翻译为"聚合报告".今天再次有同行问到这个报告中的各项数据表示什么意思,顺便在这里公布一下, ...

  4. Online database documentation.

    贫道2018年1月正式出道,可以说在IT界我就是个菜鸟.但我有着一颗不服输的心,我相信我会在这条路走上巅峰之道的.下面我来写我的第一份学习笔记: 介绍:大多数公司都有自己的数据文档,估计大多数都是用P ...

  5. 【动态规划】滚动数组的求解(C++)

    虽然接触动态规划算法已经有一段时间,给一个01背包问题,能够做到一个表格简单粗暴下去,然后求得结果,但心里总觉得对这个算法理解十分不到位,抱着对算法的热爱,网上很多大牛的算法思维实在让我佩服的五体投地 ...

  6. OSM数据下载地址

    1.OSM数据下载地址 官网下载: http://planet.openstreetmap.org/ GeoFabrik:http://www.geofabrik.de/ Metro Extracts ...

  7. 在Python中使用Redis

    在Python中要使用Redis数据库,首先要安装redis 之前的博客中有写到在命令行模式下操作Redis数据库. 要在项目中使用的话可以这么做: 通过初始化 redis.Redis,得到返回的对象 ...

  8. eclipse如何debug调试jdk源码(任何源码)并显示局部变量

    最近要看struts2源码 仿照了一下查看jdk源码的方式 首先你要有strtus2的jar包和源码,在struts官网上下载时,选择full版本,里面会有src也就是源码了. jar导入项目,保证可 ...

  9. Beat冲刺报告---Day0

    Beta阶段报告---Day0 1.需要改进完善的功能   我们上一阶段开发由于开发时间匆忙,对于爬虫耗时的优化没有考虑.优化的空间我在Alpha阶段的总结报告里说过,具体看下图.   这张图显示出爱 ...

  10. scrapy 避免被ban

    1.settings.pyCOOKIES_ENABLED = False DOWNLOAD_DELAY = 3 ROBOTSTXT_OBEY = Falseip代理池设置 IPPOOL = [{'ip ...