前端遇到302重定向問題處理方式及設(shè)置第三方Cookie研究
前端遇到302處理方式以及設(shè)置第三方Cookie研究
1、如何解決后端302重定向問題
背景:由于認(rèn)證中心網(wǎng)關(guān)檢測到用戶是未登錄態(tài)情況下的話,會將用戶重定向到認(rèn)證中心的登錄頁。
? 此時(shí),假如是使用Oauth2協(xié)議,登錄成功后,前端需要帶著登錄成功的信息(jwt),訪問/Oauth2/1/authorize接口,此時(shí)該接口將會重定向回redirect_uri的地址,這個(gè)時(shí)候的重點(diǎn)在于如何訪問/Oauth2/1/authorize接口。
我們列舉一下幾種請求方式:
- Ajax
- Fetch
- Location.href
- Form表單
- Nvigator.sendBeacon
技術(shù) | 特點(diǎn) | 是否可用 |
---|---|---|
Ajax(XMLHttpRequest ) | 不重新加載整個(gè)頁面的情況下,可以與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁內(nèi)容,捕獲不到302狀態(tài)碼,并且假如后端響應(yīng)頭的Location返回的路徑與Ajax的Referer不一致的話,會產(chǎn)生跨域報(bào)錯(cuò)。 | × |
Fetch | 針對 302 的情況,其實(shí) fetch 有個(gè)特殊的配置叫 redirect,可以捕獲302的部分內(nèi)容。但是非常可惜的是,目前 response 的內(nèi)容非常有限,僅能捕獲到該接口訪問是否存在302,捕獲不到302的具體跳轉(zhuǎn)路徑,并且也不能跟隨跳轉(zhuǎn)。 | × |
Location.href | 瀏覽器地址直接跳轉(zhuǎn)接口,默認(rèn)采用Get請求,不存在跨域問題,瀏覽器也可以直接跟隨后端產(chǎn)生的302重定向。 | √ |
Form表單 | 通過刷新整個(gè)頁面進(jìn)行訪問請求,可使用Get/Post方法,也可以跟隨后端進(jìn)行的302跳轉(zhuǎn),缺點(diǎn)是需要新建一個(gè)表單,操作比較復(fù)雜。 | √ |
Nvigator.sendBeacon | navigator.sendBeacon() 方法可用于通過 HTTP POST 將少量數(shù)據(jù)異步傳輸?shù)?Web 服務(wù)器。同時(shí)避免了用傳統(tǒng)技術(shù)(如:XMLHttpRequest)發(fā)送分析數(shù)據(jù)的一些問題。缺點(diǎn)是僅支持POST請求,以及是異步操作,也不跟隨后端302。 | √ |
根據(jù)以上方式做一個(gè)測試:
我們做一個(gè)302重定向的接口,重定向的路徑是分別為http://localhost:3000/login和https://www.baidu.com,客戶端的域名為localhost,情況如下圖:
假如采用常用的Ajax,例如Axios或者Fetch,前端代碼以及效果如下:
1、Axios:當(dāng)點(diǎn)擊按鈕時(shí)候,調(diào)用/redirectTo接口,后端返回302重定向,此時(shí)我們可以看到,重定向后的地址并不是按照預(yù)期在瀏覽器上跳轉(zhuǎn),而是重新用XHR請求重定向之后的地址,此時(shí)由于接口請求頭的Referer為localhost:3000與RequestURL:https:www.baidu.com存在跨域問題,故報(bào)錯(cuò)。
那假如后端返回重定向的地址不存在跨域問題呢(此時(shí)和客戶端同域)?
此時(shí)雖然不存在跨域問題了,但是重定向后的地址因?yàn)槭鞘褂肵HR訪問的,然而你客戶端并沒有開啟Servlet等服務(wù),故接口會返回404NotFound。
綜上所述,使用Ajax處理302是行不通的。
2、采用Fetch,網(wǎng)上對于fetch眾說紛紜,經(jīng)測試,fetch也不能跟隨302跳轉(zhuǎn)頁面,會將請求后的報(bào)文體返回回來。
3、使用Location.href,無論重定向后的地址是否跨域,均可以成功重定向。
4、使用form表單做302跳轉(zhuǎn),也是可以成功的,但是需要?jiǎng)?chuàng)建一個(gè)虛擬節(jié)點(diǎn),處理起來較為復(fù)雜。
5、Nvigator.sendBeacon,由于該方法必須采用Post,故更改一下后端代碼。雖然使用該方法沒有跨域問題,但是由于是異步方法,并不會讓瀏覽器跟隨302操作。
總結(jié):使用Location.href直接訪問接口
上述五種方式,Ajax和Fetch皆是異步請求,不能跟隨瀏覽器302的操作,并且還獲取不到接口返回的Location等信息,所以不采用。Form表單可以使用,功能也較為全面,但是實(shí)現(xiàn)方式較為復(fù)雜,且Form表單通常用于表單內(nèi)容提交,與場景語義不符,故Pass**。Location.href的方式即以Get請求直接使用瀏覽器訪問該接口,參數(shù)攜帶方便,也能跟隨重定向操作,故采用。**
附上代碼:
import serviceInstance from "../../services"; // const res = serviceInstance({ // url: "/redirectTo", //不用引入,直接在api后面接接口 // method: "get", // data: {}, // }); // console.log(res); function Home() { const setRedirect = () => { const res = serviceInstance({ url: "/redirectTo", //不用引入,直接在api后面接接口 method: "get", data: {}, }); console.log(res); }; const useFetchSetRedirect = () => { const res = fetch("/redirectTo",{ method: "get", redirect:'follow' }); console.log(res); }; const useLocationRedirect = () => { window.location.href = "http://localhost:8080/redirectTo" }; const useFormData = ()=>{ const form = document.createElement("form"); form.action = "http://localhost:8080/redirectTo"; document.getElementById("container").appendChild(form); form.submit(); document.getElementById("container").removeChild(form); } const useSendBeacon = ()=>{ navigator.sendBeacon("http://localhost:8080/redirectToPost") } return ( <div id="container"> <button onClick={setRedirect}>測試Axios重定向</button> <button onClick={useFetchSetRedirect}>測試Fetch重定向</button> <button onClick={useLocationRedirect}>測試location重定向</button> <button onClick={useFormData}>測試Form表單重定向</button> <button onClick={useSendBeacon}>測試SendBeacon重定向</button> </div> ); } export default Home;
package com.xuan.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @RestController public class TestController { @GetMapping("/redirectTo") void testRedirect(HttpServletResponse response) throws IOException { String testUrl = "https://www.baidu.com"; // String testUrl2 = "http://localhost:3000/login"; response.sendRedirect(testUrl); } @PostMapping ("/redirectToPost") void testRedirectPost(HttpServletResponse response) throws IOException { String testUrl = "https://www.baidu.com"; // String testUrl2 = "http://localhost:3000/login"; response.sendRedirect(testUrl); } }
2、子系統(tǒng)(接入認(rèn)證中心的系統(tǒng))如何接入認(rèn)證中心,獲取登錄態(tài)?
背景:由于子系統(tǒng)和認(rèn)證中心是不同的系統(tǒng),在認(rèn)證中心登錄成功后重定向回子系統(tǒng)的過程中,如何得知已登錄的登錄態(tài)呢?
此時(shí)我們在重定向的過程中,需要傳遞信息給其他系統(tǒng),僅有三種方式(據(jù)我所知):
瀏覽器地址欄攜帶
Cookie
Window.postMessage
實(shí)現(xiàn)方式 特點(diǎn) 是否可用 瀏覽器地址欄攜帶 優(yōu)點(diǎn):操作方便,無同域限制 ; 缺點(diǎn):信息完全暴露在地址欄,安全性不高 √ Cookie 優(yōu)點(diǎn):在設(shè)置Cookie的時(shí)候可以通過Domain、Path、SameSite等字段,將Cookie設(shè)置在需要獲取的應(yīng)用上 ,安全性以及準(zhǔn)確性較高; 缺點(diǎn):遵循瀏覽器的同源限制,設(shè)置的Cookie僅在本域名或者子域名下共享。 √ Window.postMessage 是一種瀏覽器提供的跨域傳輸信息方式,在認(rèn)證中心完成登錄操作,拿到Token的話,可以使用該方式傳輸信息。但是與使用場景不符,故Pass掉 ×
總結(jié): 瀏覽器地址欄攜帶和Cookie均可以完成302后傳遞信息(assess-token或者code)的操作,其中各有優(yōu)缺點(diǎn),應(yīng)根據(jù)項(xiàng)目需要以及具體情況具體采用不同的方式。同域建議采用Cookie,不同域推薦采用瀏覽器地址欄攜帶。
- 子系統(tǒng)與認(rèn)證中心同域
采用Cookie方式可以較為簡單地實(shí)現(xiàn)單點(diǎn)登錄,設(shè)置Cookie(access-token)到具體的域(Domain),通過Path去限制相應(yīng)的系統(tǒng),這樣可以發(fā)揮認(rèn)證中心實(shí)現(xiàn)單點(diǎn)登錄的效果。但是瀏覽器必須把Cookie打開,以及應(yīng)對Cookie具體設(shè)置對應(yīng)的條件,以防其他系統(tǒng)通過CSRF等手段,獲取到用戶信息。
- 子系統(tǒng)與認(rèn)證中心跨域
建議采用瀏覽器地址欄攜傳遞信息,這個(gè)時(shí)候考慮到安全問題,不應(yīng)該采用明文的形勢將access-token放到地址欄,而是將重定向后攜帶的code通過地址欄傳輸回去子系統(tǒng),然后子系統(tǒng)通過這個(gè)code調(diào)用接口獲取access-token(采用空白頁的方式)。
3、拓展:302跳轉(zhuǎn)如何SetCookie到對應(yīng)的系統(tǒng)。
背景:出現(xiàn)在本地聯(lián)調(diào)的情況,后端設(shè)置重定向到對應(yīng)的系統(tǒng),并SetCookie到開發(fā)環(huán)境,設(shè)置Domain為開發(fā)環(huán)境的ip/域名,但是發(fā)現(xiàn)Cookie并未設(shè)置上。
故排查原因,發(fā)現(xiàn)是因?yàn)橹囟ㄏ虻慕涌诘?strong>請求頭中Host與后端設(shè)置的Domain不一致,Cookie被屏蔽掉了。報(bào)錯(cuò)如下圖:
為此我做了個(gè)測試,模擬設(shè)置Cookie到百度的網(wǎng)站上:
首先設(shè)置Host文件(127.0.0.1 test.baidu.com),模擬百度的域名到本機(jī)ip;
然后在后端代碼重定向到www.baidu.com,同時(shí)設(shè)置cookie到baidu.com這個(gè)域名上。
@GetMapping("/setCookieRedirect") void testCookieRedirect(HttpServletResponse response) throws IOException { String testUrl = "http://baidu.com"; Cookie cookie = new Cookie("testCookie","test"); cookie.setDomain("baidu.com"); cookie.setMaxAge(43200); cookie.setSecure(false); cookie.setHttpOnly(false); response.addCookie(cookie); response.sendRedirect(testUrl); }
重點(diǎn):前端調(diào)用該后端接口時(shí),不可以用localhost調(diào)用,而是用test.baidu.com這個(gè)域名調(diào)用,如下:
const testThirdCookie = ()=>{ window.location. }
最后成功設(shè)置Cookie到百度上,效果如下:
總結(jié):關(guān)鍵就是請求頭的host與設(shè)置的Domain對象域名得一致,或者父級域名包括子級域名即可。
const testThirdCookie = ()=>{ window.location. }
最后成功設(shè)置Cookie到百度上,效果如下:
總結(jié):關(guān)鍵就是請求頭的host與設(shè)置的Domain對象域名得一直,或者父級域名包括子級域名即可。
總結(jié)
到此這篇關(guān)于前端遇到302重定向問題處理方式及設(shè)置第三方Cookie研究的文章就介紹到這了,更多相關(guān)前端302處理及設(shè)置第三方Cookie內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深度卷積神經(jīng)網(wǎng)絡(luò)各種改進(jìn)結(jié)構(gòu)塊匯總
這篇文章主要為大家介紹了深度卷積神經(jīng)網(wǎng)絡(luò)各種改進(jìn)結(jié)構(gòu)塊匯總,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05最新WebStorm2020.2注冊碼永久激活(激活到2089年)
JetBrains旗下有多款編譯器工具(如:IntelliJ、WebStorm、PyCharm等)在各編程領(lǐng)域幾乎都占據(jù)了壟斷地位。今天給大家?guī)淼氖菍ebStorm最新版激活至2089年2020-09-09基于ChatGPT使用AI實(shí)現(xiàn)自然對話的原理分析
ChatGPT是當(dāng)前自然語言處理領(lǐng)域的重要進(jìn)展之一,可以生成高質(zhì)量的文本,可應(yīng)用于多種場景,如智能客服、聊天機(jī)器人、語音助手等。本文將詳細(xì)介紹ChatGPT的原理、實(shí)戰(zhàn)演練和流程圖,幫助讀者更好地理解ChatGPT技術(shù)的應(yīng)用和優(yōu)勢2023-05-05如何集成Elasticsearch到django restful
在Django項(xiàng)目中集成Elasticsearch可通過Haystack實(shí)現(xiàn),Haystack作為Django插件提供搜索接口,Elasticsearch作為后端搜索引擎存儲檢索數(shù)據(jù),Haystack支持多種搜索引擎,易于切換且不需改動代碼,本文給大家介紹如何集成Elasticsearch到django restful,感興趣的朋友一起看看吧2024-09-09鴻蒙NEXT元服務(wù)之如何利用App?Linking實(shí)現(xiàn)無縫跳轉(zhuǎn)與二維碼拉起
本文介紹了如何使用AppLinking技術(shù)實(shí)現(xiàn)元服務(wù)之間的無縫跳轉(zhuǎn),并通過生成二維碼的方式快速拉起元服務(wù),從而簡化用戶操作流程,增強(qiáng)應(yīng)用的互動性和推廣效率,感興趣的朋友跟隨小編一起看看吧2024-11-11Delphi 本地路徑的創(chuàng)建、清空本地指定文件夾下的文件
這篇文章主要介紹了Delphi 本地路徑的創(chuàng)建、清空本地指定文件夾下的文件,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08偽靜態(tài)技術(shù)介紹與優(yōu)缺點(diǎn)分析(較完整篇)
偽靜態(tài)太適合用在普通的企業(yè)網(wǎng)站上了——既不要求高并發(fā),但同時(shí)又很在乎seo(搜索引擎優(yōu)化),而且也要求后臺可動態(tài)更新。2009-11-11