我就廢話不多說了,大家還是直接看代碼吧~
$.ajax({ type: "post", url:"http://127.0.0.1:4564/bsky-app/template/testpost", contenttype: "application/json;charset=utf-8", data :json.stringify({"bodyname":"sdfsdf","date":"2017-11-28 07:34:01","price": 10.5,"tbid": 1}), datatype: "json", beforesend: function (xmlhttprequest) { xmlhttprequest.setrequestheader("token", "eyjhbgcioijiuzuxmij9.eyjzdwiioiixod....."); }, success: function (data) { alert(data); },error:function(error){ console.log(error); } });
beforesend: function (xmlhttprequest) { xmlhttprequest.setrequestheader("token", "eyjhbgcioijiuzuxmij9.eyjzdwiioiixod....."); },
其中,token是服務端自定義的header參數
補充知識:ajax請求攜帶cookie和自定義請求頭header(跨域和同域)
ajax請求攜帶cookie、自定義header總結:
錯誤:
1.ajax請求時是不會自動帶上cookie的,要是想讓他帶上的話,必須設置withcredential為true。
正確:
1.ajax同域請求下,ajax會自動帶上同源的cookie;
2.ajax同域請求下,ajax添加自定義請求頭(或原裝)header,前端、后臺不需要增加任何配置,
并且不會因為增加自定義請求頭header,而引起預檢查請求(options);
3.ajax跨域請求下,如果不需要攜帶cookie、請求頭header,只需要在后臺配置相應參數即可;
后臺參數:
(1).access-control-allow-origin:設置允許跨域的配置, 響應頭指定了該響應的資源是否被允許與給定的origin共享;
4.ajax跨域請求下,ajax不會自動攜帶同源的cookie,需要通過前端配置相應參數才可以跨域攜帶同源cookie,后臺配置相應參數才可以跨域返回同源cookie;
前端參數:
withcredentials: true(發送ajax時,request header中會帶上cookie信息)
后臺參數:
(1).access-control-allow-origin:設置允許跨域的配置, 響應頭指定了該響應的資源是否被允許與給定的origin共享;
特別說明:配置了access-control-allow-credentials:true則不能把access-control-allow-origin設置為通配符*;
(2).access-control-allow-credentials:響應頭表示是否可以將對請求的響應暴露給頁面(cookie)。返回true則可以,其他值均不可以。
5.ajax請求任何時候都不會帶上不同源的cookie(cookie遵循同源策略);
6.ajax跨域請求下,ajax添加自定義或者原裝的請求頭,請求會發送兩次,第一次預檢查請求,第二次正常請求,詳細描述:
post(或get)跨域請求時,分為簡單請求和復雜請求,跨域攜帶自定義或者原裝請求頭頭時是復雜請求。
復雜請求會先發送一個method 為option的請求,目的是試探服務器是否接受發起的請求. 如果服務器說可以,再進行post(或get)請求。
對于java后臺web應用,跨域需要添加一個過濾器(過濾器詳見下面案例代碼),這個過濾器做的事就是,加了幾個http header在返回中,
access-control-allow-origin 我能接受的跨域請求來源,配置主機名
access-control-allow-headers 表示能接受的http頭部,別忘了加入你自己發明創造的頭部
access-control-allow-methods 表示能接受的http mothed ,反正就那幾種,全寫上也無妨,猥瑣點就只寫 post, options
如果是option返回空,設置返回碼為202,202表示通過。
需要前端配置相應參數才可以跨域攜帶請求頭,后臺配置相應參數進行跨域攜帶請求頭;
前端參數:
crossdomain:true(發送ajax時,request header 中會包含跨域的額外信息,但不會含cookie(作用不明,不會影響請求頭的攜帶))
后臺參數(配置預檢查過濾器):
(1)access-control-allow-origin:設置允許跨域的配置, 響應頭指定了該響應的資源是否被允許與給定的origin共享;
(2)access-control-allow-credentials:響應頭表示是否可以將對請求的響應暴露給頁面(cookie)。返回true則可以,其他值均不可以;
(3)access-control-allow-headers:用于預檢請求中,列出了將會在正式請求的 access-control-request-headers 字段中出現的首部信息。(自定義請求頭);
(4)access-control-allow-methods:在對預檢請求的應答中明確了客戶端所要訪問的資源允許使用的方法或方法列表;
親測小結論:
1.ajax跨域請求下,后臺不配置跨域access-control-allow-origin,同樣能夠執行后臺方法,但是無法執行ajax的success的方法,控制臺報跨域錯誤;
2.ajax跨域請求下,前端配置withcredentials: false,同樣能夠執行后臺方法,但是無法攜帶同源cookie,后臺無法獲取;
3.ajax跨域請求下,前端配置withcredentials: true,后端沒有配置access-control-allow-credentials:true,同樣能夠執行后臺方法,并能夠生成cookie并返回瀏覽器,但是無法執行ajax的success的方法,控制臺報跨域錯誤;
4.ajax跨域請求下,前端配置withcredentials: false或不配置withcredentials,后端配置access-control-allow-credentials:true或者false,同樣能夠執行后臺方法,并能夠生成cookie并返回瀏覽器,但是無法攜帶同源cookie,能夠執行ajax的success的方法;
5.cookie攜帶只區分域名,不區分端口;
6.jsonp可以攜帶cookie,但只能攜帶所屬域名的cookie(同源策略);
7.jsonp可以跨域生成cookie,流程如下:跨域請求之后,在服務器端生成cookie,并在瀏覽器端記錄相應的cookie;
8.靜態資源同樣會攜帶cookie(js和圖片等),但是如果是和當前頁面不同域只是在network中不顯示cookie選項,但是后臺能夠獲取到對應cookie;
9.ajax同域請求會自動帶上同源的cookie,不會帶上不同源的cookie;
10.這是mdn對withcredentials的解釋: mdn-withcredentials ,我接著解釋一下同源。
眾所周知,ajax請求是有同源策略的,雖然可以應用cors等手段來實現跨域,但是這并不是說這樣就是“同源”了。ajax在請求時就會因為這個同源的問題而決定是否帶上cookie,這樣解釋應該沒有問題了吧,還不知道同源策略的,應該去谷歌一下看看。
總結:
最好前端后臺配置跨域,則同時配置相應的跨域配置,否則總會出現不可控的錯誤;
1. ajax跨域請求(無cookie、無header)案例(java)
(1)啟動一個java web項目,配置兩個域名(host),czt.ming.com、czt.casicloud.com,java后端代碼如下:
注意:access-control-allow-origin
/** * * @title: getajaxcross * @description: todo(ajax請求,跨域) * @param request * @param response */ @requestmapping(value ="/getajaxcross",method= {requestmethod.get}) public void getajaxcross(httpservletrequest request, httpservletresponse response){ try { response.setcharacterencoding("utf-8"); //設置允許多個域名允許跨域集合 string[] allowdomains = {"http://czt.casicloud.com", "http://czt.ming.com"}; set alloworigins = new hashset(arrays.aslist(allowdomains)); string origin = request.getheader("origin"); if(alloworigins.contains(origin)){ //設置允許跨域的配置:access-control-allow-origin: 響應頭指定了該響應的資源是否被允許與給定的origin共享 response.setheader("access-control-allow-origin", origin); } //數據 map<string, object> resultmap = new hashmap<string, object>(); resultmap.put("message", "ajax請求,跨域成功"); string result = jsonutils.objecttojson(resultmap); response.getwriter().write(result); } catch (exception e) { e.printstacktrace(); } }
(2)前端頁面代碼如下:
//4.ajax跨域 function getcookieajaxcross() { $.ajax({ type:"get", url:"http://czt.ming.com/xxx/xxx/xxx/getajaxcross", async:true, data:{}, datatype: 'json', success: function(data) { console.log(data); } }); } getcookieajaxcross();
(3)測試ajax跨域請求:
通過http://czt.casicloud.com/xxx/xxx訪問頁面,js觸發ajax跨域請求http://czt.ming.com/xxx/xxx/xxx/getajaxcross,前端和后臺如果不按照代碼中配置相應參數會報各種跨域錯誤;
2. ajax跨域請求獲取和創建cookie案例(java)
(1)啟動一個java web項目,配置兩個域名(host),czt.ming.com、czt.casicloud.com,java后端代碼如下:
注意:access-control-allow-credentials和access-control-allow-origin
/** * * @title: getcookieajax * @description: todo(ajax請求,跨域傳遞cookie) * @param request * @param response */ @requestmapping(value ="/getcookieajax",method= {requestmethod.get}) public void getcookieajax(httpservletrequest request, httpservletresponse response){ try { response.setcharacterencoding("utf-8"); response.setheader("access-control-allow-credentials", "true"); //設置允許多個域名允許跨域集合 string[] allowdomains = {"http://czt.casicloud.com", "http://czt.ming.com"}; set alloworigins = new hashset(arrays.aslist(allowdomains)); string origin = request.getheader("origin"); if(alloworigins.contains(origin)){ //設置允許跨域的配置:access-control-allow-origin: 響應頭指定了該響應的資源是否被允許與給定的origin共享 response.setheader("access-control-allow-origin", origin); } //獲取cookie cookie[] cookies = request.getcookies(); //設置cookie cookie cookie = new cookie("access_token_ajax", uuid.randomuuid().tostring()); cookie.setpath("/"); response.addcookie(cookie); //數據 map<string, object> resultmap = new hashmap<string, object>(); resultmap.put("cookies", cookies); resultmap.put("message", "ajax請求,跨域傳遞cookie成功"); string result = jsonutils.objecttojson(resultmap); response.getwriter().write(result); } catch (exception e) { e.printstacktrace(); } }
(2)前端頁面代碼如下:
注意:withcredentials和crossdomain(作用不明)
//4.ajax跨域攜帶cookie和自定義請求頭header function getcookieajaxcross() { $.ajax({ type:"get", url:"http://czt.ming.com/industry/api/publishforeign/getcookieajax", async:true, data:{}, datatype: 'json', xhrfields: { withcredentials: true // 發送ajax時,request header中會帶上 cookie 信息。 }, crossdomain: true, // 發送ajax時,request header 中會包含跨域的額外信息,但不會含cookie(作用不明,不會影響請求頭的攜帶) success: function(data) { console.log(data); } }); } getcookieajaxcross();
(3)測試ajax跨域請求獲取和創建cookie:
通過http://czt.casicloud.com/xxx/xxx訪問頁面,js觸發ajax跨域請求http://czt.ming.com/xxx/xxx/xxxx/getcookieajax,前端和后臺如果不按照代碼中配置相應參數會報各種跨域錯誤;
3. ajax跨域請求,攜帶請求頭header案例(java)
(1)啟動一個java web項目,配置兩個域名(host),czt.ming.com、czt.casicloud.com;
(2)ajax跨域攜帶請求頭會發送兩次請求,一次預檢查請求(options),預檢查請求通過之后才會進行真正的請求,所以java后臺需要配置相應的跨域過濾器,如下:
import java.io.ioexception; import java.util.arrays; import java.util.hashset; import java.util.set; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletexception; import javax.servlet.servletrequest; import javax.servlet.servletresponse; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; /** * * @classname: corsfilter * @description: todo(跨域請求過濾器) * @author clm * @date 2019年10月25日 * */ public class corsfilter implements filter { @override public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception { /* * 跨域請求頭服務端配置: * 1.access-control-allow-origin:設置允許跨域的配置, 響應頭指定了該響應的資源是否被允許與給定的origin共享 * 2.access-control-allow-credentials:響應頭表示是否可以將對請求的響應暴露給頁面(cookie)。返回true則可以,其他值均不可以。 * 3.access-control-allow-headers:用于預檢請求中,列出了將會在正式請求的 access-control-request-headers 字段中出現的首部信息。(自定義請求頭) * 4.access-control-allow-methods:在對 預檢請求的應答中明確了客戶端所要訪問的資源允許使用的方法或方法列表。 */ httpservletrequest httprequest = (httpservletrequest) servletrequest; httpservletresponse httpresponse = (httpservletresponse) servletresponse; //設置允許多個域名允許跨域集合 string[] allowdomains = {"http://czt.casicloud.com", "http://czt.ming.com"}; set<string> alloworigins = new hashset<string>(arrays.aslist(allowdomains)); string origin = httprequest.getheader("origin"); if(alloworigins.contains(origin)){ //設置允許跨域的配置:access-control-allow-origin: 響應頭指定了該響應的資源是否被允許與給定的origin共享 httpresponse.setheader("access-control-allow-origin", origin); } httpresponse.setheader("access-control-allow-credentials", "true"); httpresponse.setheader("access-control-allow-headers", "origin, x-requested-with, content-type, accept, access-token"); httpresponse.setheader("access-control-allow-methods", "get, put, delete, post, options"); if (httprequest.getmethod().equalsignorecase("options")) { httpresponse.setstatus(202); httpresponse.getwriter().close(); return; } filterchain.dofilter(servletrequest, servletresponse); } @override public void destroy() { } @override public void init(filterconfig filterconfig) throws servletexception { } }
web.xml中配置過濾器:
<filter> <filter-name>corsfilter</filter-name> <filter-class>xxx.xxx.xxx.xx.xxx.corsfilter</filter-class> </filter> <filter-mapping> <filter-name>corsfilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
(3)java后臺controller代碼:
/** * * @title: getpersonheader * @description: todo(跨域獲取請求頭) * @param request * @param response */ @requestmapping(value ="/getpersonheader",method=requestmethod.get) public void getpersonheader(httpservletrequest request, httpservletresponse response){ try { response.setcharacterencoding("utf-8"); string personheader = request.getheader("access-token"); system.err.println("獲取自定義請求頭(access-token):" + personheader); //數據 map<string, object> resultmap = new hashmap<string, object>(); resultmap.put("message", "跨域獲取請求頭成功"); resultmap.put("personheader", personheader); string result = jsonutils.objecttojson(resultmap); response.getwriter().write(result); } catch (exception e) { e.printstacktrace(); } }
(4)前端頁面代碼如下:
注意:crossdomain(作用不明)
//同域前端設置自定義請求頭,后端獲取自定義請求頭 function getpersonheader() { $.ajax({ type:"get", url:"/xxx/xxx/xxx/getpersonheader", async:true, //ajax配置請求頭方式,第一種 headers: { "access-token":"access-token123456",//自定義請求頭 "content-type":"application/json;charset=utf8" }, //ajax配置請求頭方式,第二種 //beforesend : function(request) { // request.setrequestheader("access-token", "access-token123456"); // request.setrequestheader("content-type", "application/json;charset=utf8"); //} data:{}, success: function(data) { console.log(data); } }); } getpersonheader(); //跨域前端設置自定義請求頭,后端獲取自定義請求頭 function getpersonheadercross() { $.ajax({ type:"get", url:"http://czt.ming.com/xxx/xxx/xxx/getpersonheader", async:true, headers: { "access-token":"access-token123456",//自定義請求頭 "content-type":"application/json;charset=utf8" }, data:{}, crossdomain: true, // 發送ajax時,request header 中會包含跨域的額外信息,但不會含cookie(作用不明,不會影響請求頭的攜帶) success: function(data) { console.log(data); } }); } getpersonheadercross();
(5)測試ajax跨域請求攜帶請求頭header:
通過http://czt.casicloud.com/xxx/xxx訪問頁面,js觸發ajax跨域請求http://czt.ming.com/xxx/xxx/xxxx/getpersonheader,前端和后臺如果不按照代碼中配置相應參數會報各種跨域錯誤;
3. jsonp實現跨域讀寫cookie案例(java)
(1)啟動一個java web項目,配置兩個域名(host),czt.ming.com、czt.casicloud.com;
(2)java后臺jsonp代碼:
/** * * @title: setcookie * @description: todo(jsonp跨域設置cookie) * @param request * @param response */ @requestmapping(value ="/setcookie.jsonp",method=requestmethod.get) public void setcookie(httpservletrequest request, httpservletresponse response){ try { response.setcharacterencoding("utf-8"); //設置cookie cookie cookie = new cookie("access_token", uuid.randomuuid().tostring()); cookie.setpath("/"); response.addcookie(cookie); //數據 map<string, object> resultmap = new hashmap<string, object>(); resultmap.put("cookie", cookie); resultmap.put("message", "跨域設置cookie成功"); string result = jsonutils.objecttojson(resultmap); //前端傳過來的回調函數名稱 string callback = request.getparameter("callback"); //用回調函數名稱包裹返回數據,這樣,返回數據就作為回調函數的參數傳回去了 result = callback + "(" + result + ")"; response.getwriter().write(result); } catch (exception e) { e.printstacktrace(); } } /** * * @title: getcookie * @description: todo(jsonp跨域獲取cookie) * @param request * @param response */ @requestmapping(value ="/getcookie.jsonp",method=requestmethod.get) public void getcookie(httpservletrequest request, httpservletresponse response){ try { response.setcharacterencoding("utf-8"); //獲取cookie cookie[] cookies = request.getcookies(); //數據 map<string, object> resultmap = new hashmap<string, object>(); resultmap.put("cookies", cookies); resultmap.put("message", "跨域獲取cookie成功"); string result = jsonutils.objecttojson(resultmap); //前端傳過來的回調函數名稱 string callback = request.getparameter("callback"); //用回調函數名稱包裹返回數據,這樣,返回數據就作為回調函數的參數傳回去了 result = callback + "(" + result + ")"; response.getwriter().write(result); } catch (exception e) { e.printstacktrace(); } }
(3)前端代碼:
//1.jsonp跨域設置cookie function setcookiecrossjsonp() { $.ajax({ type:"get", url:"http://czt.ming.com/industry/api/publishforeign/setcookie.jsonp", async:true, data:{}, datatype: "jsonp", //返回類型為jsonp,實現跨域 jsonp:"callback", //jsonp和jsonpcallback相當于在url后添加一個參數:?callback=back jsonpcallback:"back", //設定回調函數的名字,傳到后臺,進行包裝,不設定自動生成 success: function(data) { //成功執行處理,對應后臺返回的back(data)方法 console.log(data); } }); } setcookiecrossjsonp(); //2.jsonp跨域獲取cookie function getcookiecrossjsonp() { $.ajax({ type:"get", url:"http://czt.ming.com/industry/api/publishforeign/getcookie.jsonp", async:true, data:{}, datatype: "jsonp", //返回類型為jsonp,實現跨域 jsonp:"callback", //jsonp和jsonpcallback相當于在url后添加一個參數:?callback=back jsonpcallback:"back1", //設定回調函數的名字,傳到后臺,進行包裝,不設定自動生成 success: function(data) { //成功執行處理,對應后臺返回的back(data)方法 console.log(data); } }); } getcookiecrossjsonp();
(4)測試jsonp跨域請求獲取和創建cookie:
通過http://czt.casicloud.com/xxx/xxx訪問頁面,js觸發jsonp跨域請求http://czt.ming.com/xxx/xxx/xxxx/getcookie.jsonp、http://czt.ming.com/xxx/xxx/xxxx/setcookie.jsonp,能夠正常跨域設置cookie和獲取cookie;
以上這篇ajax請求添加自定義header參數代碼就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持碩編程。