前言
我们经常会在页面上使用 ajax 请求访问其他服务器的数据,此时,客户端发送的请求就属于跨域请求 . 实际应用中,成功发送一个跨域请求有一定要求,今天我们就来了解一下这些要求。
HTML 中支持跨域的标签
让 JavaScript 支持跨域的其他方式
《 1 》 jsonp 方式实现跨域(以 php 为例)
有些网站出于安全考虑, 不会设置允许跨域, 而我们又刚好需要用到一次跨域请求, 那么, jsonp 就派上用场了:
现在问题来了?什么是 jsonp ?维基百科的定义是: JSONP ( JSON with Padding )。 JSONP 也叫填充式 JSON ,是应用 JSON 的一种新方法,只不过是被包含在函数调用中的 JSON ,例如:
callbackfunction({"name","trigkit4"});
JSONP 由两部分组成:回调函数和 JSON 数据。回调函数是当响应到来时应该在页面中调用的函数,而 JSON 数据就是传入回调函数中的参数。
php 代码:
$callback = $this->request->param('callback'); $employees = ["employees"=> [ ["id"=>10001, "name"=>"马云", "age"=>"88", "job"=>"CEO", "salary"=>"10000万", "isAdmin"=>true, "entryTime"=>"2001-10-1 17:05"], ["id"=>10002, "name"=>"马化腾", "age"=>"77", "job"=>"CEO", "salary"=>"10000万", "isAdmin"=>true, "entryTime"=>"2002-10-2 17:05"], ["id"=>10003, "name"=>"李彦宏", "age"=>"66", "job"=>"CEO", "salary"=>"10000万", "isAdmin"=>true, "entryTime"=>"2003-10-3 17:05"], ["id"=>10004, "name"=>"老马", "age"=>"28", "job"=>"web前端高级软件开发工程师", "salary"=>"10000万", "isAdmin"=>false, "entryTime"=>"2004-10-4 17:05"], ["id"=>10005, "name"=>"老张", "age"=>"26", "job"=>"web前端高级软件开发工程师", "salary"=>"10000万", "isAdmin"=>false, "entryTime"=>"2005-10-5 17:05"] ] ]; $d = json_encode($employees); echo $callback.'('.$d.')';
这段 php 代码清晰展示了后台语言做了哪些操作。只是个例子,无法直接拷贝使用,前端开发人员可以忽略。
访问:
这里正是利用了 script 标签本身支持跨域访问资源的特性,因此完成了跨域。
请求响应为:
hello( { employees: [ { id: 10001, name: "马云", age: "88", job: "CEO", salary: "10000万", isAdmin: true, entryTime: "2001-10-1 17:05" }, { id: 10002, name: "马化腾", age: "77", job: "CEO", salary: "10000万", isAdmin: true, entryTime: "2002-10-2 17:05" }, { id: 10003, name: "李彦宏", age: "66", job: "CEO", salary: "10000万", isAdmin: true, entryTime: "2003-10-3 17:05" }, { id: 10004, name: "老马", age: "28", job: "web前端高级软件开发工程师", salary: "10000万", isAdmin: false, entryTime: "2004-10-4 17:05" }, { id: 10005, name: "老张", age: "26", job: "web前端高级软件开发工程师", salary: "10000万", isAdmin: false, entryTime: "2005-10-5 17:05" } ] } )
可以看出,响应格式为: hello( json 数据 ) ; 这是一个标准的 js 函数调用语句。 于是乎, 在 js 中我们只需要定义一个同名的 js 函数就可以了:
function hello(data) { console.log(data); }
这个函数被调用时,参数部分传入的就是从其他域获取的数据,至此,跨域资源共享已经实现。
JSONP 的优点:它不像 XMLHttpRequest 对象实现的 Ajax 请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要 XMLHttpRequest 或 ActiveX 的支持;并且在请求完毕后可以通过调用 callback 的方式回传结果。
JSONP 的缺点:它只支持 GET 请求而不支持 POST 等其它类型的 HTTP 请求;它只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题。
《 2 》在后端程序中设置响应头(以 php 为例)
代码如下:
//允许从 yantianfeng.com 发起的跨域请求 header("Access-Control-Allow-Origin: yantianfeng.com"); //如果需要设置允许所有域名发起的跨域请求,可以使用通配符 * header("Access-Control-Allow-Origin: *");
这种设置是由后端开发人员操作的,无需前端配合;对于前端开发人员来说就是福音,前端无需做任何配置、准备,正常请求数据即可完成跨域。
当然,如果希望 整个网站允许跨域请求,可以参考第三种设置:
《 3 》在服务器中设置响应头(以 IIS 为例)
打开 IIS ,找到 "HTTP 响应标头 " 点进去,在右侧可以看到【添加】按钮,点击添加并加入如下标头即可:
Access - Control - Allow - Headers : Content - Type , api_key , Authorization
Access - Control - Allow - Origin :*
效果如下: