在前端开发过程中,难免和服务端产生数据交互。一般情况我们的请求分为这么几种情况:

  1. 只关注发送,不关注接收
  2.不仅要发送,还要关注服务端返回的信息

      a.  同域请求
      b.  跨域请求

所谓 跨域,一般情况下为三种情况:跨协议、跨子域、跨域名。下面距离梳理一下这三种情况。

跨协议:比如说我现在的域名地址是http://www.12306.cn,有一些请求需要发送到https://www.12306.cn,此时这个请求相对与http://www.12306.cn来说就是跨协议的请求
跨子域:比如说我现在是http://www.12306.cn,在登录的时候需要请求http://passport.12306.cn这个接口,此时这个请求就是跨子域的请求
跨域名:我们都知道现在的12306添加新的常用联系人的时候需要验证身份证号码,据说校验身份证号和姓名是否匹配只有公安部才有这个接口,并且使用费用相当高(扯远了),此时需要请求公安部的服务接口,此时从12306发出的请求就需要跨域名了

跨域请求只要满足这是三种情况之一就会被认定为跨域请求。
目前流行比较广的跨域请求解决方案有:window.name、document.domain、服务端代理、jsonp、前端代理。
以下介绍的方式只是实现原理,没有过多考虑安全性,可以根据自己的情况进行选择。

window.name
前端发送一个请求给隐藏的iframe,然后服务端每次将返回值,以js形式返回,然后iframe的父窗口获取window.name的值。服务端返回数据形式为:

<script>window.name={errno:0, errmsg:'ok'}</script>

document.domain
这个使用限制条件较多,必须是不同子域间,协议和端口号必须相同。比如:a.12306.cn和b.12306.cn之间相互操作,可以分别在两个域名下定义:document.domain = '12306.cn'; 这样就实现了跨子域通信。 服务端代理
这种情况不适合跨协议通信,比较适合跨端口和跨域名。这个前端基本上相当于普通的请求,我们所要访问的接口都经过服务端的代理,我们访问的请求都是本域的。 jsonp请求
我们用的比较多,原理就是在发起请求时,动态的在页面加载一个script标签,因为src可以接收跨域资源,然后这个script标签的资源是执行一个js方法,并且将服务端返回的数据作为参数传递过来。这种情况唯一的缺点就是只能发送get请求,不适用用post请求。jsonp返回的数据格式为:
callback({errno:0,errmsg:'ok'}); 前端代理
和window.name的实现比较类似,将请求发送到一个隐藏的iframe,然后服务端返回类似这样的内容:
<script>location.href='http://www.12306.cn/proxy.html?func=callback&errno=0&errmsg=ok'</script>

然后proxy文件,接收到这些参数,进行处理,转化成类似与jsonp的返回值,执行页面上的回调。这种情况是可以发送post请求的。
proxy文件的内容,如下:

