Ajax請求攜帶Cookie
目錄
xhr
先來了解下xhr
xhr,全稱為XMLHttpRequest
,用於與伺服器互動資料,是ajax功能實現所依賴的物件,jquery中的ajax就是對 xhr的封裝。
還有axios和fetch請求都屬於xhr請求,都是基於標準 Promise 實現。
ajax cookie跨域處理
簡單說說cookie
和session
的關係
不少朋友搞的不是特別清楚,一知半解的,在這裡闡述下
cookie儲存於客戶端瀏覽器,預設生命週期跟隨瀏覽器,瀏覽器關閉,cookie就會失效,tab標籤也關閉了並不會失效
session儲存於伺服器,比如tomcat
,預設失效時間30分鐘,當然也可以通過redis來儲存。
這裡登入做個示例說明
未登入狀態下,匿名使用者通過客戶端瀏覽器請求資料,都是無狀態的(服務端不知道你是誰
)
使用者進行請求登入操作,登入成功,服務端會在response header里加一個Set-Cookie
寫入瀏覽器中。
之後客戶端在以後的請求中,會自動在請求頭中攜帶此cookie。
cookie有一些屬性,比如
-
失效時間(跟隨瀏覽器,但是也可以進行持久化。跟localstorage和sessionstorage類似)
-
httponly(設定為true的話,客戶端在控制檯就獲取不到)
-
path(預設為/)
同源情況下,比如是前後端不分離的專案,xhr(ajax)請求沒有任何問題,但是會發現,不支援cookie跨域
非同源情況下,xhr(ajax)請求服務端處理了,但是不會進行響應,會顯示如下錯誤。也就是出現了跨域問題。
所以,解決介面跨域和解決xhr cookie跨域,是不一樣的。
解決cookie跨域需要客戶端和服務端都做處理,主要操作在服務端。
客戶端
ajax請求新增該引數即可
xhrFields: {
withCredentials: true
},
同理axios也是如此
axios.defaults.withCredentials = true
注意,修改cookie值直接document修改即可,請求的時候瀏覽器會自動攜帶的。
不需要在header中新增cookie頭,這樣做是沒有任何意義的。比如
headers: {
'Cookie': 'JSESSIONID=6FA9E27092EC212E439851D4831AADE6'
}
服務端
新增允許跨域操作,此處表示Spring
框架,直接用@CrossOrigin
處理即可(最為簡單)
@CrossOrigin(value = "*", allowCredentials = "true")
服務端設定跨域的幾種方式
方式一 重寫addCorsMappings方法
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.maxAge(3600)
.allowCredentials(true);
}
}
方式二 對單個介面處理
// 需要設定前端請求的url。不支援*
responses.setHeader("Access-Control-Allow-Origin", "http://localhost:63342");
// 設定允許跨域的方法
responses.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
// 之後需要設定允許cookie跨域
response.setHeader("Access-Control-Allow-Credentials", "true");
方式三 @CrossOrigin註解
@CrossOrigin(value = "*", allowCredentials = "true")
方式四 nginx配置新增允許跨域請求
server {
listen 5566;
server_name localhost;
# 指定客戶端的請求地址
add_header 'Access-Control-Allow-Origin' 'http://localhost:63342';
add_header 'Access-Control-Allow-Credentials' true;
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization,token,r,sign,time";
location / {
if ($request_method = OPTIONS ) {
return 200;
}
proxy_method get;
proxy_set_header X-real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:5005;
proxy_set_header Host $host;
}
}
OK,完美解決!