終于理解了 Next.js 中的 Cookie
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
Cookie 是瀏覽器中默默存在的數(shù)據(jù)塊。雖然有些 Cookie 會(huì)侵犯用戶隱私,但其他一些則試圖通過(guò)跟蹤用戶的瀏覽習(xí)慣、偏好等來(lái)改善瀏覽體驗(yàn)。Cookie 在許多場(chǎng)景都很有用,包括身份驗(yàn)證、改善用戶體驗(yàn)和加快響應(yīng)時(shí)間。 在本文中,我們將探討如何在 Next.js 的服務(wù)器組件和客戶端組件以及中間件中管理 Cookie。我們還將介紹兩個(gè)可以在 Next.js Pages Router 中設(shè)置 Cookie 的包,并將它們應(yīng)用到實(shí)際用例中。 要跟隨本教程學(xué)習(xí),可以前往此 GitHub 倉(cāng)庫(kù)。 https://github.com/GeoBrodas/cookies-with-nextjs Cookie:福祉還是禍害?Cookie 是 Web 應(yīng)用程序放置在用戶計(jì)算機(jī)上的小數(shù)據(jù)塊,用于存儲(chǔ)狀態(tài)信息,如用戶偏好或會(huì)話管理,也用于跟蹤目的。 近年來(lái),關(guān)于 Cookie 的討論引發(fā)了很多爭(zhēng)議,因?yàn)樗鼈兗扔袃?yōu)點(diǎn)也有缺點(diǎn)。 一方面,Cookie 可以幫助你輕松存儲(chǔ)用戶的個(gè)性化數(shù)據(jù),讓你能更好地為每個(gè)用戶定制用戶體驗(yàn)。另一方面,Cookie 跟蹤用戶在線行為的能力引發(fā)了隱私擔(dān)憂。 因此,現(xiàn)在有了一些標(biāo)準(zhǔn)和法規(guī),要求 Web 應(yīng)用程序披露其 Cookie 使用情況,并讓用戶選擇是否退出。 鑒于 Next.js 的多功能性,有多種方法可以管理 Cookie。在此之前,我們只需要在頁(yè)面、API 路由和中間件中管理 Cookie。然而,Next 13 中添加的服務(wù)器組件引入了更多新技術(shù)。 客戶端 vs 服務(wù)器端 Cookie很多人問(wèn)的一個(gè)問(wèn)題是客戶端和服務(wù)器端 Cookie 是否有區(qū)別。 Cookie 可以通過(guò)客戶端和服務(wù)器端操作創(chuàng)建。服務(wù)器端 Cookie 通常是通過(guò) HTTP 標(biāo)頭創(chuàng)建和訪問(wèn)的。無(wú)論如何創(chuàng)建,Cookie 都存儲(chǔ)在用戶的瀏覽器中,可以直接在客戶端訪問(wèn)。 但是,httpOnly Cookie 是個(gè)例外。如果你創(chuàng)建啟用了 httpOnly 屬性的 Cookie,這些 Cookie 就不能通過(guò)客戶端操作直接訪問(wèn),從而降低XSS攻擊的風(fēng)險(xiǎn)。 在服務(wù)器組件中處理 Cookie:Next.js App Router我們首先探討如何在使用 Next.js App Router 的服務(wù)器組件中訪問(wèn)和修改 Cookie。要繼續(xù),請(qǐng)運(yùn)行以下命令創(chuàng)建一個(gè)新的 Next 應(yīng)用:
在安裝過(guò)程中,選擇你偏好的配置。不過(guò),別忘了為"use App router?"選項(xiàng)選擇"Yes"。完成基本設(shè)置后 如何獲取 Cookie要在服務(wù)器組件中讀取傳入的請(qǐng)求 Cookie 值,我們使用
在本例中,如果沒(méi)有存儲(chǔ)帶有user_id標(biāo)簽的 cookie,我們將看到一個(gè)空白屏幕。但是,如果有多個(gè) cookie 與此標(biāo)記匹配,userId將被設(shè)置為第一個(gè)匹配,并顯示在瀏覽器上。 要獲取與某個(gè)名稱匹配的所有 cookie,我們可以使用
在這個(gè)更新的示例中,如果有多個(gè)帶有 如何設(shè)置 cookie我們可以通過(guò)
在這個(gè)例子中,我們用"use server"語(yǔ)句標(biāo)記了設(shè)置 Cookie 的函數(shù),將其指定為服務(wù)器操作。然后我們渲染了一個(gè)表單,允許用戶選擇首選主題。用戶提交表單后,我們獲取他們選擇的主題值并將其設(shè)置到 theme cookie 中。 此外,我們可以使用以下語(yǔ)法在設(shè)置新 Cookie 時(shí)傳入額外選項(xiàng):
這樣,我們可以創(chuàng)建一個(gè) httpOnly cookie 并設(shè)置 cookie 的路徑、最大年齡和過(guò)期日期。 如果你使用的 Next.js 版本低于v14,在使用服務(wù)器操作時(shí)可能會(huì)遇到以下錯(cuò)誤:
要修復(fù)這個(gè)問(wèn)題,只需更新你的 next.config.js 文件以啟用實(shí)驗(yàn)性的 serverActions,如下所示:
但是,如果你使用的是 Next.js v14 或更新版本,則不會(huì)遇到此類錯(cuò)誤。 如何刪除 Cookie我們可以使用 cookies().delete(name) 方法刪除 Cookie。但是,和設(shè)置 Cookie 一樣,我們只能在服務(wù)器操作或 API 路由中使用此方法,如下所示:
通過(guò)上面這個(gè)例子,當(dāng)用戶點(diǎn)擊按鈕提交表單時(shí),theme cookie 將從瀏覽器中刪除。 Next.js 路由處理程序和 API 路由中的 Cookie在 Next.js 路由處理程序(即 /app 目錄的 API 路由等價(jià)物)中,我們可以自由使用我們剛剛介紹的所有 cookie 方法,而無(wú)需創(chuàng)建服務(wù)器操作。你可以在下面看到一個(gè)例子:
另外,你也可以在路由處理程序和 API 路由中使用傳統(tǒng)的 Web API 從請(qǐng)求中讀取 cookie,如下所示:
在這個(gè)例子中,我們直接從請(qǐng)求對(duì)象中獲取 theme cookie 并將其作為 API 響應(yīng)返回。 在 Next.js Pages Router 中處理 Cookie現(xiàn)在,讓我們看看如何在經(jīng)典的 Next.js Pages Router 中管理 Cookie。首先,創(chuàng)建一個(gè)新的 Next.js 應(yīng)用程序,并確保在配置過(guò)程中選擇 pages router。 在 Next.js 中使用 react-cookie我們要探索的第一個(gè)包是 react-cookie。這個(gè)包旨在幫助你在 React 應(yīng)用程序中加載和保存 cookie。為了嘗試一下,我們將創(chuàng)建一個(gè)簡(jiǎn)單的應(yīng)用程序來(lái)跟蹤注冊(cè)用戶。 使用以下代碼安裝 react-cookie:
要開(kāi)始使用這些 Hook,在 _app.tsx 文件中添加 CookiesProvider 組件,如下所示:
我們首先添加一個(gè) useEffect Hook 來(lái)在加載時(shí)獲取所有 cookie:
目前,你應(yīng)該還看不到任何 cookie。所以,我們創(chuàng)建一個(gè)使用 setCookie() 函數(shù)來(lái)設(shè)置 cookie 的函數(shù):
setCookie() 函數(shù)接受三個(gè)參數(shù):鍵名、鍵值和一些配置選項(xiàng)。這些選項(xiàng)包括 MaxAge、Path、Domain、expires 等。在這種情況下使用了 path 選項(xiàng),允許程序從任何位置訪問(wèn)該 cookie。 如你所見(jiàn),我們還使用了 useRouter() Hook 通過(guò) replace() 方法重新加載頁(yè)面,以避免在歷史堆棧中添加 URL 條目。這樣看起來(lái)就像頁(yè)面重新渲染了一樣! 隨著我們繼續(xù)前進(jìn),請(qǐng)記住本教程僅專注于演示特定包的功能。因此,我們將假設(shè)你理解認(rèn)證流程等概念。 要了解更多關(guān)于 Next.js 中的認(rèn)證信息,請(qǐng)參考這個(gè)關(guān)于 SuperTokens 的指南。你也可以在這篇文章中回顧認(rèn)證流程。 將函數(shù)綁定到按鈕接下來(lái),讓我們將這個(gè)函數(shù)綁定到一個(gè)按鈕上。輸入以下代碼:
在這種情況下,只有當(dāng) cookie 存在時(shí)按鈕才會(huì)渲染。運(yùn)行開(kāi)發(fā)服務(wù)器來(lái)看看這個(gè)效果。你可以通過(guò)按 Control+Shift+J 打開(kāi)開(kāi)發(fā)者工具,然后選擇 Application 部分來(lái)直觀地看到這個(gè) cookie。 ? 現(xiàn)在,我們刪除 cookie 以允許用戶退出。首先,編寫(xiě)另一個(gè)函數(shù):
接下來(lái),將它綁定到另一個(gè)只有在 cookie 可用時(shí)才會(huì)渲染的按鈕上。這意味著什么?如果用戶已注冊(cè),cookie 就會(huì)可用。代碼看起來(lái)是這樣的:
下面是它在應(yīng)用程序中的樣子: 使用 cookies-next 包接下來(lái),我們來(lái)看看如何使用 cookies-next 包。這個(gè)包更適合 Next.js 生態(tài)系統(tǒng),因?yàn)樗梢栽谌魏蔚胤绞褂?- 無(wú)論是在 Pages Router 還是 App Router 中,在客戶端,通過(guò) getServerSideProps 在服務(wù)器端,甚至在 Next.js API 路由中。 以下是這兩個(gè)包的對(duì)比:
另一個(gè)關(guān)于 cookies-next 令人驚喜的事實(shí)(這個(gè)是給那些關(guān)心包大小的開(kāi)發(fā)者) - 它比 react-cookie 的包體積更小。這使得它在你的下一個(gè)項(xiàng)目中更具吸引力! ?? 按照慣例,讓我們首先用以下命令安裝 cookies-next:
cookies-next 包內(nèi)置了類似于 react-cookie 包的功能。這些功能可用于設(shè)置和刪除 cookie。讓我們用以下代碼創(chuàng)建用于設(shè)置和刪除 cookie 的處理函數(shù):
完成后,你可以通過(guò)將其綁定到在 cookie 存在時(shí)渲染的不同按鈕來(lái)測(cè)試它。除了 getServerSideProps 和 API 路由外,你還可以在應(yīng)用程序的服務(wù)器端使用 cookies-next 包。 讓我們看一個(gè)例子,用戶收到一些信息,對(duì)其進(jìn)行驗(yàn)證,然后設(shè)置一個(gè) cookie 來(lái)表示信息的合法性,所有這些都在 API 路由上完成。 實(shí)現(xiàn) API 路由繼續(xù)在 ./pages/api/verify-otp.ts 中創(chuàng)建一個(gè)新的 API 路由。在文件中,用以下代碼創(chuàng)建一個(gè)基本的處理函數(shù):
我們將設(shè)置 cookie 來(lái)表示用戶的可信度,并在特定時(shí)間后過(guò)期。更具體地說(shuō),如果有某種驗(yàn)證(比如用于檢查憑證的數(shù)據(jù)庫(kù)或某些 OTP 邏輯),它就會(huì)過(guò)期。處理函數(shù)如下:
在這里,cookie 會(huì)在一周后過(guò)期,并要求用戶重新驗(yàn)證。在驗(yàn)證成功后,API 會(huì)返回一個(gè)狀態(tài)為 200 的消息,其中包含可以在前端顯示的相關(guān)數(shù)據(jù)。 從前端訪問(wèn) API 路由現(xiàn)在,我們嘗試從前端訪問(wèn)這個(gè)路由。該函數(shù)只能在用戶首次注冊(cè)時(shí)觸發(fā)。使用以下代碼創(chuàng)建函數(shù):
我們可以使用 useState Hook 來(lái)存儲(chǔ)來(lái)自 API 路由的數(shù)據(jù),并基于 isAuthorized 變量有條件地渲染按鈕。使用以下代碼:
完成這些后,試試到目前為止寫(xiě)的代碼。你可以通過(guò)打開(kāi)開(kāi)發(fā)者工具并選擇 Application 部分來(lái)檢查 cookie 是否存在。 Next.js 中間件中的 CookieNext.js 中間件設(shè)計(jì)在 Pages Router 和 App Router 中是一致的。因此,在中間件中處理 cookie 的方式對(duì)兩者都是相同的。例如,我們可以通過(guò)中間件請(qǐng)求獲取和刪除 cookie,如下所示:
要在中間件中設(shè)置新的 cookie,我們還可以利用 NextResponse API,如下所示:
這樣,cookie 就會(huì)全局設(shè)置在用戶的瀏覽器中,并可以在我們之前演示的 Next.js 頁(yè)面中訪問(wèn)。 常見(jiàn)的 Next.js Cookie 問(wèn)題及解決方案sameSite 功能是 cookie 的一個(gè)重要屬性,但它也可能在生產(chǎn)級(jí)應(yīng)用程序中造成問(wèn)題: sameSite 功能僅表明是否可以通過(guò)具有不同源的其他網(wǎng)站檢索 cookie。理想情況下,這應(yīng)該是準(zhǔn)確的,因?yàn)樗惶峁┝艘粚臃烙缯竟舻谋Wo(hù)。 為了確定方案和域名的最后部分是否匹配,sameSite 瀏覽器機(jī)制會(huì)分析目標(biāo) URI 和來(lái)自客戶端的請(qǐng)求: 由于 sameSite 參數(shù)默認(rèn)設(shè)置為 true,如果你是一個(gè)經(jīng)常使用其他智能手機(jī)并通過(guò)開(kāi)發(fā)服務(wù)器托管在本地主機(jī)上的私有 IP 地址連接的開(kāi)發(fā)者,cookie 將不會(huì)被注冊(cè)。 domain 屬性是 cookie 的一個(gè)關(guān)鍵但有時(shí)容易混淆的元素。這個(gè)屬性決定了哪些域可以訪問(wèn)該 cookie。如果沒(méi)有指定域,cookie 的默認(rèn)域分配將是最初生成它的域。 這就是為什么在多個(gè)子域試圖訪問(wèn)相同 cookie 的情況下,建議設(shè)置 domain 屬性: 結(jié)論Cookie 對(duì)于 Web 開(kāi)發(fā)至關(guān)重要。react-cookie 和 cookies-next 包由于其獨(dú)特的特性和優(yōu)勢(shì),非常適合各種使用場(chǎng)景。 react-cookie 更受歡迎,提供簡(jiǎn)單易用的 API 和與 React 框架的良好兼容性。相比之下,cookies-next 是一個(gè)專門(mén)為 Next.js 創(chuàng)建的相對(duì)較新的包,提供服務(wù)器端渲染功能和改進(jìn)的安全措施。 另一個(gè)令人驚喜的事實(shí) - 這是給所有注重包大小的開(kāi)發(fā)者的 - 就是與 react-cookie 相比,cookies-next 的包體積更小。這本質(zhì)上使它在你的下一個(gè)項(xiàng)目中更具吸引力! ?? 該文章在 2024/11/27 14:52:24 編輯過(guò) |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |