跳至页脚内容
NODE 帮助

next-auth NPM(开发者如何使用)

身份验证对于现代网络应用程序至关重要,它确保用户可以安全地访问他们的数据和功能,并提供基础设施支持。 NextAuth.js 是一个功能强大且灵活的身份验证库,旨在与 Next.js 无缝协作。 本文将探讨如何在 Next.js 项目中设置和使用 NextAuth.js,轻松保护用户数据。 我们还将向您展示如何将此 npm 与其他库(如 IronPDF 库)结合使用,为您的项目提供直观的无状态身份验证。

什么是 NextAuth.js?

NextAuth.js 是一个开源身份验证库,用于 Next.js 应用程序,提供了一种灵活安全的方式在 Web 应用中实现身份验证。使用 NextAuth.js,开发人员可以轻松地将身份验证集成到他们的 Next.js 项目中,而无需管理用户身份验证和会话管理的复杂性。

该软件包高度可配置,允许开发人员定制身份验证流程、保护 API 路由以及无缝处理用户会话。 具有增强的功能,可以创建用于管理账户访问的程序、加密和解码 JSON Web 令牌、建立自定义 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

代码解释

ProtectedPage 组件在 Next.js 应用程序中使用 NextAuth.js 限制对仅限身份验证用户的访问。 它在服务器端使用 getServerSideProps 检索用户的会话属性,并将其作为道具传递给组件。 如果用户未通过身份验证,页面将显示一条消息指示需要身份验证。 如果用户已通过身份验证,它将通过显示其电子邮件地址来欢迎他们。 这种设置确保只有登录用户才能访问页面的内容。

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集成到您的Node.js应用程序中,使用其npm包。 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

这将创建一个利用 IronPDF 库生成 PDF 文件的 Next.js API 路由。 它创建一个包含标题和当前日期的 HTML 字符串,使用 date-fns 格式化日期,并将 HTML 转换为 PDF。 生成的 PDF 随后被作为可下载文件返回。 这种方法允许在服务器端环境中动态生成 PDF,对于实时创建报告、发票或其他文档非常有用。

现在让我们使用 Next-Auth 为我们的前端网站添加一个 GIT 登录。 为此,我们需要获取用户的 GitID 和秘密。 登录到您的 Git 账户,并导航到如下的开发者设置:

next-auth NPM (开发者如何工作):图 2 - 查找 Git 开发者设置的地方

点击 New GitHub App 并添加您的网站详细信息:

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

请确保记得在代码开始处放置您收到的 License Key,如下所示:

// 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 来说,他的工作令人满意,因为它被重视并产生真正的影响。