CORS跨域请求C#版
1、什么是跨域请求:
当从A网站使用AJAX请求B网站时,就会出现跨域请求。
此时B网站能够接收到A网站发来的请求并返回相应的结果,但是浏览器拿到B网站返回的数据时检测到与当前网站的域名不同,出于安全考虑浏览器不会把数据传递给A网站的这个AJAX请求。
2、如何解决跨域请求问题:
跨域问题到现在已经不是什么新鲜事情了,前辈们总结出来大致有以下几种方法:
CORS 、JSONP、flash、iframe、xhr2等等。
但是笔者最喜欢用CORS方法来解决该问题,因为该解决方案的原理非常简单,只需要由服务器发送一个响应头即可。
headers.Add("Access-Control-Allow-Origin", origin);
3、代码:
封装一个过滤器来处理Http请求
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.All, Inherited = true, AllowMultiple = true)] public class CorsAttribute : ActionFilterAttribute, IActionFilter { /// <summary> /// 构造函数 /// </summary> /// <param name="AllowOriginsPattern"></param> public CorsAttribute(string allowOriginsPattern = "") { if (string.IsNullOrEmpty(allowOriginsPattern)) { this.AllowOriginsPattern = ConfigurationManager.AppSettings["AllowOriginsPattern"].ToString(); } else { this.AllowOriginsPattern = allowOriginsPattern; } } /// <summary> /// 访问完成,追加head /// </summary> /// <param name="filterContext"></param> public override void OnResultExecuted(ResultExecutedContext filterContext) { try { base.OnResultExecuted(filterContext); GetResponse(); } catch (Exception exception) { HttpContext.Current.Response.Clear(); HttpContext.Current.Response.Write(exception.Message); HttpContext.Current.Response.End(); } } /// <summary> /// 允许的正则表达式 /// </summary> public string AllowOriginsPattern { get; set; } /// <summary> /// 获取response /// </summary> /// <returns></returns> public HttpResponse GetResponse() { HttpRequest request = HttpContext.Current.Request; IDictionary<string, string> headers; bool IsEvaluate = TryEvaluate(HttpContext.Current.Request, out headers); if (IsEvaluate) { foreach (var item in headers) { HttpContext.Current.Response.Headers.Add(item.Key, item.Value); } } return HttpContext.Current.Response; } /// <summary> /// 是否匹配 /// </summary> /// <param name="request"></param> /// <param name="headers"></param> /// <returns></returns> public bool TryEvaluate(HttpRequest request, out IDictionary<string, string> headers) { headers = null; if (request.Headers.GetValues("Origin") != null) { string origin = request.Headers.GetValues("Origin").First(); Regex regex = new Regex(AllowOriginsPattern, RegexOptions.IgnoreCase); if (regex.IsMatch(origin))//匹配正则 { headers = this.GenerateResponseHeaders(request); return true; } } return false; } /// <summary> /// 生成head /// </summary> /// <param name="request"></param> /// <returns></returns> private IDictionary<string, string> GenerateResponseHeaders(HttpRequest request) { string origin = request.Headers.GetValues("Origin").First(); Dictionary<string, string> headers = new Dictionary<string, string>(); headers.Add("Access-Control-Allow-Origin", origin); headers.Add("Access-Control-Allow-Headers", "x-requested-with,content-type,requesttype,Token"); headers.Add("Access-Control-Allow-Methods", "POST,GET"); return headers; } }
在接收跨域请求的方法上使用这个过滤器
[Cors(".*")]//这里的这个参数将允许任何网站请求 public JsonResult CorsApi() { return Json(new { data="跨域请求成功"},JsonRequestBehavior.AllowGet); }
也可通过在配置文件中添加 AllowOriginsPattern ,来控制可请求改方法的站点。此时方法上过滤器换成 [Cors]
<appSettings> <add key="AllowOriginsPattern" value="(http://)?(localhost:20735)"/> </appSettings>
4、当然如果是通过后台去请求其他网站的API是不存在跨域问题的
public ActionResult About() { HttpWebRequest http = (HttpWebRequest)HttpWebRequest.Create("http://localhost:20735/home/CorsApi"); var reader = new StreamReader(http.GetResponse().GetResponseStream(), Encoding.UTF8).ReadToEnd(); ViewBag.result = reader; return View(); }