JS跨域解决方案之使用CORS实现跨域


Posted in Javascript onApril 14, 2016

引言

       跨域是我在日常面试中经常会问到的问题,这词在前端界出现的频率不低,主要原因还是由于安全限制(同源策略, 即JavaScript或Cookie只能访问同域下的内容),因为我们在日常的项目开发时会不可避免的需要进行跨域操作,所以跨域能力也算是前端工程师的基本功之一。

和大多数跨域的解决方案一样,JSONP也是我的选择,可是某天PM的需求变了,某功能需要改成支持POST,因为传输的数据量比较大,GET形式搞不定。所以折腾了下闻名已久的CORS(跨域资源共享,Cross-Origin Resource Sharing),这边文章也就是折腾期间的小记与总结。

•CORS能做什么:

正常使用AJAX会需要正常考虑跨域问题,所以伟大的程序员们又折腾出了一系列跨域问题的解决方案,如JSONP、flash、ifame、xhr2等等。

• CORS的原理:

CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

下面我们步入正题具体详情如下所示:

跨站HTTP请求(Cross-site HTTP request)是指发起请求的资源所在域不同于请求指向的资源所在域的HTTP请求。

比如说,我在Web网站A(www.a.com)中通过<img>标签引入了B站的资源(www.b.com/images/1.jpg),那么A站会向B站发起一个跨站请求。

这种图片资源的跨站请求是被允许的,类似的跨站请求还有CSS文件,JavaScript文件等。

但是如果是在脚本中发起HTTP请求,出于安全考虑,会被浏览器限制。比如,使用 XMLHttpRequest 对象发起 HTTP 请求就必须遵守 同源策略。

所谓“同源策略”是指Web应用程序只能使用 XMLHttpRequest 对象向发起源所在域内发起HTTP请求,这个请求源和请求对象必须在一个域内。

举例来说,http://www.a.com,这个网址的协议是http,域名是www.a.com,端口默认是80。那么以下是它的同源情况:

•http://www.a.com/index.html 同源

•https://www.a.com/a.html 不同源(协议不同)

•http://service.a.com/testService/test 不同源(域名不同)

•http://www.b.com/index.html 不同源(域名不同)

•http://www.a.com:8080/index.html 不同源(端口不同)

为了开发出更强大,更丰富的Web应用,跨域请求是很常见的,那么如何在不舍弃安全的情况下进行跨域请求呢?

W3C推荐了一种新的机制,即跨源资源共享(Cross-Origin Resource Sharing (CORS))。

跨源资源共享(CORS)是通过客户端+服务端协作声明的方式来确保请求安全的。服务端会在HTTP请求头中增加一系列HTTP请求参数(例如Access-Control-Allow-Origin等),来限制哪些域的请求和哪些请求类型可以接受,而客户端在发起请求时必须声明自己的源(Orgin),否则服务器将不予处理,如果客户端不作声明,请求甚至会被浏览器直接拦截都到不了服务端。服务端收到HTTP请求后会进行域的比较,只有同域的请求才会处理。

一个使用CORS实现跨域请求的示例:

客户端:

function getHello() {
var xhr = new XMLHttpRequest();
xhr.open("post", "http://b.example.com/Test.ashx", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
// 声明请求源
xhr.setRequestHeader("Origin", "http://a.example.com");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var responseText = xhr.responseText;
console.info(responseText);
}
}
xhr.send();
}

服务端:

public class Test : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
// 声明接受所有域的请求
context.Response.AddHeader("Access-Control-Allow-Origin", "*");
context.Response.Write("Hello World");
}
public bool IsReusable
{
get
{
return false;
}
}
}

在Web API中启用跨域访问

CORS是服务端和客户端协作声明来确保请求安全的,因此,如果需要在Web API中启用CORS也需要进行相应配置。好在微软的ASP.NET团队提供了官方的支持跨域的解决方案,只需要在NuGet中添加即可。

JS跨域解决方案之使用CORS实现跨域

然后在App_Start/WebApiConfig.cs进行如下配置即可实现跨域访问:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 配置和服务
// 将 Web API 配置为仅使用不记名令牌身份验证。
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// 允许Web API跨域访问
EnableCrossSiteRequests(config);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
}
private static void EnableCrossSiteRequests(HttpConfiguration config) {
var cors = new EnableCorsAttribute(
origins: "*",
headers: "*",
methods: "*"
);
config.EnableCors(cors);
}
}

