WCF SOA --- AJAX 跨域请求处理 CORS for WCF
一、问题
跨域请求无法处理的问题,由于为了阻止恶意的网站通过JS脚本来窃取正常网站受保护的资源。所由所有的浏览器的默认策略是阻止XmlHttpRequest的跨域的异步请求。 但是对于一个 复合型的应用集合来说,可能需要使用不同的域来部署我们的应用。对于这种正常的需求,我们的服务与应用就需要能够支持指定信认域的跨域的异步请法。
通常来说,我们有三种替代方案
1, 使用JSONP,
JSONP(JSON with Padding), 但由于JSONP使用的是在HTML DOM中加入<script>标签来包裹来对提供GET的服务请求数据,所有JSONP只对HTTP GET方式的请求取作用。我们的SOA框架,大多是使用POST的请求。
2, 使用分离的“Proxy”代理服务,
代理服务是指,在同一个请求的域下创建一个代理的服务, Ajax请求这个代理服务,由代理服务来路由这个请求到目标域的服务上。 如果我们的所有的运用都必须使用HTML页面来实现。 那这种方式,需要为每一个不同域的应用创建代理服务。 但请注意,如果我们的应用是门户网,请求可能来自外面的人, 对于性能需求高,那么使用HTML是不可行的。我们需要使用ASP.NET MVC结构, 那么Controller层就如同我们的代理服务层。
3, 使用CORS
CORS,Cross-Origin Resource Sharing, 这是一种新的对跨域支持的方法, 它是通过定义一系列的HTTP Headers 在Service 与Client, 服务端可以去掉对于跨域的约束,不仅可以使用GET,还可以使用POST, PUT,或是DELETE, XmlHttpRequest对象已经实现了CORS, 将它作为正常的AJAX调用。但是目前只有最新版本的浏览器才支持, 对于Firefox 3.5以下,Safari 4以下,Chrome 3以下, IE 10 以下,可以使用XDomainRequest对象来代替XmlHttpRequest对象来实现。
浏览器对于使用CORS的请求,会分成次请求,第一次,预先授权请求,会将请求的方式变成OPTIONS, 请求的数据为空,这个过程实际上是在看当前的Origin是否被服务允许,如果允许只服务返回200OK, 否则返回405 Method NOT Allowed, 第二次,正常请求,浏览器将请求的数据POST发送服务,服务端会正常响应。 注意下面是Chrome的,IE的话,只会显示一条。

二、解决步骤。
1, 应用, 对于应用层来说, 该怎么样写,还是怎么样写,不需要变化。但对于底版本的浏览器的支持需要改代码,不能使用XmlHttpRequest。需要使用XDomainRequest。
2, 服务, 这里我们使用的是WCF, 对于使用ASP.NET Web API的话,使用参考:https://msdn.microsoft.com/en-us/magazine/dn532203.aspx, 或是Google, CORS in ASP.NET Web Api.
对于WCF,我参考了 CarlosFigueira写的 http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx ,文章写的非常不错, 但是我发现,其它它是一个半成品,没有实现玩,它的目的是创建一个新的Operation,只是支持OPTIONS方式的请求,Action的名称是当前操作的名称 +特定的后缀。 但这样问题来了,客户端浏览器的请求,每一次不会自动加上这个后缀,所有Invoke一直都不会被调用。 大家的兴趣下载了使用的话,如果想结合到自己的项目中, 可要记得把Web.config中的<modules runAllManagedModulesForAllRequests="true">去掉。 当然,前提是,你使用的Service都是自己通过ServiceHostFactory创建出来的, 如果使用默认的,是不会支持的。 其它 CarlosFigueira想法。 我做了一些改变。 实现步骤如下:
1,在IIS中,添加Http Response Header 3个,如下

