跳過到頁腳內容
NODE 說明

next-auth NPM(開發者的使用方法)

身份驗證對於現代 Web 應用程式至關重要,它能確保使用者安全地存取其資料和功能,並提供基礎設施支援。 NextAuth.js 是一個強大且靈活的身份驗證庫,旨在與 Next.js 無縫協作。 本文將探討如何在 Next.js 專案中設定和使用 NextAuth.js,以便輕鬆保護使用者資料。 我們還將向您展示如何將此 npm 與其他庫(例如 IronPDF 庫)集成,從而為您的專案實現直觀的無狀態身份驗證。

NextAuth.js 是什麼?

NextAuth.js 是一個面向 Next.js 應用的開源身份驗證庫,它提供了一種靈活且安全的 Web 應用驗證實作方式。借助 NextAuth.js,開發者可以輕鬆地將身份驗證整合到 Next.js 專案中,而無需處理複雜的使用者身份驗證和會話管理。

該軟體包具有高度可配置性,可讓開發人員自訂身份驗證流程、保護 API 路由並無縫處理使用者會話。 透過增強的功能,您可以建立管理帳戶存取的程式、加密和解碼 JSON Web Tokens 以及建立自訂 cookie 安全性原則和會話屬性,從而可以控制帳戶存取和會話驗證的頻率。

為什麼選擇 NextAuth.js?

NextAuth.js 有以下幾個優點:

*易於使用*:設定簡單,配置極少。 靈活性:支援多種身份驗證提供者,包括 OAuth、電子郵件/密碼等。 安全性:內建安全功能,可保護您自己的資料庫中的使用者資料。 可擴展性**:易於擴展以滿足自訂身份驗證需求。

NextAuth.js npm 入門指南

首先,我們建立一個新的 Next.js 專案。 打開終端機並運作:

npx create-next-app@latest my-next-auth-app
cd my-next-auth-app
npx create-next-app@latest my-next-auth-app
cd my-next-auth-app
SHELL

接下來,安裝 NextAuth.js:

npm install next-auth
npm install next-auth
SHELL

設定 NextAuth.js

為你的 API 路由建立一個新檔案來處理身份驗證。 在pages/api/auth目錄下,建立以下[...nextauth].js檔案:

// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import GitHubProvider from 'next-auth/providers/github';
import GoogleProvider from 'next-auth/providers/google';

