在之前的項目中,我們設置跨域都是直接在web.config中設置的。
這樣是可以實現跨域訪問的。因為我們這邊一般情況下一個webapi會有多個網站、小程序、微信公眾號等訪問,所以這樣設置是沒有問題的。但是……如果其中一個網站需要用到cookie或者session的時候,
Access-Control-Allow-Origin如果還是設置成“*”就會報錯,當然是前端報錯。。。數據返回還有cookie/session都還是能存,但是報錯就不爽了啊。
於是,想着整改一下。
先上前端代碼。來個頁面遠程ajax請求去設置session。啥都沒有,就是點按鈕,發個請求。標記地方是必須加的
@{ ViewBag.Title = "TestSetSession"; } <h2>TestSetSession</h2> <button onclick="Set()">設置session</button> @section scripts{ <script src="~/Scripts/jquery-1.10.2.min.js"></script> <script> function Set() { $.ajax({ url: "http://localhost:1338/api/Test/SetSession?session=1234567fdsdfghjhgfds", dataType: "json", xhrFields: { withCredentials: true }, crossDomain: true, data: {}, type: "post", success: function (data) { alert(data.message) }, error: function () { alert('服務器發生錯誤!'); } }); } </script> }
然后再來個頁面,獲取上個頁面設置的session。
@{ ViewBag.Title = "TestGetSession"; } <h2>TestGetSession</h2> <button onclick="Get()">獲取session</button> @section scripts{ <script src="~/Scripts/jquery-1.10.2.min.js"></script> <script> function Get() { $.ajax({ url: "http://localhost:1338/api/Test/GetSession", dataType: "json", xhrFields: { withCredentials: true }, crossDomain: true, data: {}, type: "get", success: function (data) { alert("session:" + data.data.session_state + ",cookie:" + data.data.cookie); }, error: function () { alert('服務器發生錯誤!'); } }); } </script> }
后台代碼
1.先允許webapi使用session
在global中加入如下代碼
public override void Init() { PostAuthenticateRequest += MvcApplication_PostAuthenticateRequest; base.Init(); } void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e) { System.Web.HttpContext.Current.SetSessionStateBehavior( System.Web.SessionState.SessionStateBehavior.Required); }
2.允許跨域。我這里使用的是Microsoft.AspNet.WebApi.Cors
先安裝包,然后在WebApiConfig中加入如下代碼。等同於在web.config中設置
//允許跨域 config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
在請求方法上打上[EnableCors]標簽,特指某一些域名的訪問需要cookie/session
[EnableCors("http://localhost:6477,http://localhost:6478", "*","*")] public class TestController : ApiController { /// <summary> /// 設置session /// </summary> /// <returns></returns> public dynamic SetSession(string session) { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true"); //緩存state HttpContext.Current.Session["session_test"] = session; HttpCookie cookie = new HttpCookie("cookie_test") { Value = session, Expires = DateTime.Now.AddHours(1) }; HttpContext.Current.Response.Cookies.Add(cookie); return new { success = true, message = "設置session" }; } /// <summary> /// 獲取session /// </summary> /// <returns></returns> public dynamic GetSession() { HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true"); var session = HttpContext.Current.Session["session_test"]; HttpCookie _cookie = HttpContext.Current.Request.Cookies["cookie_test"]; var cookie = _cookie?.Value??""; string session_state = session == null ? "" : session.ToString(); return new { success = true, message = "獲取session", data = new { session_state, cookie } }; }
結果: