1、什麼是跨域請求: 當從A網站使用AJAX請求B網站時,就會出現跨域請求。 此時B網站能夠接收到A網站發來的請求並返回相應的結果,但是瀏覽器拿到B網站返回的數據時檢測到與當前網站的功能變數名稱不同,出於安全考慮瀏覽器不會把數據傳遞給A網站的這個AJAX請求。 2、如何解決跨域請求問題: 跨域問題到現在已經 ...
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(); }