项目中使用了CORS来解决跨域问题,但是基于C#语言来说,网上的例子实在不多,而且对于我使用的一般处理程序(Handler)的例子就更少了,按照网上说的方法我都一一尝试过,但总是各种报错。由于没有学过C#语言,对这些例子理解的还不够,今天好不容易整出来了,写上一篇留作日后复习用,也希望能帮到像我一样有困惑的人。
CORS(Cross-origin resource sharing),跨域资源共享,仔细理解这个名称,跨域资源共享,其实就是它存在的意义,也是我们使用它的地方。
首先需要了解一个定义叫做“同源策略”,这个词在百度百科上可以查得到,其中最主要的地方在于三点“:
同源策略必须保证以上三点必须一模一样,完完全全的一样,比如举几个例子:
序号 | address1 | address2 | 是否满足同源 |
---|---|---|---|
1 | http://127.0.0.1:80 | http://localhost:80 | 否 |
2 | http://127.0.0.1:80 | http://127.0.0.1:5050 | 否 |
3 | http://127.0.0.1:80 | https://127.0.0.1:80 | 否 |
所以一旦看到协议、ip、端口号只要有一个不同,就一定是非同源策略,也就是跨域。
先说明一下,在下是转行之后才开始写后台代码,项目上正好遇到CORS处理跨域问题,以下内容写的不合适的地方欢迎批评指正。
3.1 遇到的报错信息
3.1.1 No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
这句话的意思就是在请求的资源文件中没有Access-Control-Allow-Origin,那解决办法就是在资源文件中添加上这个Header即可。比如我请求的路径是http://172.0.0.1:3000/HandlerDemo/TestHandler.ashx,我只需要在TestHandler.ashx.cs文件中添加 **context.Response.AddHeader(“Access-Control-Allow-Origin”,"");**即可,当然还可以进行其他信息的配置,比如是否允许携带cookie,请求方式等。可以参考如下代码:(在这里想说的是,使用CORS解决跨域问题时,一旦Access-Control-Allow-Origin的值设置为“”,它是不可以携带cookie数据的,但是把“*”换成某个固定的地址时,可以通过设置Access-Control-Allow-Credentials的值为true来实现允许携带cookie,默认是false)
public class TestHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.AddHeader("Access-Control-Allow-Origin","*");
context.Response.AddHeader("Access-Control-Allow-Headers"," x-www-form-urlencoded, Content-Type,x-requested-with");
context.Response.AddHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS");
}
public bool IsReusable
{
get
{
return false;
}
}
}
在这里非常想强调的一个问题是:使用CORS在处理Http协议的跨域请求时,http协议在真正发起POST或GET请求之前先发一个OPTIONS请求,这个请求主要适用于询问后台是否可以将请求发送过去,如果校验通过,才会将我们很正的POST或GET请求发送给后台。所以我们必须要先处理了OPTIONS请求并返回给前端,才能进行后面的业务处理。
我被这个问题坑了一个下午,因为我按照网上的教程将Header的内容配好了,但是会有个新的报错类型。
3.1.2 It does not have HTTP ok status.
其实这个报错原因就是没有对OPTIONS请求做处理导致的,我们先来分析一下原因,再来想解决办法。
打开控制台之后,发现与我上述的表达是一致的,在General发出来OPTIONS请求,但是后台并没有作响应,所以自然就报错了。另外,我发现,我的这个项目Access-Control-Request-Headers的值是
x-requested-with,所以在我上面的代码中,也将这个值添加到项目中。
那么说到底这个问题该怎么解决呢?先别急,我有一个更好的解决方法。咱们先来看一下这样写代码的一个很重要的问题:
3.1.3 代码复用性太差
复用性差是指上面代码中的三行 context.Response.AddHeader(…);这要求我们每写一个Handler就要重新复制一遍一模一样的内容,实在是费力不讨好的事。
所以我们将这些内容放到“Web.config”文件中,一劳永逸。顺便提醒一句,对OPTIONS的处理,也可以在这里配置。直接看代码!
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Accept, Origin, x-www-form-urlencoded, Content-Type,Last-Modified,x-requested-with" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
第一次写博客,花了近两个小时的时间,希望对大家有所帮助。