React項(xiàng)目中fetch實(shí)現(xiàn)跨域接收傳遞session的解決方案
本次項(xiàng)目使用了react框架,同時(shí)使用fetch取代ajax作為獲取接口數(shù)據(jù)的交互方法。本以為過(guò)程中應(yīng)該不會(huì)有什么磕絆,沒想到遇到了session丟失這個(gè)讓人甚是苦惱的問(wèn)題。期間本想換種方法來(lái)對(duì)接接口,但轉(zhuǎn)念一想如果每次遇到問(wèn)題都選擇逃避,那么以后的編碼之路只能越走越窄,所以還是決定堅(jiān)持下去。好在經(jīng)過(guò)一整天的摸索,總算是成功攻克了這個(gè)難關(guān),下面就對(duì)這次問(wèn)題的解決做個(gè)總結(jié)。
首先,為什么會(huì)出現(xiàn)postman接口調(diào)試正常而程序里fetch調(diào)用卻出現(xiàn)session丟失的問(wèn)題?
回顧fetch本身的特性——默認(rèn)情況下, fetch在服務(wù)端不會(huì)發(fā)送或接收任何 cookies?。?/p>
再來(lái)看session——當(dāng)客戶端第一次請(qǐng)求服務(wù)器的時(shí)候,服務(wù)器生成一份session保存在服務(wù)端,將該數(shù)據(jù)(session)的id以cookie的形式傳遞給客戶端;以后的每次請(qǐng)求,瀏覽器都會(huì)自動(dòng)的攜帶cookie來(lái)訪問(wèn)服務(wù)器(session數(shù)據(jù)id)。
這就意味著fetch這種方法如果想要攜帶cookie,需要經(jīng)過(guò)特殊的處理——credentials: "include",代碼如下:
fetch("https://ip:端口/api/Values/GetVerifyCode", { method: "GET", credentials: 'include', mode: 'cors', headers: { 'Content-Type': 'application/json' } }).then(res => res.json()) .then(res => { if (res.code == 200) { //xxxxxxx } });
這里還涉及到前后臺(tái)分離時(shí)經(jīng)常遇到的跨域問(wèn)題(mode: 'cors'),什么是跨域?瀏覽器從一個(gè)域名的網(wǎng)頁(yè)去請(qǐng)求另一個(gè)域名的資源時(shí),域名、端口、協(xié)議任一不同,都是跨域。在前后端分離的模式下,前后端的域名是不一致的,此時(shí)就會(huì)發(fā)生跨域訪問(wèn)問(wèn)題。在請(qǐng)求的過(guò)程中我們要想回去數(shù)據(jù)一般都是post/get請(qǐng)求,所以..跨域問(wèn)題就出現(xiàn)。這是出于瀏覽器的同源策略限制。(節(jié)選自https://zhuanlan.zhihu.com/p/425855609)
后臺(tái)以.netcore webapi為例,需要在Startup.cs里配置好Cors,代碼如下:
ConfigureServices里:
services.AddCors(options => { options.AddPolicy("any", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); });//跨域請(qǐng)求 });
Configure里:
app.UseCors("any");//跨域請(qǐng)求
這里要注意的是如果你在服務(wù)器端的web.config里已經(jīng)配置過(guò)跨域相關(guān)參數(shù)了,這里在加的話程序運(yùn)行時(shí)會(huì)報(bào)錯(cuò)(”*,*”…意思就是重復(fù)配置跨域參數(shù)),要使用credentials: 'include',需要將上面的允許來(lái)自所有域的跨域請(qǐng)求訪問(wèn)改為只允許特定域訪問(wèn),同時(shí)允許Credentials,如下:
services.AddCors(options => { options.AddPolicy("any", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); });//跨域請(qǐng)求 });
本來(lái)進(jìn)行到這里我以為問(wèn)題已經(jīng)解決了,在本地調(diào)試OK的情況下發(fā)布接口,然后調(diào)用發(fā)布好的服務(wù)器接口,卻還是沒有獲取到想要的cookie。以驗(yàn)證碼為例:一個(gè)fetch1生成驗(yàn)證碼,并把它通過(guò)響應(yīng)標(biāo)頭帶回來(lái),之后另一個(gè)fetch2調(diào)接口時(shí)把之前帶回來(lái)的cookie再通過(guò)請(qǐng)求標(biāo)頭傳到后臺(tái)進(jìn)行校驗(yàn),打開控制臺(tái)發(fā)現(xiàn)fetch2的請(qǐng)求標(biāo)頭并沒有cookie值,而fetch1的響應(yīng)標(biāo)頭里也沒有Set-Cookie。
點(diǎn)開末尾的cookie才發(fā)現(xiàn)問(wèn)題的所在:
這個(gè)SameSite是何許人也?
SameSite是瀏覽器請(qǐng)求中Set-Cookie響應(yīng)頭新增的一種屬性,它用來(lái)標(biāo)明這個(gè) cookie 是否是“同站 cookie”,同站 cookie 只能在本域名中使用的cookie,不能作為第三方 cookie。Chrome 51 開始,瀏覽器的 Cookie 新增加了一個(gè)SameSite屬性,用來(lái)防止 CSRF 攻擊和用戶追蹤。該屬性起初是由Google 起草的一份草案用來(lái)來(lái)改進(jìn) HTTP 協(xié)議的。Chrome 計(jì)劃將Lax變?yōu)槟J(rèn)設(shè)置。這時(shí),網(wǎng)站可以選擇顯式關(guān)閉SameSite屬性,將其設(shè)為None (對(duì)舊版瀏覽器無(wú)效,因?yàn)榕f版瀏覽器沒有該值) 。不過(guò),前提是必須同時(shí)設(shè)置Secure屬性(Cookie 只能通過(guò) HTTPS 協(xié)議發(fā)送),否則無(wú)效。(節(jié)選自https://www.cnblogs.com/w821759016/p/14595832.html)
了解了這個(gè),便可以很快地對(duì)Startup.cs里的services.AddSession做出調(diào)整,如下:
services.AddSession(options => { options.Cookie.Name = ".AdventureWorks.Session"; options.IdleTimeout = TimeSpan.FromSeconds(1800);//設(shè)置session的過(guò)期時(shí)間 options.Cookie.HttpOnly = true;//設(shè)置在瀏覽器不能通過(guò)js獲得該cookie的值 options.Cookie.SameSite = SameSiteMode.None; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; options.Cookie.IsEssential = true; });
其中,SameSite設(shè)為None配合Secure設(shè)為SameAsRequest,但要注意這個(gè)只允許訪問(wèn)的接口為https接口,另外將SameSite設(shè)置為了Unspecified瀏覽器則會(huì)使用默認(rèn)值lax,是沒有效果的。
最后,將原先的http接口改為https,至于https認(rèn)證所需的SSL證書怎么搞這里就不贅述了,將這些完成后再次嘗試調(diào)用發(fā)布好的接口,fetch1里的響應(yīng)標(biāo)頭以及fetch2里的請(qǐng)求標(biāo)頭就都能在控制臺(tái)看見了,問(wèn)題解決!
到此這篇關(guān)于React項(xiàng)目中fetch實(shí)現(xiàn)跨域接收傳遞session的解決方案的文章就介紹到這了,更多相關(guān)react fetch跨域接收傳遞session內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React-hooks面試考察知識(shí)點(diǎn)匯總小結(jié)(推薦)
這篇文章主要介紹了React-hooks面試考察知識(shí)點(diǎn)匯總,Hook?使你在無(wú)需修改組件結(jié)構(gòu)的情況下復(fù)用狀態(tài)邏輯,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10react以create-react-app為基礎(chǔ)創(chuàng)建項(xiàng)目
這篇文章主要介紹了react以create-react-app為基礎(chǔ)創(chuàng)建項(xiàng)目,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03ReactJS?應(yīng)用兼容ios9對(duì)標(biāo)ie11解決方案
這篇文章主要為大家介紹了ReactJS?應(yīng)用兼容ios9對(duì)標(biāo)ie11解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01React?正確使用useCallback?useMemo的方式
這篇文章主要介紹了React?正確使用useCallback?useMemo的方式,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08react源碼層深入刨析babel解析jsx實(shí)現(xiàn)
同作為MVVM框架,React相比于Vue來(lái)講,上手更需要JavaScript功底深厚一些,本系列將閱讀React相關(guān)源碼,從jsx -> VDom -> RDOM等一些列的過(guò)程,將會(huì)在本系列中一一講解2022-10-10