关于前端开发的跨域问题以及解决方法jsonp
2016-10-12 10:50
776 查看
对于一名初级的Web前端开发工程师来说,刚进入这个行业应该会经历这样的一个面试问题,那就是跨域问题。
什么是跨域呢?首先我们先来了解一下域名地址这个概念。
一个域名地址的组成:
协议+子域名+主域名+端口号+请求资源
http:// www . abc.com : 8080 / scripts/jquery.js
当这几个中有任意一个不相同时,都算作不同域。
不同域之间相互请求资源,我们就叫做“跨域”。
比如:http://www.abc.com/index.html请求http://www.efg.com/service.php
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。因为JavaScript同源策略的限制,a.com域名下的js无法操作b.com或者是c.com域名下的对象。
比如:
www.abc.com/index.html 调用 www.abc.com/service.php( 非跨域 )
www.abc.com/index.html 调用 www.efg.com/service.php( 跨域 )
www.abc.com/index.html 调用 bbs.abc.com/service.php( 跨域 )
www.abc.com/index.html 调用 www.abc.com:81/service.php( 跨域 )
www.abc.com/index.html 调用 https://www.abc.com/service.php( 跨域 )
服务器端代码 serverjson.php
运行结果
说明此时访问是成功的。
接下来改成跨域访问
对上面客户端的代码做下小小的改动:
运行结果:
因为域名发生了改变,所以构成了跨域访问。
不足:
只能使用 GET 方法发起请求,这是由于 script 标签自身的限制决定的。
客户端代码POST请求部分改为:
服务器端代码:
运行之后则成功了!
什么是跨域呢?首先我们先来了解一下域名地址这个概念。
一个域名地址的组成:
协议+子域名+主域名+端口号+请求资源
http:// www . abc.com : 8080 / scripts/jquery.js
当这几个中有任意一个不相同时,都算作不同域。
不同域之间相互请求资源,我们就叫做“跨域”。
比如:http://www.abc.com/index.html请求http://www.efg.com/service.php
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。因为JavaScript同源策略的限制,a.com域名下的js无法操作b.com或者是c.com域名下的对象。
比如:
www.abc.com/index.html 调用 www.abc.com/service.php( 非跨域 )
www.abc.com/index.html 调用 www.efg.com/service.php( 跨域 )
www.abc.com/index.html 调用 bbs.abc.com/service.php( 跨域 )
www.abc.com/index.html 调用 www.abc.com:81/service.php( 跨域 )
www.abc.com/index.html 调用 https://www.abc.com/service.php( 跨域 )
实例
客户端代码 jQueryAjax.html<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>jQuery封装的Ajax库</title> <style> body, input, select, button, h1 { font-size: 28px; line-height:1.7; } </style> </head> <body> <h1>员工查询</h1> <label>请输入员工编号:</label> <input type="text" id="keyword" /> <button id="search">查询</button> <p id="searchResult"></p> <h1>员工新建</h1> <label>请输入员工姓名:</label> <input type="text" id="staffName" /><br> <label>请输入员工编号:</label> <input type="text" id="staffNumber" /><br> <label>请选择员工性别:</label> <select id="staffSex"> <option>女</option> <option>男</option> </select><br> <label>请输入员工职位:</label> <input type="text" id="staffJob" /><br> <button id="save">保存</button> <p id="createResult"></p> <script type="text/javascript" src="jquery-1.12.1.js" ></script> <script> $(function(){ $("#search").click(function(){ $.ajax({ type:"GET", 4000 url:"http://localhost/AjaxDemo/serverjson.php?number="+$("#keyword").val(), dataType:"json", success:function(data){ if(data.success){ $("#searchResult").html(data.msg); }else{ $("#searchResult").html("出现错误:"+data.msg); } }, error:function(jqXHR){ alert("发生错误:"+jqXHR.status); }, }); }); $("#save").click(function(){ $.ajax({ type:"POST", url:"http://localhost/AjaxDemo/serverjson.php", data:{ name:$("#staffName").val(), number: $("#staffNumber").val(), sex: $("#staffSex").val(), job: $("#staffJob").val() }, dataType: "json", success: function(data){ if (data.success) { $("#createResult").html(data.msg); } else { $("#createResult").html("出现错误:" + data.msg); } }, error: function(jqXHR){ alert("发生错误:" + jqXHR.status); }, }); }); }); </script> </body> </html>
服务器端代码 serverjson.php
<?php header("Content-Type: application/json;charset=utf-8"); //定义一个多维数组,包含员工的信息,每条员工信息为一个数组 $staff = array ( array("name" => "洪七", "number" => "101", "sex" => "男", "job" => "总经理"), array("name" => "郭靖", "number" => "102", "sex" => "男", "job" => "开发工程师"), array("name" => "黄蓉", "number" => "103", "sex" => "女", "job" => "产品经理") ); //判断如果是get请求,则进行搜索;如果是POST请求,则进行新建 //$_SERVER是一个超全局变量,在一个脚本的全部作用域中都可用,不用使用global关键字 //$_SERVER["REQUEST_METHOD"]返回访问页面使用的请求方法 if ($_SERVER["REQUEST_METHOD"] == "GET") { search(); } elseif ($_SERVER["REQUEST_METHOD"] == "POST"){ create(); } //通过员工编号搜索员工 function search(){ //检查是否有员工编号的参数 //isset检测变量是否设置;empty判断值为否为空 //超全局变量 $_GET 和 $_POST 用于收集表单数据 if (!isset($_GET["number"]) || empty($_GET["number"])) { echo '{"success":false,"msg":"参数错误"}'; return; } //函数之外声明的变量拥有 Global 作用域,只能在函数以外进行访问。 //global 关键词用于访问函数内的全局变量 global $staff; //获取number参数 $number = $_GET["number"]; $result = '{"success":false,"msg":"没有找到员工。"}'; //遍历$staff多维数组,查找key值为number的员工是否存在,如果存在,则修改返回结果 foreach ($staff as $value) { if ($value["number"] == $number) { $result = '{"success":true,"msg":"找到员工:员工编号:' . $value["number"] . ',员工姓名:' . $value["name"] . ',员工性别:' . $value["sex"] . ',员工职位:' . $value["job"] . '"}'; break; } } echo $result; } //创建员工 function create(){ //判断信息是否填写完全 if (!isset($_POST["name"]) || empty($_POST["name"]) || !isset($_POST["number"]) || empty($_POST["number"]) || !isset($_POST["sex"]) || empty($_POST["sex"]) || !isset($_POST["job"]) || empty($_POST["job"])) { echo '{"success":false,"msg":"参数错误,员工信息填写不全"}'; return; } //TODO: 获取POST表单数据并保存到数据库 //提示保存成功 echo '{"success":true,"msg":"员工:' . $_POST["name"] . ' 信息保存成功!"}'; } ?>
运行结果
说明此时访问是成功的。
接下来改成跨域访问
对上面客户端的代码做下小小的改动:
//GET url:"http://127.0.0.1/AjaxDemo/serverjson.php?number="+$("#keyword").val(), //POST url:"http://127.0.0.1/AjaxDemo/serverjson.php",
运行结果:
因为域名发生了改变,所以构成了跨域访问。
处理跨域的方法–JSONP(JSON with padding )
JSONP 是 JSON 的一种使用模式,可以解决主流浏览器的跨域数据访问问题。其原理是根据 XmlHttpRequest 对象受到同源策略的影响,而<script>标签元素却不受同源策略影响,可以加载跨域服务器上的脚本,网页可以从其他来源动态产生 JSON 资料。用 JSONP 获取的不是 JSON 数据,而是可以直接运行的 JavaScript 语句。
不足:
只能使用 GET 方法发起请求,这是由于 script 标签自身的限制决定的。
客户端代码POST请求部分改为:
$("#search").click(function(){ $.ajax({ type:"GET", url:"http://127.0.0.1/AjaxDemo/serverjson.php?number="+$("#keyword").val(), dataType:"jsonp", jsonp:"callback", success:function(data){ if(data.success){ $("#searchResult").html(data.msg); }else{ $("#searchResult").html("出现错误:"+data.msg); } }, error:function(jqXHR){ alert("发生错误:"+jqXHR.status); }, }); });
服务器端代码:
<?php header("Content-Type: application/json;charset=utf-8"); //定义一个多维数组,包含员工的信息,每条员工信息为一个数组 $staff = array ( array("name" => "洪七", "number" => "101", "sex" => "男", "job" => "总经理"), array("name" => "郭靖", "number" => "102", "sex" => "男", "job" => "开发工程师"), array("name" => "黄蓉", "number" => "103", "sex" => "女", "job" => "产品经理") ); //判断如果是get请求,则进行搜索;如果是POST请求,则进行新建 //$_SERVER是一个超全局变量,在一个脚本的全部作用域中都可用,不用使用global关键字 //$_SERVER["REQUEST_METHOD"]返回访问页面使用的请求方法 if ($_SERVER["REQUEST_METHOD"] == "GET") { search(); } elseif ($_SERVER["REQUEST_METHOD"] == "POST"){ create(); } //通过员工编号搜索员工 $jsonp=$_GET["callback"]; //检查是否有员工编号的参数 //isset检测变量是否设置;empty判断值为否为空 //超全局变量 $_GET 和 $_POST 用于收集表单数据 if (!isset($_GET["number"]) || empty($_GET["number"])) { echo '{"success":false,"msg":"参数错误"}'; return; } //函数之外声明的变量拥有 Global 作用域,只能在函数以外进行访问。 //global 关键词用于访问函数内的全局变量 global $staff; //获取number参数 $number = $_GET["number"]; //callback()注意有括号 $result = $jsonp.'({"success":false,"msg":"没有找到员工。"})'; //遍历$staff多维数组,查找key值为number的员工是否存在,如果存在,则修改返回结果 foreach ($staff as $value) { if ($value["number"] == $number) { $result = $jsonp.'({"success":true,"msg":"找到员工:员工编号:' . $value["number"] . ',员工姓名:' . $value["name"] . ',员工性别:' . $value["sex"] . ',员工职位:' . $value["job"] . '"})'; break; } } echo $result; } //创建员工 function create(){ //判断信息是否填写完全 if (!isset($_POST["name"]) || empty($_POST["name"]) || !isset($_POST["number"]) || empty($_POST["number"]) || !isset($_POST["sex"]) || empty($_POST["sex"]) || !isset($_POST["job"]) || empty($_POST["job"])) { echo '{"success":false,"msg":"参数错误,员工信息填写不全"}'; return; } //TODO: 获取POST表单数据并保存到数据库 //提示保存成功 echo '{"success":true,"msg":"员工:' . $_POST["name"] . ' 信息保存成功!"}'; } ?>
运行之后则成功了!
相关文章推荐
- 关于TP5视图分离到根目录的解决方法 原有: 为了方便前端开发,我想把视图(view)部分分离出来专门给前端进行修改 过程:在进行视图设置分离的过程遇到了问题 参考了官方文档http://www
- 跨域请求问题以及相关解决方法之JSONP
- 关于使用SuperMap以及开发中一些问题的解决方法。
- 关于android开发时,eclipse的函数自动提示功能很卡的问题解决方法
- 开发与部署的讨论以及最近遇到问题及其解决方法(大杂烩)
- 【原创】关于html+ashx开发中几个问题的解决方法
- 关于在做java的Web开发中遇到跨域访问的问题的解决方法汇总
- 关于修改frameworks的源码遇到的一点问题以及解决方法
- 关于Cookie跨域操作遇到的问题及解决方法
- 关于html+ashx开发中几个问题的解决方法
- 关于html+ashx开发中几个问题的解决方法
- ASP.NET MVC3开发中遇到问题以及解决方法
- 关于CSS+DIV 开发 与各浏览器的兼容性问题..解决方法.
- flex关于跨域访问会引起安全沙箱问题,下面是在网上找到的解决安全沙箱问题的方法
- 关于html+ashx开发中几个问题的解决方法
- 关于 clock_gettime() 的一个问题以及解决方法
- 关于std::fstream以及std::ifstream打开中文路径名失败的问题和解决方法
- 关于CSS+DIV 开发 与各浏览器的兼容性问题及解决方法
- Ubuntu下Eclipse 配置开发C以及小问题,小疑问的解决方法
- 关于图片资源在android2.1/2.2/2.3下无法显示的问题以及解决方法