背景介紹:
開發微信公共號時前后端分離,后台用C#開發,前端使用vue框架,數據采用axios傳輸
具體問題:
1:前后端分離造成的跨域訪問問題
2:跨域后cookie傳輸和設置問題
解決方案:
1:使用jsonp作為數據傳輸的方式,前端和后端配合解決跨域問題
2:通過設置webconfig配合axios.js解決cookie傳輸(get、set)
具體方案:
問題一:
1:controller
/// <summary> /// get /// </summary> /// <param name="ID"></param> /// <returns></returns> public JsonpResult Text(int ID) { return this.Jsonp(ID); } /// <summary> /// post /// </summary> /// <param name="jsonp"></param> /// <returns></returns> [HttpPost] public JsonpResult TextJsonpHttp(string jsonp) { return this.Jsonp(jsonp); }
2:JsonpResult

/// <summary> /// Controller控制器類的擴展方法,即:Controller控制器下擴展一個Jsonp方法,這個方法帶一個object類型的參數 /// </summary> public static class ControllerExtension { public static JsonpResult Jsonp(this Controller controller, object data) { JsonpResult result = new JsonpResult() { Data = data, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; return result; } } public class JsonpResult : JsonResult { public static readonly string JsonpCallbackName = "MoDoPMS";//js中設置的jsonp public static readonly string CallbackApplicationType = "application/json"; public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new AccessViolationException("context"); } if (JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) //如果不允許來自客戶端的Get請求,並且請求類型是Get { throw new AccessViolationException(); } var response = context.HttpContext.Response; if (!string.IsNullOrEmpty(ContentType)) //這個ContentType是獲取或設置內容的類型。它是JsonResult類中的一個屬性 { response.ContentType = ContentType; //設置響應內容的類型 } else { response.ContentType = CallbackApplicationType; //設置響應內容的類型 } if (ContentEncoding != null) { response.ContentEncoding = this.ContentEncoding;//設置響應內容的編碼 } if (Data != null) //這個Data是JsonResult類中的一個屬性 { string buffer; var request = context.HttpContext.Request; JsonSerializerSettings settings = new JsonSerializerSettings(); settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; if (request[JsonpCallbackName] != null) //獲取回調函數名稱 { buffer = String.Format("{0}({1})", request[JsonpCallbackName], JsonConvert.SerializeObject(Data, Formatting.None, settings));//首先根據callback獲取獲取函數名,然后傳入json字符串作為函數參數 } else { buffer = JsonConvert.SerializeObject(Data, settings);//首先根據callback獲取獲取函數名,然后傳入json字符串作為函數參數 } response.Write(buffer); } } }
3:vue中axios.js

var url="/Wechat/JsonP/GetVueBranchList"; this.$http({ method: 'get', dataType: "jsonp", jsonp: "MoDoPMS",//jsonp接口參數 timeout: 10000,//超時 url: url, }) .then(function(response){ });

axios.post('/Wechat/JsonP/PostVueLogin', qs.stringify({loginphone:_this.phone,loginpwd:_this.password})) .then(response => { console.log(response); let instance = Toast(response.data.Message); setTimeout(() => { instance.close(); _this.$router.push({name: response.data.Url}); }, 1000); }) .catch(err => { console.log(err); });
get與post均可使用axios.js
4:配置項web.config

<system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /><!--解決跨域問題--> <add name="Access-Control-Allow-Methods" value="POST,GET" /><!--解決提交方式問題--> </customHeaders> </httpProtocol> </system.webServer>
問題二:
1:web.config中配置項
<system.webServer> <httpProtocol> <customHeaders> <!--上線后將這里改為微信端的域名--> <add name="Access-Control-Allow-Origin" value="http://localhost:8080" /><!--解決跨域問題--> <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS" /><!--解決提交方式問題--> <add name="Access-Control-Allow-Credentials" value="true" /><!--解決cookie問題--> <add name="Access-Control-Max-Age" value="1000"/> </customHeaders> </httpProtocol> </system.webServer>
很多人問題出在這里
The credentials mode of an XMLHttpRequest is controlled by the withCredentia
原因是將origin設置成*,*可以解決跨域問題,但是如果想配合使用cookie就必須設置固定域名,如果設置兩個,則會有一個不起作用。這里參考了簡書 CSDN 中的一些理論
2:vue-main.js中
axios.defaults.withCredentials = true//解決cookie問題
3:axios請求
4:http header
得到結論,在跨域的情況下使用 axios,首先需要配置 axios 的 withCredentials 屬性為 true。然后服務器還需要配置響應報文頭部的 Access-Control-Allow-Origin 和 Access-Control-Allow-Credentials 兩個字段,Access-Control-Allow-Origin 字段的值需要為確定的域名,而不能直接用 ‘*’ 代替,Access-Control-Allow-Credentials 的值需要設置為 true。前端和服務端兩邊都配置完善之后就可以正常進行跨域訪問以及攜帶 cookie 信息了。