你的位置:首页 > 软件开发 > ASP.net > 使用代理解决跨站点请求和跨站点上传文件

使用代理解决跨站点请求和跨站点上传文件

发布时间:2016-04-11 23:00:11
在做Web系统的时候,我们经常会使用Ajax技术来实现异步加载数据的功能,开始的时候我们的系统只有一个,但随着业务的发展,我们的Web系统可能有很多个,而且每个系统可能都是一个独立的站点,那么当我们直接使用Ajax技术来访问其它站点时,就会出现意外。假设我们直接使用jQuery提 ...

使用代理解决跨站点请求和跨站点上传文件

在做Web系统的时候,我们经常会使用Ajax技术来实现异步加载数据的功能,开始的时候我们的系统只有一个,但随着业务的发展,我们的Web系统可能有很多个,而且每个系统可能都是一个独立的站点,那么当我们直接使用Ajax技术来访问其它站点时,就会出现意外。

假设我们直接使用jQuery提供的Ajax方法来把京东的首页给抓取下来,那么有如下代码:

$.ajax({

我当前的站点是http://localhost:6404,浏览器提示说我当前的站点不被允许访问京东的站点,原因是京东的响应头里面没有“Access-Control-Allow-Origin”字段,那么“Access-Control-Allow-Origin”又是什么?

出于安全的因素,浏览器会限制我们从脚本中发起跨站请求,所以W3C工作组退出了一种新的机制,即跨源资源共享(Cross-Origin Resource Sharing (CORS)),这种机制让Web应用服务器能支持跨站访问控制,从而使得安全地进行跨站数据传输成为可能。而“Access-Control-Allow-Origin”就是该机制里面所定义的字段。W3C上有对该字段的准确定义:

使用代理解决跨站点请求和跨站点上传文件

请求头里面的“Origin”字段的值就是我当前的站点地址,我是从“http://localhost:6404”这个站点向“http://www.jd.com”这个站点发起的Ajax请求的。所以根据W3C的文档描述,如果京东的响应头的“Access-Control-Allow-Origin”字段里面有“http://localhost:6404”这个值,那么我就可以成功抓取到京东的首页。

由于我改不了京东的响应头“Access-Control-Allow-Origin”字段,所以我就自己建了一个新的站点来测试一下。

站点“http://localhost:6404”上发起的请求脚本:

$.ajax({

从结果上可以看出,跨站点请求已经成功。接下来,我们把响应头里面的“Access-Control-Allow-Origin”字段去掉:

public void ProcessRequest(HttpContext context)

结果果然跟之前的是一样的,这也证明了“Access-Control-Allow-Origin”在跨站点请求里面扮演的重要角色。

虽然问题解决了,但是新的问题又来了,如果我有1000个站点都要用到跨站点请求,那么我难道要把这1000个站点都加到响应头里面?所以,这肯定是不行的,那么我如何在不改动响应头的情况下实现跨站点请求呢?

前面说过,导致这个问题的直接原因是由于“浏览器限制了我们的脚本”,那么这里就有两个前提,一个是浏览器,一个是脚本,如果我们能避开其中一个,是不是就可以实现跨站点请求呢?于是我就想到了在后台代码里面直接构建Http请求代理来干掉浏览器。

由于直接使用HttpWebRequest类要配置的东西太多,而且在异步API这块写起来太繁琐,所以我使用了一个轻量但功能强大的HttpClient类来实现这一功能。

首先,我们来设计前端脚本API,为了更好的兼容性,我不打算重新写套Ajax请求的API,而是继续采用$.ajax(),只不过传递的参数不一样而已。所以,就有了下面这个脚本API:

$.ajax({

然后再来说说 “/cors”这个地址是怎么来的,这个地址就是代理处理程序的地址,我们可以在Web.config文件里面的webServer>节点里进行配置:

 <system.webServer>

从上图看出,我们设想成功实现了。我们把请求头和响应头的详细信息调出来看看:

请求头:

使用代理解决跨站点请求和跨站点上传文件使用代理解决跨站点请求和跨站点上传文件

通过反编译工具,我们看到“FormUrlEncodedContent”类的描述为“A container for name/value tuples encoded using application/x-www-form-urlencoded MIME type.”,所以它是适用于“application/x-www-form-urlencoded”这种类型的,很明显文件不属于这种,StringContent同样不适合。然后我们再看看“MultipartFormDataContent”类,它的描述为“Provides a container for content encoded using multipart/form-data MIME type.”,眼尖的同学一定已经发现了,它就是跟我们上传文件所需的MIME类型一致的类了,所以我们就使用它来封装我们要上传的文件数据。

所以核心代码如下:

public void ProcessRequest(HttpContext context)

这个就是我上传的图片文件地址,它已成功上传到“http://localhost:6408”这个站点的“uploaddir”目录。

参考文献

 

海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:https://www.xlkjsw.com

原标题:使用代理解决跨站点请求和跨站点上传文件

关键词:上传

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。