狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

終于理解了 Next.js 中的 Cookie

admin
2024年11月27日 14:52 本文熱度 816

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)用:

npx create-next-app@latest next-cookie

在安裝過(guò)程中,選擇你偏好的配置。不過(guò),別忘了為"use App router?"選項(xiàng)選擇"Yes"。完成基本設(shè)置后

如何獲取 Cookie

要在服務(wù)器組件中讀取傳入的請(qǐng)求 Cookie 值,我們使用 cookies().get(cookieName) 方法,如下所示:

// app/page.js

import { cookies } from "next/headers";

const Home = () => {
  const cookieStore = cookies();
  const userId = cookieStore.get("user_id");

  return <>{userId && <p>User ID: {userId}</p>}</>;
};

export default Home;

在本例中,如果沒(méi)有存儲(chǔ)帶有user_id標(biāo)簽的 cookie,我們將看到一個(gè)空白屏幕。但是,如果有多個(gè) cookie 與此標(biāo)記匹配,userId將被設(shè)置為第一個(gè)匹配,并顯示在瀏覽器上。

要獲取與某個(gè)名稱匹配的所有 cookie,我們可以使用cookies().getAll()方法,如下所示:

// app/page.js

import { cookies } from "next/headers";

const Home = () => {
  const cookieStore = cookies();
  const userId = cookieStore.getAll("user_id");

  return (
    <>
      {userId.length > 0 &&
        userId.map((cookie) => (
          <div key={cookie.name}>
            <p>Name: {cookie.name}</p>
            <p>Value: {cookie.value}</p>
          </div>
        ))}
    </>
  );
};

export default Home;

在這個(gè)更新的示例中,如果有多個(gè)帶有user_id標(biāo)記的 cookie,我們就會(huì)遍歷它們,并顯示每個(gè) cookie 的名稱和值。

如何設(shè)置 cookie

我們可以通過(guò) cookies().set() 方法設(shè)置新的 Cookie。但是,由于 HTTP 不允許在流式傳輸開(kāi)始后設(shè)置 Cookie,我們只能在服務(wù)器操作(Server Actions)或 API 路由中修改 Cookie 值(設(shè)置和刪除)。以下是一個(gè)例子:

// app/page.js

import { cookies } from "next/headers";

const Home = () => {
  async function createThemeCookie(formData) {
    "use server";

    const selectedTheme = formData.get("theme");
    cookies().set("theme", selectedTheme);
  }

  return (
    <>
      <form action={createThemeCookie}>
        <select name="theme">
          <option value="dark">Dark Theme</option>
          <option value="light">Light Theme</option>
        </select>
        <button type="submit">Create Theme Cookie</button>
      </form>
    </>
  );
};

export default Home;

在這個(gè)例子中,我們用"use server"語(yǔ)句標(biāo)記了設(shè)置 Cookie 的函數(shù),將其指定為服務(wù)器操作。然后我們渲染了一個(gè)表單,允許用戶選擇首選主題。用戶提交表單后,我們獲取他們選擇的主題值并將其設(shè)置到 theme cookie 中。

此外,我們可以使用以下語(yǔ)法在設(shè)置新 Cookie 時(shí)傳入額外選項(xiàng):

cookies().set({
  name: "theme",
  value: "light || dark",
  httpOnly: true,
  path: "/",
  maxAge: 60 * 60 * 24 * 365 * 1000,
  expires: new Date(Date.now() + 60 * 60 * 24 * 365 * 1000),
});

這樣,我們可以創(chuàng)建一個(gè) httpOnly cookie 并設(shè)置 cookie 的路徑、最大年齡和過(guò)期日期。

如果你使用的 Next.js 版本低于v14,在使用服務(wù)器操作時(shí)可能會(huì)遇到以下錯(cuò)誤:

Error: 
  × To use Server Actions, please enable the feature flag in your Next.js config.

要修復(fù)這個(gè)問(wèn)題,只需更新你的 next.config.js 文件以啟用實(shí)驗(yàn)性的 serverActions,如下所示:

const nextConfig = {
  experimental: {
    serverActions: true,
  },
  // . . .
};

module.exports = nextConfig;