// Configuring NextAuth to use GitHub and Google providers for authentication
export default NextAuth({
  providers: [
    GitHubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET, // Secret for encrypting tokens if needed
});
// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import GitHubProvider from 'next-auth/providers/github';
import GoogleProvider from 'next-auth/providers/google';

// Configuring NextAuth to use GitHub and Google providers for authentication
export default NextAuth({
  providers: [
    GitHubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET, // Secret for encrypting tokens if needed
});
JAVASCRIPT

環境變數

在專案根目錄下建立一個.env.local文件,用於儲存環境變數:

# Just make sure to fill out the variables with your actual information!
GITHUB_ID=your_github_client_id
GITHUB_SECRET=your_github_client_secret
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
NEXTAUTH_SECRET=your_nextauth_secret

為您的應用程式新增身份驗證

現在,讓我們為您的應用程式添加身份驗證功能。 建立登入按鈕和個人資料元件,用於顯示使用者資訊。

// components/LoginButton.js
import { signIn, signOut, useSession } from 'next-auth/react';

const LoginButton = () => {
  const { data: session, status } = useSession();
  const loading = status === "loading"; // Used to determine loading state
  return (
    <div>
      {!session && ( // Render sign-in buttons when session is not active
        <>
          <button onClick={() => signIn('github')}>Sign in with GitHub</button>
          <button onClick={() => signIn('google')}>Sign in with Google</button>
        </>
      )}
      {session && ( // Display user info and sign-out option when session is active
        <>
          <p>Signed in as {session.user.email}</p>
          <button onClick={() => signOut()}>Sign out</button>
        </>
      )}
    </div>
  );
};

export default LoginButton;
// components/LoginButton.js
import { signIn, signOut, useSession } from 'next-auth/react';

const LoginButton = () => {
  const { data: session, status } = useSession();
  const loading = status === "loading"; // Used to determine loading state
  return (
    <div>
      {!session && ( // Render sign-in buttons when session is not active
        <>
          <button onClick={() => signIn('github')}>Sign in with GitHub</button>
          <button onClick={() => signIn('google')}>Sign in with Google</button>
        </>
      )}
      {session && ( // Display user info and sign-out option when session is active
        <>
          <p>Signed in as {session.user.email}</p>
          <button onClick={() => signOut()}>Sign out</button>
        </>
      )}
    </div>
  );
};

export default LoginButton;
JAVASCRIPT

程式碼說明

LoginButton元件使用 NextAuth.js 處理 Next.js 應用程式中的使用者驗證。 它使用useSession鉤子來確定使用者是否已登入。 如果使用者未通過身份驗證,則會顯示按鈕,允許他們使用 GitHub 或 Google 登入。 如果使用者經過驗證,則會顯示一則包含其電子郵件地址和登出按鈕的訊息。 該元件提供了一個簡單的接口,可以透過操作會話物件來管理使用者登入和登出操作。

保護路線

為了保護路由並確保只有經過驗證的使用者才能存取某些頁面,請使用 NextAuth.js 中的 getSession 函數。

// pages/protected.js
import { getSession } from 'next-auth/react';

const ProtectedPage = ({ session }) => {
  if (!session) {
    return <p>You need to be authenticated to view this page.</p>;
  }
  return <p>Welcome, {session.user.email}!</p>;
};

export async function getServerSideProps(context) {
  const session = await getSession(context); // Fetch session data server-side
  return {
    props: { session },
  };
}

export default ProtectedPage;
// pages/protected.js
import { getSession } from 'next-auth/react';

const ProtectedPage = ({ session }) => {
  if (!session) {
    return <p>You need to be authenticated to view this page.</p>;
  }
  return <p>Welcome, {session.user.email}!</p>;
};

export async function getServerSideProps(context) {
  const session = await getSession(context); // Fetch session data server-side
  return {
    props: { session },
  };
}

export default ProtectedPage;
JAVASCRIPT

程式碼說明

Next.js 應用程式中的ProtectedPage元件使用 NextAuth.js 來限制只有經過驗證的使用者才能存取。 它使用getServerSideProps從伺服器端檢索使用者的會話屬性,並將其作為 prop 傳遞給元件。 如果使用者未通過身份驗證,頁面將顯示一則訊息,提示需要進行身份驗證。 如果使用者通過身份驗證,則會顯示其電子郵件地址以示歡迎。 這種設定確保只有登入使用者才能存取頁面內容。

介紹 IronPDF。

IronPDF是一個功能強大的 node.js PDF 程式庫,可讓開發人員在其 node.js 專案中產生和編輯 PDF。 無論您需要從 HTML 建立 PDF、修改現有 PDF,或是將網頁轉換為 PDF 格式,IronPDF 都能滿足您的需求。

! next-auth NPM(開發者使用方法):圖 1 - IronPDF for Node.js:Node.js PDF 庫

主要功能

HTML 至 PDF 轉換

輕鬆將HTML內容轉換為PDF文件。 此功能對於從網頁內容產生動態 PDF 特別有用。

URL 至 PDF 轉換

直接從 URL 產生 PDF,讓您可以捕獲網頁內容並以程式設計方式將其儲存為 PDF 檔案。

PDF 操作

輕鬆合併、分割和操作現有 PDF 文件。 IronPDF 提供諸如追加頁面、分割文件等功能。

PDF安全性

使用密碼加密或套用數位簽章來保護您的 PDF 文件。 IronPDF 提供多種選項,保護您的敏感文件免受未經授權的存取。

高品質輸出

產生高品質的 PDF 文檔,精確呈現文字、圖像和格式。 IronPDF 可確保您產生的 PDF 檔案與原始內容一致。

跨平台相容性

IronPDF 與包括 Windows、Linux 和 macOS 在內的各種平台相容,使其適用於各種開發環境。

簡單集成

使用 IronPDF 的 npm 包,即可輕鬆整合到您的 Node.js 應用程式中。 該 API 文件齊全,可以輕鬆地將 PDF 生成功能整合到您的專案中。

安裝

若要安裝IronPDF軟體包,請使用以下命令:

yarn add @ironsoftware/ironpdf @ironsoftware/ironpdf-engine-windows-x64
yarn add @ironsoftware/ironpdf @ironsoftware/ironpdf-engine-windows-x64
SHELL

使用 IronPDF 和 NextAuth.js 產生 PDF 文檔

安裝依賴項:首先,使用以下命令建立新的 Next.js 專案(如果還沒有):

npx create-next-app@latest nextauth-pdf --use-npm --example "https://github.com/vercel/next-learn/tree/main/basics/learn-starter"
npx create-next-app@latest nextauth-pdf --use-npm --example "https://github.com/vercel/next-learn/tree/main/basics/learn-starter"
SHELL

接下來,導航到您的專案目錄:

cd nextauth
cd nextauth
SHELL

安裝所需軟體包:

yarn add @ironsoftware/ironpdf @ironsoftware/ironpdf-engine-windows-x64
yarn add next-auth
yarn add @ironsoftware/ironpdf @ironsoftware/ironpdf-engine-windows-x64
yarn add next-auth
SHELL

建立 PDF 生成器

PDF 產生 API :第一步是建立後端 API 來產生 PDF 文件。 由於 IronPDF 只能在伺服器端運行,我們需要建立一個 API,以便在使用者想要產生 PDF 時呼叫。 在pages/api/pdf.js路徑下建立文件,並新增以下內容:

// pages/api/pdf.js
import { IronPdf } from "@ironsoftware/ironpdf";
import { format } from 'date-fns'; // Import the format function for date formatting

// Apply your IronPDF license key
IronPdf.GlobalSettings.LicenseKey = "Your license key goes here";

export default async function handler(req, res) {
  try {
    const currentDate = new Date();
    const formattedDate = format(currentDate, 'MMMM do, yyyy');
    // Defining the HTML content for the PDF
    let content = "<h1>Demo React Hook Form and Generate PDF Using IronPDF</h1>";
    content += `<p>Date: ${currentDate}</p>`;
    content += `<p>Formatted Date: ${formattedDate}</p>`;
    // Convert HTML content to PDF
    const pdf = await IronPdf.HtmlToPdfDocument({ htmlContent: content });
    const data = await pdf.toBuffer(); // Convert the PDF to a buffer for response
    res.setHeader("Content-Type", "application/pdf");
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=awesomeIron.pdf"
    );
    res.send(data); // Send the PDF file as a response
  } catch (error) {
    console.error("Error generating PDF:", error);
    res.status(500).end();
  }
}
// pages/api/pdf.js
import { IronPdf } from "@ironsoftware/ironpdf";
import { format } from 'date-fns'; // Import the format function for date formatting

// Apply your IronPDF license key
IronPdf.GlobalSettings.LicenseKey = "Your license key goes here";

export default async function handler(req, res) {
  try {
    const currentDate = new Date();
    const formattedDate = format(currentDate, 'MMMM do, yyyy');
    // Defining the HTML content for the PDF
    let content = "<h1>Demo React Hook Form and Generate PDF Using IronPDF</h1>";
    content += `<p>Date: ${currentDate}</p>`;
    content += `<p>Formatted Date: ${formattedDate}</p>`;
    // Convert HTML content to PDF
    const pdf = await IronPdf.HtmlToPdfDocument({ htmlContent: content });
    const data = await pdf.toBuffer(); // Convert the PDF to a buffer for response
    res.setHeader("Content-Type", "application/pdf");
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=awesomeIron.pdf"
    );
    res.send(data); // Send the PDF file as a response
  } catch (error) {
    console.error("Error generating PDF:", error);
    res.status(500).end();
  }
}
JAVASCRIPT