<!doctype html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><script type="text/javascript">
(function(){
var queryStr = location.search.substring(1).split('&'),oneQueryStr,args = {},g = parent,scope = parent ,callback;
for(var i in queryStr){
oneQueryStr = queryStr[i].split('=');
if(!callback && oneQueryStr[0] == 'fun'){
callback = oneQueryStr[1];
};
if(oneQueryStr[0]&&oneQueryStr[1]){
args[oneQueryStr[0]] = (oneQueryStr[1]||'').replace(/[><'"{}]/g, '');
} }
callback = callback.split('.'); if( callback[0] === 'document'
|| callback[0] === 'location'
|| callback[0] === 'alert'){
}else{
for(var i = 0,len= callback.length;i<len;i++){
if(i==0 && callback[0]=="parent"){
g = parent;
scope = parent;
}else if(i==0 && callback[0]=="top"){
g = top;
scope = top;
}else{
if(i<len-1){
scope = scope[callback[i]];
}
g = g[callback[i]];
}
} g.call(scope,args);
} })();
</script>
</body></html>

通过上面的介绍,简单的知道了处理跨域请求的一些方法,下面整理了一个基于jquery的,解决跨域的方法。

$(function() {
'use strict'; /**
* 交互类
* @param {object} param 要提交的数据
* @param {Object} [ajaxOpt] ajax配置
* @param {boolean} [https=false] 是否使用https协议
* @constructor
*/
var Sync = function(param, ajaxOpt, https) {
var protocol = this.protocol = https ? 'https': 'http'; var ajaxOptDefault = {
url: protocol + '://'+location.host,
type: 'GET',
dataType: 'jsonp',
timeout: 20000
}; param = string2JSON(param) || {}; this.protocol = protocol;
this.param = $.extend({}, param, ajaxOpt);
this.ajaxOpt = $.extend({data: this.param}, ajaxOptDefault);
this.HOST = protocol + '://'+location.host;
}; function string2JSON(str){
if($.isPlainObject(str)) {
return str;
}
var params = {};
var str2Arr = str.split('&');
$.each(str2Arr, function(i, keyVal) {
var arr = keyVal.split('=');
//去除serialize把空格转成+
params[arr[0]] = decodeURIComponent(arr[1]).replace(/[\+]+/, '').replace(/[\+]+/, '');
});
return params;
} $.extend(Sync.prototype, {
/**
* 通过get方式(jsonp)提交
* @param {String} [url] 请求链接
* @return {Object} promise对象
*/
get: function(url) {
var self = this;
var send = $.ajax(url, this.ajaxOpt);
return send.then(this.done, function(statues) {
return self.fail(statues);
});
},
/**
* 通过post方式提交,依赖psp_jump.html文件
* @param {String} [url] 请求链接
* @return {Object} promise对象
*/
post: function(url) {
var deferred = $.Deferred();
var timer = null;
var guid = parseInt(new Date().getTime().toString().substr(4), 10);
var funName = 'QBXJsonp' + guid;
var formName = 'QBXForm' + guid;
var iframeName = 'QBXIframe' + guid; // iframe 不能使用attr('name', xxx) 否则在ie7上添加的不是name属性而是submitName
var iframe = $('<iframe name="' + iframeName +'">').hide();
var param = $.extend({}, this.param, {proxy: this.HOST+'/proxy.html', callback: funName});
var form = buildForm(param, {name: formName, target: iframeName, url: url || this.ajaxOpt.url}); window[funName] = function (data){
clearTimeout(timer);
var value;
for (var i in data) {
if (data.hasOwnProperty(i)) {
value = decodeURIComponent(data[i]);
if (value.match(/^(\{.*\})|(\[.*\])$/)) {
value = $.parseJSON(value);
}
data[i] = value;
}
}
deferred.resolve(data);
}; timer = setTimeout(function(){
deferred.reject({
errno: 999999,
errmsg: '网络超时,请稍后重试'
});
}, this.ajaxOpt.timeout); // do some clear
deferred.always(function(data) {
$(iframe).remove();
$(form).remove();
// IE8以下不支持delete window属性
try {
delete window[funName];
} catch (e){
window[funName] = null;
}
});
$(document.body).append(iframe).append(form);
$(form).submit();
return deferred.then(this.done);
},
/**
* 收到响应时默认回调
* @param {Object} data 数据
* @return {Object}
*/
done: function (data) {
var deferred = $.Deferred();
if (data.errno == 0) {
deferred.resolve(data);
} else {
deferred.reject(data);
}
return deferred.promise();
},
/**
* 未收到响应时默认回调
* @param {Object} error 错误信息
* @return {Object}
*/
fail: function(error) {
var deferred = $.Deferred();
deferred.reject({
errno: 999999,
errmsg: '网络超时,请稍后重试'
});
return deferred.promise();
}
}); /**
* 把数据对象转成form元素
* @param {Object} data json数据
* @param {Object} opts form所需参数或其他数据
* @return {Object}
*/
function buildForm(data, opts) {
if (opts.url) {
opts.action = opts.url;
delete opts.url;
}
opts.method = 'post';
var $form = $('<form>').attr(opts).hide();
$.each(data, function (name, value) {
$('<input>').attr({type: 'hidden', name: name, value: value}).appendTo($form);
});
return $form[0];
} window.Sync = Sync; });
这样我们就可以通过一下方式进行使用:
var login = function(data) {
var sync = new Sync(data);
return sync.post(sync.HOST+'/login');
} login({username: 'blackMao', password: 'blackMao'})
.done(function() {
alert('登陆成功!');
})
.fail(function(error) {
alert(error.errmsg);
});
至此就可以做到跨域请求了

Web 跨域请求的更多相关文章

  1. Web 跨域请求问题的解决方案- CORS 方案

    1.什么是跨域 跨域是指跨域名的访问,以下情况都属于跨域: 跨域现象 实例 域名不相同 www.baidu.com与www.taobao 一级域名相同,但是端口不相同 www.baidu.com:80 ...

  2. web跨域请求

    第一种情况: 1. sina.com=====>baidu.com/xxx.jsp 也就是前面的域名不相同,(url第三根斜杠之前的内容,也就是主机) 2:localhost =====> ...

  3. Web 跨域请求(OCRS) 前端解决方案

    1.同源策略如下: URL 说明 是否允许通信 http://www.a.com/a.jshttp://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.j ...

  4. 基于.Net Framework 4.0 Web API开发(5):ASP.NET Web APIs AJAX 跨域请求解决办法(CORS实现)

    概述:  ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.但是在使用API的时候总会遇到跨域请求的问题,特 ...

  5. javascript跨域请求RESTful Web Service

    跨域请求RESTful Web Service 当我们用js请求RESTful Web Service的时候,通常会出现跨域无法访问的问题,也就是无法正常得到我们要的值.jsonp是个解决问题的方法. ...

  6. Java Web解决跨域请求

    要知道跨域请求就要先了解同源策略,那么什么是同源?什么是不同源?简单来说就是,如果两个资源,包括HTML页面.JavaScript脚本.css样式,对应的协议.域名和端口完全相同,那么这两个资源就是同 ...

  7. Spring Boot Web应用开发 CORS 跨域请求支持:

    Spring Boot Web应用开发 CORS 跨域请求支持: 一.Web开发经常会遇到跨域问题,解决方案有:jsonp,iframe,CORS等等CORS与JSONP相比 1. JSONP只能实现 ...

  8. Java Web应用中支持跨域请求

    转载:https://blog.csdn.net/lmy86263/article/details/51724221 由于工程合作开发的需要,后台的应用要能支持跨域访问,但是在这个跨域访问“时好时坏” ...

  9. ASP.NET web api 跨域请求

    1.学习文章:AJAX 跨域请求 - JSONP获取JSON数据 1.asp.net代码 参考文章:http://www.sxt.cn/info-2790-u-756.html (1).增加CorsH ...

随机推荐

  1. Linux Framebuffer save as picture

    /********************************************************************************* * Linux Framebuff ...

  2. opencv-learnopencv-Facial Landmark Detection

    re: 1.facial-landmark-detection; https://www.learnopencv.com/facial-landmark-detection/ 2.landmark h ...

  3. [LeetCode&Python] Problem 806. Number of Lines To Write String

    We are to write the letters of a given string S, from left to right into lines. Each line has maximu ...

  4. Java乱码解决之道

    1.常见字符编码 ASCII编码: ASCII,American Standard Code for Information Interchange,是基于拉丁字母的一套电脑编码系统,主要用于显示现代 ...

  5. SQL Server2008 R2命令行启动及停止SQL服务的方法

    ===================================================== 在 SQL Server中,想要启动或停止SQL Server服务,通过SQL Server ...

  6. 《DSP using MATLAB》Problem 4.26

    Y(z)部分分式展开, 零状态响应和零输入响应的部分分式展开,

  7. 【知识笔记】Debugging

    一.启动调试出现 无法启动程序 当前状态中是非法 VS工具--选项--调试--常规--启用asp.net的JavaScript调试(chrome和ie)去掉勾选 二.web.config中<cu ...

  8. google play apk 下载

    https://apps.evozi.com/apk-downloader/?id=com.sgiggle.production

  9. microsoft webMatrix 使用 IISnode 进行node express 开发

    微软的microsoft webMatrix是一个免费的开发工具,我们可以使用它进行node 开发并利用iisnode 模块进行iis 的nodejs网站的维护,还是比较方便的. 一个简单的node ...

  10. 罗技 M558 鼠标维修记录

    罗技 M558 鼠标维修记录 故障现象 按键不灵敏 拆机内部图 前进键 后退键 左键 右键 中键 自定义功能键 使用的是 OMRON 按键,好东西,质量可以. 但毕竟是机械的东西,还是有老化,用万用表 ...