建议这个设置在WebSite上, 这样你的服务在这个Website下作为一个Web Application的话,将自动继承这些配置。 写在web.config,可以方便控制允许访问的域。当前我使用 *, 这样所有的域都能访问,如果想指定哪些域的话,可以改成如 Http://domain1.com,Http://domain2......。那么只有来自这些域的请求才能处理。当然这个设置,或以在WCF,添加自己的IDispatchMessageInspector实现, 在BeforeSendReply事件中,添加响应头。
2,在使用自定ServiceHostFactory,创建服务时, 我们可以指定IServiceBehavior, 在它的ApplyDispatchBehavior事件中。 找到所有的Operation,对它注入WebInvokeAttribute, Method设置成*, 目的是动态将Operation对 Method=OPTIONS的请求处理, 如下代码
foreach (ServiceEndpoint endpoint in desc.Endpoints)
{
foreach (var operation in endpoint.Contract.Operations)
{
//Add WebInvoke Attribute to all operation except for WebGet only, so that our opeations are able to handle OPTIONS Http Request Method for CORS issue.
if ( !operation.Behaviors.Any(d => d is WebGetAttribute)
&& !operation.Behaviors.Any(d => d is WebInvokeAttribute))
{
WebInvokeAttribute wia = new WebInvokeAttribute();
wia.UriTemplate = operation.Name;
wia.Method = "*";
operation.Behaviors.Add(wia);
}
}
}
3,当OPTIONS方式的请求来到时,在自定的 IOperationInvoker的invoke事件中, 判断当前的Http Method是否为OPTIONS, 如果是的话,不处理正常逻辑, 返回一个200 OK的响应。代码如下
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
string operationName = "";
if (OperationContext.Current.IncomingMessageHeaders.Action != null)
{
operationName = OperationContext.Current.IncomingMessageHeaders.Action.ToString();
}
if (OperationContext.Current.IncomingMessageProperties.Keys.Contains("HttpOperationName"))
{
operationName = OperationContext.Current.IncomingMessageProperties["HttpOperationName"].ToString();
}
HttpRequestMessageProperty request = System.ServiceModel.OperationContext.Current.IncomingMessageProperties["httpRequest"] as HttpRequestMessageProperty;
//If enable CORS, then we need to handle OPTIONS Method to reply OK, so that the browser will seed the right POST request.
if (request != null
&& request.Method == "OPTIONS" )
{
System.ServiceModel.Channels.Message input = (System.ServiceModel.Channels.Message)inputs[0];
outputs = null;
return HandlePreflight(input, operationName);
}
else
{
正常处理。。。。
}
}
System.ServiceModel.Channels.Message HandlePreflight(System.ServiceModel.Channels.Message input, string operationName)
{
System.ServiceModel.Channels.Message reply = System.ServiceModel.Channels.Message.CreateMessage(MessageVersion.None, operationName);
HttpResponseMessageProperty httpResponse = new HttpResponseMessageProperty();
reply.Properties.Add(HttpResponseMessageProperty.Name, httpResponse);
httpResponse.SuppressEntityBody = true;
httpResponse.StatusCode = System.Net.HttpStatusCode.OK;
httpResponse.Headers.Add(CorsConstants.AccessControlAllowOrigin, "*");
httpResponse.Headers.Add(CorsConstants.AccessControlAllowMethods, string.Join(",", new List<string>() { "POST", "GET", "OPTIONS" }));
return reply;
}
结束。
WCF SOA --- AJAX 跨域请求处理 CORS for WCF的更多相关文章
- JQuery.Ajax + 跨域 (crossDomain) + POST + JSON + WCF RESTful, 5大陷阱和解决方案
JQuery.Ajax + 跨域 (crossDomain) + POST + JSON + WCF RESTful, 5大陷阱和解决方案 最近在开发WSS RESTful服务的时候, 碰到了这些个纠 ...
- Springmvc ajax跨域请求处理
上次给一个网站写网站 前后端分离 最后跪在ajax跨域上面了 自己在网上找了个方法 亲试可用 记录一下 写一个类 继承HandlerInterceptorAdapter package co ...
- [经验] - JQuery.Ajax + 跨域 (crossDomain) + POST + JSON + WCF RESTful, 5大陷阱和解决方案
最近在开发WSS RESTful服务的时候, 碰到了这些个纠结的问题. 在网上查找了半天, 找到n多种解决方案, 但是都是部分的, 要么是没有跨域的情况, 要么是没有post的情况, 要么不是用WCF ...
- AJAX跨域资源共享 CORS 详解
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing). 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从 ...
- Jquery:ajax跨域请求处理
昨天朋友想做个图片懒加载的效果,朋友是前端的,我这边给他提供数据,程序写好了放到服务器上,本地测试访问时却报jquery跨域的问题,于是找度娘了解了一下jquey如何处理,网上有很多参考文章,但没细看 ...
- Ajax 跨域 异步 CORS
HTTP access control (CORS) 核心在于使用定制(添加新的header)HTTP header让浏览器和服务器有更多的相互了解,从而决定一个请求或者响应成功还是失败 对于一个 ...
- ajax跨域通过 Cors跨域资源共享 进行GetPost请求
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...
- ajax 跨域了 cors
<?php /** * Author: humanhuang * Date: 13-12-17 */ header('Access-Control-Allow-Origin:*'); heade ...
- 分享知识-快乐自己:Ajax 跨域请求处理
<%-- Created by IntelliJ IDEA. User: asus Date: 2019/1/24 Time: 15:57 To change this template use ...
随机推荐
- maven+tomcat6-maven-plugin实现热部署及调试
maven project,特别是maven module项目默认情况下是是无法直接通过tomcat等容器部署的,如图,我要部署fastdev_web这个maven module,可以看出在tomca ...
- button以回车方式提交
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- myeclipse报错:Could not create the view: An unexpected exception was thrown.
打开server窗口,发现显示:Could not create the view: An unexpected exception was thrown. 此处解决方法: 关闭myeclipse 删 ...
- 【图说】Eclipse与Unity 3D协同工作
原地址:http://blog.csdn.net/h570768995/article/details/9355313 Eclipse开发过程中总会碰到很多的难题,如何利用好工具帮助我们更快捷的开发也 ...
- 【leetcode】Word Break II (hard)★
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...
- ECNU-2574 Principles of Compiler
题意: 给出编译规则,求是否满足条件 A:= '(' B')'|'x'. B:=AC. C:={'+'A}. 其中{}表示里面的内容可以出现0次或者多次 注意点见代码注释 #include ...
- hdu 4678 Mine 博弈论
这是一题简单的博弈论!! 所有的空白+边界的数字(个数为n)为一堆,容易推出其SG函数值为n%2+1: 其他所有的数字(个数为m)的SG值为m%2. 再就是用dfs将空白部分搜一下即可!(注意细节) ...
- codeforces #313 div1 D
好神的题目! 首先我们运用pick定理A=S-B/2+1将要求的东西转化掉 之后分离变量,我们变成了求选取凸包面积的期望和求选取凸包在边界上的点的期望 我们先考虑求选取凸包面积的期望 如何计算凸多边形 ...
- [mock]12月27日
一开始介绍项目,最后的反馈是,还是说得不清楚,需要再准备准备. 然后两道题,第一题是有个数组,有2*n个数字,从1~n.比如n=3的数组,{1,2,2,3,1,3}.然后两两相同的数字删除,每次删除得 ...
- ajax返回son数据
JSON 只是一种文本字符串.它被存储在 responseText 属性中 为了读取存储在 responseText 属性中的 JSON 数据,需要根据 JavaScript 的 eval 语句. 函 ...