這將建立一個 Next.js API 路由,該路由使用 IronPDF 庫產生 PDF 檔案。 它會建立一個包含標題和目前日期的 HTML 字串,使用date-fns格式化日期,並將 HTML 轉換為 PDF。 生成的 PDF 文件將作為可下載文件在回應中返回。 這種方法允許在伺服器端環境中動態產生 PDF,因此可用於即時建立報告、發票或其他文件。

現在讓我們使用 Next-Auth 為前端網站新增 GIT 登入功能。 為此,我們需要取得使用者的 GitID 和金鑰。 登入您的 Git 帳戶並導航至如下所示的開發者設定:

! next-auth NPM(開發者使用方法):圖 2 - 在哪裡可以找到 Git 的開發者設置

點擊"新建 GitHub 應用程式"並新增您的網站詳細資訊:

! next-auth NPM(開發者使用指南):圖 3 - 在 GitHub 中添加網站詳細信息

請將套用 ID 和客戶端 ID 保存在安全的地方。 然後,在專案根目錄下建立一個.env.local檔案來儲存環境變數:

# Here you can use the App and Client ID you just got from GitHub
GITHUB_ID=your_github_client_id
GITHUB_SECRET=your_github_client_secret
NEXTAUTH_SECRET=secret

為你的 API 路由建立一個新檔案來處理身份驗證。 在pages/api/auth目錄下,建立一個名為[...nextauth].js文件,內容如下:

// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import GitHubProvider from 'next-auth/providers/github';

// Setting up NextAuth with GitHub provider
export default NextAuth({
  providers: [
    GitHubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
});
// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import GitHubProvider from 'next-auth/providers/github';

// Setting up NextAuth with GitHub provider
export default NextAuth({
  providers: [
    GitHubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
});
JAVASCRIPT

新增一個名為LoginButton.js的元件。 其中包含以下內容:

// components/LoginButton.js
import { useSession, signIn, signOut } from "next-auth/react"

export default function Component() {
  const { data: session } = useSession()
  if (session) { // Display sign-out button and user info when session is active
    return (
      <>
        Signed in as {session.user.email} <br />
        <button onClick={() => signOut()}>Sign out</button>
      </>
    )
  }
  return ( // Display sign-in button when not signed in
    <>
      Not signed in <br />
      <button onClick={() => signIn()}>Sign in</button>
    </>
  )
}
// components/LoginButton.js
import { useSession, signIn, signOut } from "next-auth/react"

export default function Component() {
  const { data: session } = useSession()
  if (session) { // Display sign-out button and user info when session is active
    return (
      <>
        Signed in as {session.user.email} <br />
        <button onClick={() => signOut()}>Sign out</button>
      </>
    )
  }
  return ( // Display sign-in button when not signed in
    <>
      Not signed in <br />
      <button onClick={() => signIn()}>Sign in</button>
    </>
  )
}
JAVASCRIPT

請如下修改index.js檔:

// pages/index.js
import Head from "next/head";
import styles from "../styles/Home.module.css";
import React, { useState, useEffect } from "react";
import { format } from "date-fns";
import LoginButton from "../components/LoginButton";
import { useSession } from "next-auth/react";

export default function Home() {
  const [text, setText] = useState("");
  const { data: session } = useSession();

  useEffect(() => {
    const currentDate = new Date();
    const formattedDate = format(currentDate, "MMMM do, yyyy");
    setText(formattedDate); // Set initial text state to formatted current date
  }, []);

  const generatePdf = async () => {
    try {
      const response = await fetch("/api/pdf-datefns?f=" + text);
      const blob = await response.blob();
      const url = window.URL.createObjectURL(new Blob([blob]));
      const link = document.createElement("a");
      link.href = url;
      link.setAttribute("download", "awesomeIron.pdf");
      document.body.appendChild(link);
      link.click();
      link.parentNode.removeChild(link); // Clean up after downloading
    } catch (error) {
      console.error("Error generating PDF:", error);
    }
  };

  const handleChange = (event) => {
    setText(event.target.value); // Update the text state with input value
  };

  return (
    <div className={styles.container}>
      <Head>
        <title>Generate PDF Using IronPDF</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        <h1>Demo Next Auth and Generate PDF Using IronPDF</h1>
        {!session && <LoginButton />}
        {session && (
          <>
            <p className="w-full text-center">
              <span className="px-4 text-xl border-gray-500">
                You are logged in enter URL to convert to PDF:
              </span>
              <input
                className="border border-gray-700 w-1/4"
                onChange={handleChange}
                placeholder="Enter URL here..."
              />
            </p>
            <button
              className="rounded-sm bg-blue-800 p-2 m-12 text-xl text-white"
              onClick={generatePdf}
            >
              Generate PDF
            </button>
          </>
        )}
      </main>
      <style jsx>{`
        main {
          padding: 5rem 0;
          flex: 1;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
        }
        footer {
          width: 100%;
          height: 100px;
          border-top: 1px solid #eaeaea;
          display: flex;
          justify-content: center;
          align-items: center;
        }
        footer img {
          margin-left: 0.5rem;
        }
        footer a {
          display: flex;
          justify-content: center;
          align-items: center;
          text-decoration: none;
          color: inherit;
        }
        code {
          background: #fafafa;
          border-radius: 5px;
          padding: 0.75rem;
          font-size: 1.1rem;
          font-family:
            Menlo,
            Monaco,
            Lucida Console,
            Liberation Mono,
            DejaVu Sans Mono,
            Bitstream Vera Sans Mono,
            Courier New,
            monospace;
        }
      `}</style>
      <style jsx global>{`
        html,
        body {
          padding: 0;
          margin: 0;
          font-family:
            -apple-system,
            BlinkMacSystemFont,
            Segoe UI,
            Roboto,
            Oxygen,
            Ubuntu,
            Cantarell,
            Fira Sans,
            Droid Sans,
            Helvetica Neue,
            sans-serif;
        }
        * {
          box-sizing: border-box;
        }
      `}</style>
    </div>
  );
}
// pages/index.js
import Head from "next/head";
import styles from "../styles/Home.module.css";
import React, { useState, useEffect } from "react";
import { format } from "date-fns";
import LoginButton from "../components/LoginButton";
import { useSession } from "next-auth/react";

export default function Home() {
  const [text, setText] = useState("");
  const { data: session } = useSession();

  useEffect(() => {
    const currentDate = new Date();
    const formattedDate = format(currentDate, "MMMM do, yyyy");
    setText(formattedDate); // Set initial text state to formatted current date
  }, []);

  const generatePdf = async () => {
    try {
      const response = await fetch("/api/pdf-datefns?f=" + text);
      const blob = await response.blob();
      const url = window.URL.createObjectURL(new Blob([blob]));
      const link = document.createElement("a");
      link.href = url;
      link.setAttribute("download", "awesomeIron.pdf");
      document.body.appendChild(link);
      link.click();
      link.parentNode.removeChild(link); // Clean up after downloading
    } catch (error) {
      console.error("Error generating PDF:", error);
    }
  };

  const handleChange = (event) => {
    setText(event.target.value); // Update the text state with input value
  };

  return (
    <div className={styles.container}>
      <Head>
        <title>Generate PDF Using IronPDF</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        <h1>Demo Next Auth and Generate PDF Using IronPDF</h1>
        {!session && <LoginButton />}
        {session && (
          <>
            <p className="w-full text-center">
              <span className="px-4 text-xl border-gray-500">
                You are logged in enter URL to convert to PDF:
              </span>
              <input
                className="border border-gray-700 w-1/4"
                onChange={handleChange}
                placeholder="Enter URL here..."
              />
            </p>
            <button
              className="rounded-sm bg-blue-800 p-2 m-12 text-xl text-white"
              onClick={generatePdf}
            >
              Generate PDF
            </button>
          </>
        )}
      </main>
      <style jsx>{`
        main {
          padding: 5rem 0;
          flex: 1;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
        }
        footer {
          width: 100%;
          height: 100px;
          border-top: 1px solid #eaeaea;
          display: flex;
          justify-content: center;
          align-items: center;
        }
        footer img {
          margin-left: 0.5rem;
        }
        footer a {
          display: flex;
          justify-content: center;
          align-items: center;
          text-decoration: none;
          color: inherit;
        }
        code {
          background: #fafafa;
          border-radius: 5px;
          padding: 0.75rem;
          font-size: 1.1rem;
          font-family:
            Menlo,
            Monaco,
            Lucida Console,
            Liberation Mono,
            DejaVu Sans Mono,
            Bitstream Vera Sans Mono,
            Courier New,
            monospace;
        }
      `}</style>
      <style jsx global>{`
        html,
        body {
          padding: 0;
          margin: 0;
          font-family:
            -apple-system,
            BlinkMacSystemFont,
            Segoe UI,
            Roboto,
            Oxygen,
            Ubuntu,
            Cantarell,
            Fira Sans,
            Droid Sans,
            Helvetica Neue,
            sans-serif;
        }
        * {
          box-sizing: border-box;
        }
      `}</style>
    </div>
  );
}
JAVASCRIPT

程式碼範例的輸出

首頁

! next-auth NPM(開發者使用指南):圖 4 - 輸出的網站

登入頁面

! next-auth NPM(開發者使用方法):圖 5 - 使用 GitHub 登入按鈕

登入後

! next-auth NPM(開發者使用方法):圖 6 - 主 PDF 產生網頁

輸出生成的PDF

! next-auth NPM(開發者使用方法):圖 7 - 輸出的 PDF

IronPDF 授權。

IronPDF.

請務必將收到的許可證密鑰放在代碼開頭,如下所示:

// Adjust paths as necessary depending on how you import IronPDF
import { IronPdfGlobalConfig, PdfDocument } from "@ironsoftware/ironpdf";

// Apply your IronPDF license key
IronPdfGlobalConfig.getConfig().licenseKey = "Add Your key here";
// Adjust paths as necessary depending on how you import IronPDF
import { IronPdfGlobalConfig, PdfDocument } from "@ironsoftware/ironpdf";

// Apply your IronPDF license key
IronPdfGlobalConfig.getConfig().licenseKey = "Add Your key here";
JAVASCRIPT

結論

最終,NextAuth.js 簡化了向 Next.js 應用程式添加身份驗證的過程。 它支援多種身份驗證供應商,並具有強大的安全功能,是處理用戶身份驗證的絕佳選擇。 您可以隨時查閱 NextAuth.js 文檔,以了解更多高級配置和功能。 除此之外,IronPDF Node.js 還為您的應用程式提供強大的 PDF 生成和操作功能,並與現代應用程式開發很好地整合。

Darrius Serrant
全棧軟件工程師 (WebOps)

Darrius Serrant 擁有邁阿密大學計算機科學學士學位,目前任職於 Iron Software 的全栈 WebOps 市場營銷工程師。從小就迷上編碼,他認為計算既神秘又可接近,是創意和解決問題的完美媒介。

在 Iron Software,Darrius 喜歡創造新事物,並簡化複雜概念以便於理解。作為我們的駐場開發者之一,他也自願教學生,分享他的專業知識給下一代。

對 Darrius 來說,工作令人滿意因為它被重視且有實際影響。