由于IE10以下浏览器不支持CORS,所以目前在国内CORS并不是主流的跨域解决方案,但是随着windows 10的发布,IE的逐渐衰落,可以预见,在不远的将来CORS将成为跨域的标准解决方案。

以上所述是小编给大家介绍的JS跨域解决方案之使用CORS实现跨域,希望对大家有所帮助!

Javascript 相关文章推荐
javascript学习笔记(九)javascript中的原型(prototype)及原型链的继承方式
Apr 12 Javascript
Jquery取得iframe下内容的方法
Nov 18 Javascript
Node.js中child_process实现多进程
Feb 03 Javascript
js正则表达式中exec用法实例
Jul 23 Javascript
javascript HTML5文件上传FileReader API
Mar 27 Javascript
JavaScript仿聊天室聊天记录
Dec 27 Javascript
微信小程序“摇一摇”的实例代码
Jul 20 Javascript
JS+jQuery实现注册信息的验证功能
Sep 26 jQuery
angular之ng-template模板加载
Nov 09 Javascript
vue-cli3 karma单元测试的实现
Jan 18 Javascript
Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现
Apr 01 Javascript
了解JavaScript表单操作和表单域
May 27 Javascript
[原创]Bootstrap 中下拉菜单修改成鼠标悬停直接显示
Apr 14 #Javascript
Seajs 简易文档 提供简单、极致的模块化开发体验
Apr 13 #Javascript
原生js编写autoComplete插件
Apr 13 #Javascript
JS中的eval 为什么加括号
Apr 13 #Javascript
jQuery操作属性和样式详解
Apr 13 #Javascript
jquery跟随屏幕滚动效果的实现代码
Apr 13 #Javascript
两种方法解决javascript url post 特殊字符转义 + &amp; #
Apr 13 #Javascript
You might like
PHP连接MySQL查询结果中文显示乱码解决方法
2013/10/25 PHP
隐性调用php程序的方法
2015/06/13 PHP
php文件压缩之PHPZip类用法实例
2015/06/18 PHP
摘自织梦CMS的HTTP文件下载类
2015/08/08 PHP
PHP带节点操作的无限分类实现方法详解
2016/11/09 PHP
关于PHP转换超过2038年日期出错的问题解决
2017/06/28 PHP
phpstudy后门rce批量利用脚本的实现
2019/12/12 PHP
js每次Title显示不同的名言
2008/09/25 Javascript
javascript IFrame 强制刷新代码
2009/07/23 Javascript
基于jquery的修改当前TAB显示标题的代码
2010/12/11 Javascript
基于jquery的跟随屏幕滚动代码
2012/07/24 Javascript
fmt:formatDate的输出格式详解
2014/01/09 Javascript
jquery淡化版banner异步图片文字效果切换图片特效
2014/04/08 Javascript
js实现简洁的TAB滑动门效果代码
2015/09/06 Javascript
Javascript的表单验证-提交表单
2016/03/18 Javascript
jQuery控制li上下循环滚动插件用法实例(附demo源码下载)
2016/05/28 Javascript
jQuery实现的购物车物品数量加减功能代码
2016/11/16 Javascript
WebStorm ES6 语法支持设置&amp;babel使用及自动编译(详解)
2017/09/08 Javascript
vue.js开发实现全局调用的MessageBox组件实例代码
2017/11/22 Javascript
js实现微信/QQ直接跳转到支付宝APP打开口令领红包功能
2018/01/09 Javascript
基于Vue实现微信小程序的图文编辑器
2018/07/25 Javascript
[02:38]2018DOTA2亚洲邀请赛赛前采访-VGJ.T
2018/04/03 DOTA
[42:32]完美世界DOTA2联赛循环赛 Magma vs PXG BO2第二场 10.28
2020/10/28 DOTA
python3利用Dlib19.7实现人脸68个特征点标定
2018/02/26 Python
获取python的list中含有重复值的index方法
2018/06/27 Python
使用Python写一个量化股票提醒系统
2018/08/22 Python
Python学习笔记之函数的参数和返回值的使用
2019/11/20 Python
Python类class参数self原理解析
2020/11/19 Python
基于python+selenium自动健康打卡的实现代码
2021/01/13 Python
招商经理岗位职责
2013/11/16 职场文书
汽车维修专业毕业生的求职信分享
2013/12/04 职场文书
草船借箭教学反思
2014/02/03 职场文书
大学生个人实习的自我评价
2014/02/15 职场文书
2015年售后服务工作总结
2015/04/25 职场文书
校园之声广播稿
2015/08/18 职场文书
2019运动会广播加油稿汇总
2019/08/21 职场文书