我就廢話不多說了,大家還是直接看代碼吧~
$.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是服務(wù)端自定義的header參數(shù)
補(bǔ)充知識:ajax請求攜帶cookie和自定義請求頭header(跨域和同域)
ajax請求攜帶cookie、自定義header總結(jié):
錯(cuò)誤:
1.ajax請求時(shí)是不會(huì)自動(dòng)帶上cookie的,要是想讓他帶上的話,必須設(shè)置withcredential為true。
正確:
1.ajax同域請求下,ajax會(huì)自動(dòng)帶上同源的cookie;
2.ajax同域請求下,ajax添加自定義請求頭(或原裝)header,前端、后臺不需要增加任何配置,
并且不會(huì)因?yàn)樵黾幼远x請求頭header,而引起預(yù)檢查請求(options);
3.ajax跨域請求下,如果不需要攜帶cookie、請求頭header,只需要在后臺配置相應(yīng)參數(shù)即可;
后臺參數(shù):
(1).access-control-allow-origin:設(shè)置允許跨域的配置, 響應(yīng)頭指定了該響應(yīng)的資源是否被允許與給定的origin共享;
4.ajax跨域請求下,ajax不會(huì)自動(dòng)攜帶同源的cookie,需要通過前端配置相應(yīng)參數(shù)才可以跨域攜帶同源cookie,后臺配置相應(yīng)參數(shù)才可以跨域返回同源cookie;
前端參數(shù):
withcredentials: true(發(fā)送ajax時(shí),request header中會(huì)帶上cookie信息)
后臺參數(shù):
(1).access-control-allow-origin:設(shè)置允許跨域的配置, 響應(yīng)頭指定了該響應(yīng)的資源是否被允許與給定的origin共享;
特別說明:配置了access-control-allow-credentials:true則不能把a(bǔ)ccess-control-allow-origin設(shè)置為通配符*;
(2).access-control-allow-credentials:響應(yīng)頭表示是否可以將對請求的響應(yīng)暴露給頁面(cookie)。返回true則可以,其他值均不可以。
5.ajax請求任何時(shí)候都不會(huì)帶上不同源的cookie(cookie遵循同源策略);
6.ajax跨域請求下,ajax添加自定義或者原裝的請求頭,請求會(huì)發(fā)送兩次,第一次預(yù)檢查請求,第二次正常請求,詳細(xì)描述:
post(或get)跨域請求時(shí),分為簡單請求和復(fù)雜請求,跨域攜帶自定義或者原裝請求頭頭時(shí)是復(fù)雜請求。
復(fù)雜請求會(huì)先發(fā)送一個(gè)method 為option的請求,目的是試探服務(wù)器是否接受發(fā)起的請求. 如果服務(wù)器說可以,再進(jìn)行post(或get)請求。
對于java后臺web應(yīng)用,跨域需要添加一個(gè)過濾器(過濾器詳見下面案例代碼),這個(gè)過濾器做的事就是,加了幾個(gè)http header在返回中,
access-control-allow-origin 我能接受的跨域請求來源,配置主機(jī)名
access-control-allow-headers 表示能接受的http頭部,別忘了加入你自己發(fā)明創(chuàng)造的頭部
access-control-allow-methods 表示能接受的http mothed ,反正就那幾種,全寫上也無妨,猥瑣點(diǎn)就只寫 post, options
如果是option返回空,設(shè)置返回碼為202,202表示通過。
需要前端配置相應(yīng)參數(shù)才可以跨域攜帶請求頭,后臺配置相應(yīng)參數(shù)進(jìn)行跨域攜帶請求頭;
前端參數(shù):
crossdomain:true(發(fā)送ajax時(shí),request header 中會(huì)包含跨域的額外信息,但不會(huì)含cookie(作用不明,不會(huì)影響請求頭的攜帶))
后臺參數(shù)(配置預(yù)檢查過濾器):
(1)access-control-allow-origin:設(shè)置允許跨域的配置, 響應(yīng)頭指定了該響應(yīng)的資源是否被允許與給定的origin共享;
(2)access-control-allow-credentials:響應(yīng)頭表示是否可以將對請求的響應(yīng)暴露給頁面(cookie)。返回true則可以,其他值均不可以;
(3)access-control-allow-headers:用于預(yù)檢請求中,列出了將會(huì)在正式請求的 access-control-request-headers 字段中出現(xiàn)的首部信息。(自定義請求頭);
(4)access-control-allow-methods:在對預(yù)檢請求的應(yīng)答中明確了客戶端所要訪問的資源允許使用的方法或方法列表;
親測小結(jié)論:
1.ajax跨域請求下,后臺不配置跨域access-control-allow-origin,同樣能夠執(zhí)行后臺方法,但是無法執(zhí)行ajax的success的方法,控制臺報(bào)跨域錯(cuò)誤;
2.ajax跨域請求下,前端配置withcredentials: false,同樣能夠執(zhí)行后臺方法,但是無法攜帶同源cookie,后臺無法獲??;
3.ajax跨域請求下,前端配置withcredentials: true,后端沒有配置access-control-allow-credentials:true,同樣能夠執(zhí)行后臺方法,并能夠生成cookie并返回瀏覽器,但是無法執(zhí)行ajax的success的方法,控制臺報(bào)跨域錯(cuò)誤;
4.ajax跨域請求下,前端配置withcredentials: false或不配置withcredentials,后端配置access-control-allow-credentials:true或者false,同樣能夠執(zhí)行后臺方法,并能夠生成cookie并返回瀏覽器,但是無法攜帶同源cookie,能夠執(zhí)行ajax的success的方法;
5.cookie攜帶只區(qū)分域名,不區(qū)分端口;
6.jsonp可以攜帶cookie,但只能攜帶所屬域名的cookie(同源策略);
7.jsonp可以跨域生成cookie,流程如下:跨域請求之后,在服務(wù)器端生成cookie,并在瀏覽器端記錄相應(yīng)的cookie;
8.靜態(tài)資源同樣會(huì)攜帶cookie(js和圖片等),但是如果是和當(dāng)前頁面不同域只是在network中不顯示cookie選項(xiàng),但是后臺能夠獲取到對應(yīng)cookie;
9.ajax同域請求會(huì)自動(dòng)帶上同源的cookie,不會(huì)帶上不同源的cookie;
10.這是mdn對withcredentials的解釋: mdn-withcredentials ,我接著解釋一下同源。
眾所周知,ajax請求是有同源策略的,雖然可以應(yīng)用cors等手段來實(shí)現(xiàn)跨域,但是這并不是說這樣就是“同源”了。ajax在請求時(shí)就會(huì)因?yàn)檫@個(gè)同源的問題而決定是否帶上cookie,這樣解釋應(yīng)該沒有問題了吧,還不知道同源策略的,應(yīng)該去谷歌一下看看。
總結(jié):
最好前端后臺配置跨域,則同時(shí)配置相應(yīng)的跨域配置,否則總會(huì)出現(xiàn)不可控的錯(cuò)誤;
1. ajax跨域請求(無cookie、無header)案例(java)
(1)啟動(dòng)一個(gè)java web項(xiàng)目,配置兩個(gè)域名(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"); //設(shè)置允許多個(gè)域名允許跨域集合 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)){ //設(shè)置允許跨域的配置:access-control-allow-origin: 響應(yīng)頭指定了該響應(yīng)的資源是否被允許與給定的origin共享 response.setheader("access-control-allow-origin", origin); } //數(shù)據(jù) 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觸發(fā)ajax跨域請求http://czt.ming.com/xxx/xxx/xxx/getajaxcross,前端和后臺如果不按照代碼中配置相應(yīng)參數(shù)會(huì)報(bào)各種跨域錯(cuò)誤;
2. ajax跨域請求獲取和創(chuàng)建cookie案例(java)
(1)啟動(dòng)一個(gè)java web項(xiàng)目,配置兩個(gè)域名(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"); //設(shè)置允許多個(gè)域名允許跨域集合 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)){ //設(shè)置允許跨域的配置:access-control-allow-origin: 響應(yīng)頭指定了該響應(yīng)的資源是否被允許與給定的origin共享 response.setheader("access-control-allow-origin", origin); } //獲取cookie cookie[] cookies = request.getcookies(); //設(shè)置cookie cookie cookie = new cookie("access_token_ajax", uuid.randomuuid().tostring()); cookie.setpath("/"); response.addcookie(cookie); //數(shù)據(jù) 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 // 發(fā)送ajax時(shí),request header中會(huì)帶上 cookie 信息。 }, crossdomain: true, // 發(fā)送ajax時(shí),request header 中會(huì)包含跨域的額外信息,但不會(huì)含cookie(作用不明,不會(huì)影響請求頭的攜帶) success: function(data) { console.log(data); } }); } getcookieajaxcross();
(3)測試ajax跨域請求獲取和創(chuàng)建cookie:
通過http://czt.casicloud.com/xxx/xxx訪問頁面,js觸發(fā)ajax跨域請求http://czt.ming.com/xxx/xxx/xxxx/getcookieajax,前端和后臺如果不按照代碼中配置相應(yīng)參數(shù)會(huì)報(bào)各種跨域錯(cuò)誤;
3. ajax跨域請求,攜帶請求頭header案例(java)
(1)啟動(dòng)一個(gè)java web項(xiàng)目,配置兩個(gè)域名(host),czt.ming.com、czt.casicloud.com;
(2)ajax跨域攜帶請求頭會(huì)發(fā)送兩次請求,一次預(yù)檢查請求(options),預(yù)檢查請求通過之后才會(huì)進(jìn)行真正的請求,所以java后臺需要配置相應(yīng)的跨域過濾器,如下:
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 { /* * 跨域請求頭服務(wù)端配置: * 1.access-control-allow-origin:設(shè)置允許跨域的配置, 響應(yīng)頭指定了該響應(yīng)的資源是否被允許與給定的origin共享 * 2.access-control-allow-credentials:響應(yīng)頭表示是否可以將對請求的響應(yīng)暴露給頁面(cookie)。返回true則可以,其他值均不可以。 * 3.access-control-allow-headers:用于預(yù)檢請求中,列出了將會(huì)在正式請求的 access-control-request-headers 字段中出現(xiàn)的首部信息。(自定義請求頭) * 4.access-control-allow-methods:在對 預(yù)檢請求的應(yīng)答中明確了客戶端所要訪問的資源允許使用的方法或方法列表。 */ httpservletrequest httprequest = (httpservletrequest) servletrequest; httpservletresponse httpresponse = (httpservletresponse) servletresponse; //設(shè)置允許多個(gè)域名允許跨域集合 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)){ //設(shè)置允許跨域的配置:access-control-allow-origin: 響應(yīng)頭指定了該響應(yīng)的資源是否被允許與給定的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); //數(shù)據(jù) 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(作用不明)
//同域前端設(shè)置自定義請求頭,后端獲取自定義請求頭 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(); //跨域前端設(shè)置自定義請求頭,后端獲取自定義請求頭 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, // 發(fā)送ajax時(shí),request header 中會(huì)包含跨域的額外信息,但不會(huì)含cookie(作用不明,不會(huì)影響請求頭的攜帶) success: function(data) { console.log(data); } }); } getpersonheadercross();
(5)測試ajax跨域請求攜帶請求頭header:
通過http://czt.casicloud.com/xxx/xxx訪問頁面,js觸發(fā)ajax跨域請求http://czt.ming.com/xxx/xxx/xxxx/getpersonheader,前端和后臺如果不按照代碼中配置相應(yīng)參數(shù)會(huì)報(bào)各種跨域錯(cuò)誤;
3. jsonp實(shí)現(xiàn)跨域讀寫cookie案例(java)
(1)啟動(dòng)一個(gè)java web項(xiàng)目,配置兩個(gè)域名(host),czt.ming.com、czt.casicloud.com;
(2)java后臺jsonp代碼:
/** * * @title: setcookie * @description: todo(jsonp跨域設(shè)置cookie) * @param request * @param response */ @requestmapping(value ="/setcookie.jsonp",method=requestmethod.get) public void setcookie(httpservletrequest request, httpservletresponse response){ try { response.setcharacterencoding("utf-8"); //設(shè)置cookie cookie cookie = new cookie("access_token", uuid.randomuuid().tostring()); cookie.setpath("/"); response.addcookie(cookie); //數(shù)據(jù) map<string, object> resultmap = new hashmap<string, object>(); resultmap.put("cookie", cookie); resultmap.put("message", "跨域設(shè)置cookie成功"); string result = jsonutils.objecttojson(resultmap); //前端傳過來的回調(diào)函數(shù)名稱 string callback = request.getparameter("callback"); //用回調(diào)函數(shù)名稱包裹返回?cái)?shù)據(jù),這樣,返回?cái)?shù)據(jù)就作為回調(diào)函數(shù)的參數(shù)傳回去了 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(); //數(shù)據(jù) map<string, object> resultmap = new hashmap<string, object>(); resultmap.put("cookies", cookies); resultmap.put("message", "跨域獲取cookie成功"); string result = jsonutils.objecttojson(resultmap); //前端傳過來的回調(diào)函數(shù)名稱 string callback = request.getparameter("callback"); //用回調(diào)函數(shù)名稱包裹返回?cái)?shù)據(jù),這樣,返回?cái)?shù)據(jù)就作為回調(diào)函數(shù)的參數(shù)傳回去了 result = callback + "(" + result + ")"; response.getwriter().write(result); } catch (exception e) { e.printstacktrace(); } }
(3)前端代碼:
//1.jsonp跨域設(shè)置cookie function setcookiecrossjsonp() { $.ajax({ type:"get", url:"http://czt.ming.com/industry/api/publishforeign/setcookie.jsonp", async:true, data:{}, datatype: "jsonp", //返回類型為jsonp,實(shí)現(xiàn)跨域 jsonp:"callback", //jsonp和jsonpcallback相當(dāng)于在url后添加一個(gè)參數(shù):?callback=back jsonpcallback:"back", //設(shè)定回調(diào)函數(shù)的名字,傳到后臺,進(jìn)行包裝,不設(shè)定自動(dòng)生成 success: function(data) { //成功執(zhí)行處理,對應(yīng)后臺返回的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,實(shí)現(xiàn)跨域 jsonp:"callback", //jsonp和jsonpcallback相當(dāng)于在url后添加一個(gè)參數(shù):?callback=back jsonpcallback:"back1", //設(shè)定回調(diào)函數(shù)的名字,傳到后臺,進(jìn)行包裝,不設(shè)定自動(dòng)生成 success: function(data) { //成功執(zhí)行處理,對應(yīng)后臺返回的back(data)方法 console.log(data); } }); } getcookiecrossjsonp();
(4)測試jsonp跨域請求獲取和創(chuàng)建cookie:
通過http://czt.casicloud.com/xxx/xxx訪問頁面,js觸發(fā)jsonp跨域請求http://czt.ming.com/xxx/xxx/xxxx/getcookie.jsonp、http://czt.ming.com/xxx/xxx/xxxx/setcookie.jsonp,能夠正??缬蛟O(shè)置cookie和獲取cookie;
以上這篇ajax請求添加自定義header參數(shù)代碼就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持碩編程。