但是,如果你使用的是 Next.js v14 或更新版本,則不會(huì)遇到此類錯(cuò)誤。

如何刪除 Cookie

我們可以使用 cookies().delete(name) 方法刪除 Cookie。但是,和設(shè)置 Cookie 一樣,我們只能在服務(wù)器操作或 API 路由中使用此方法,如下所示:

// app/page.js

import { cookies } from "next/headers";

const Home = () => {
  async function deleteThemeCookie(formData{
    "use server";

    cookies().delete("theme");
  }

  return (
    <>
      <form action={deleteThemeCookie}>
        <button type="submit">Delete Theme Cookie</button>
      </form>
    </>

  );
};

export default Home;

通過(guò)上面這個(gè)例子,當(dāng)用戶點(diǎn)擊按鈕提交表單時(shí),theme cookie 將從瀏覽器中刪除。

Next.js 路由處理程序和 API 路由中的 Cookie

在 Next.js 路由處理程序(即 /app 目錄的 API 路由等價(jià)物)中,我們可以自由使用我們剛剛介紹的所有 cookie 方法,而無(wú)需創(chuàng)建服務(wù)器操作。你可以在下面看到一個(gè)例子:

// app/api/route.js

import { cookies } from "next/headers";
export async function GET(request{
  const cookieStore = cookies();

  // 獲取 Cookie
  const myCookie = cookieStore.get("cookieName");

  // 獲取所有 Cookie
  const myCookies = cookieStore.getAll("cookieName");

  // 設(shè)置 Cookie
  cookies().set("cookieName""value");

  // 刪除 Cookie
  cookies().delete("cookieName");

  return new Response("Hello, World!", {
    status200,
  });
}

另外,你也可以在路由處理程序和 API 路由中使用傳統(tǒng)的 Web API 從請(qǐng)求中讀取 cookie,如下所示:

// app/api/route.js 或 pages/api/index.js

export async function GET(request{
  let theme = request.cookies.get("theme");
  return new Response(JSON.stringify(theme));
}

在這個(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:

npm install react-cookie

要開(kāi)始使用這些 Hook,在 _app.tsx 文件中添加 CookiesProvider 組件,如下所示:

import type { AppProps } from 'next/app';
import { CookiesProvider } from 'react-cookie';

function MyApp({ Component, pageProps }: AppProps{
  return (
    <CookiesProvider>
      <Component {...pageProps} />
    </CookiesProvider>

  );
}

export default MyApp;

我們首先添加一個(gè) useEffect Hook 來(lái)在加載時(shí)獲取所有 cookie:

import { useCookies } from 'react-cookie';

const Home: NextPage = () => {
  const [cookies, setCookie, removeCookie] = useCookies(['user']);

  useEffect(() => {
    console.log('Cookies: ', cookies);
  }, [cookies]);

  return (
  <div>...</div>
)}

目前,你應(yīng)該還看不到任何 cookie。所以,我們創(chuàng)建一個(gè)使用 setCookie() 函數(shù)來(lái)設(shè)置 cookie 的函數(shù):

import { useRouter } from 'next/router';

//...在默認(rèn)函數(shù)內(nèi)部
const router = useRouter();

const setCookieHandler = () => {
  setCookie('new-user'true, {
    path'/',
  });

  router.replace("/");
};

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è)按鈕上。輸入以下代碼:

{!cookies['user'] && (
  <button onClick={setCookieHandler} className={styles.button}>
    Complete new user registration!
  </button>

)}

在這種情況下,只有當(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ù):

const removeCookieHandler = () => {
  removeCookie('new-user');

  router.replace("/");
};

接下來(lái),將它綁定到另一個(gè)只有在 cookie 可用時(shí)才會(huì)渲染的按鈕上。這意味著什么?如果用戶已注冊(cè),cookie 就會(huì)可用。代碼看起來(lái)是這樣的:

{cookies['new-user'] && (
  <button onClick={removeCookieHandler} className={styles.resetbutton}>
    Reset new user registration
  </button>

)}

下面是它在應(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ì)比:

  • react-cookie 更加流行,提供簡(jiǎn)單易用的 API 并與 React 框架高度兼容
  • cookies-next 是專門(mén)為 Next.js 創(chuàng)建的相對(duì)較新的包,提供服務(wù)器端渲染功能和改進(jìn)的安全措施

另一個(gè)關(guān)于 cookies-next 令人驚喜的事實(shí)(這個(gè)是給那些關(guān)心包大小的開(kāi)發(fā)者) - 它比 react-cookie 的包體積更小。這使得它在你的下一個(gè)項(xiàng)目中更具吸引力! ??

按照慣例,讓我們首先用以下命令安裝 cookies-next:

npm install cookies-next

cookies-next 包內(nèi)置了類似于 react-cookie 包的功能。這些功能可用于設(shè)置和刪除 cookie。讓我們用以下代碼創(chuàng)建用于設(shè)置和刪除 cookie 的處理函數(shù):

// 添加 cookie
const addCookie = () => {
  setCookie('user'true, {
    path'/',
  });
  router.replace('/');
};

// 刪除 cookie
const removeCookie = () => {
  deleteCookie('user', {
    path'/',
  });
  router.replace('/');
};

完成后,你可以通過(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ù):

export default function handler (
  req: NextApiRequest,
  res: NextApiResponse
{
  return;  
}

我們將設(shè)置 cookie 來(lái)表示用戶的可信度,并在特定時(shí)間后過(guò)期。更具體地說(shuō),如果有某種驗(yàn)證(比如用于檢查憑證的數(shù)據(jù)庫(kù)或某些 OTP 邏輯),它就會(huì)過(guò)期。處理函數(shù)如下:

if (
    req.method === 'POST' // 只允許 POST 請(qǐng)求
  ) {
  // 從請(qǐng)求體中獲取用于驗(yàn)證的憑證
  const { name } = req.body;

  // OTP 驗(yàn)證邏輯

  // 設(shè)置 cookie
  setCookie('authorize'true, {
    req,
    res,
    maxAge: 60 * 60 * 24 * 7// 1 周
    path: '/',
  });

  // 響應(yīng)狀態(tài)和消息
  return res.status(200).json({
    message: `${name} is authorized to access`,
    authorize: true,
    code: '20-0101-2092',
  });
}

在這里,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ù):

const verifyOTP = async (name: string) => {
  const response = await fetch('/api/verify-otp', {
    method: 'POST',
    body: JSON.stringify({ name }),
  });

  const data = await response.json();

  if (data.authorize) {
    setAuthorization(true);
    setLaunchCode(data.code);
  } else {
    setAuthorization(false);
    alert('Invalid OTP');
  }
};

我們可以使用 useState Hook 來(lái)存儲(chǔ)來(lái)自 API 路由的數(shù)據(jù),并基于 isAuthorized 變量有條件地渲染按鈕。使用以下代碼:

const [isAuthorized, setAuthorization] = useState(false);
const [launchCode, setLaunchCode] = useState('');

完成這些后,試試到目前為止寫(xiě)的代碼。你可以通過(guò)打開(kāi)開(kāi)發(fā)者工具并選擇 Application 部分來(lái)檢查 cookie 是否存在。

Next.js 中間件中的 Cookie

Next.js 中間件設(shè)計(jì)在 Pages Router 和 App Router 中是一致的。因此,在中間件中處理 cookie 的方式對(duì)兩者都是相同的。例如,我們可以通過(guò)中間件請(qǐng)求獲取和刪除 cookie,如下所示:

// middleware.js

export function middleware(request{
  // 獲取 Cookie
  let cookie = request.cookies.get("cookieName");
  console.log(cookie);
  // 獲取所有 Cookie
  const allCookies = request.cookies.getAll();
  console.log(allCookies);
  // 刪除 Cookie
  request.cookies.delete("cookieName");
}

要在中間件中設(shè)置新的 cookie,我們還可以利用 NextResponse API,如下所示:

// middleware.js

import { NextResponse } from "next/server";

export function middleware(request{
  const response = NextResponse.next();
  // 設(shè)置 cookies
  response.cookies.set("foo""bar");
  // 或者
  response.cookies.set({
    name"foo",
    value"bar",
    path"/",
    // . . .
  });
  return response;
}

這樣,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)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved