Trong hướng dẫn này, bạn sẽ tìm hiểu cách triển khai xác thực người dùng trong ứng dụng Next.js bằng Auth.js và Upstash Redis. Bạn sẽ tìm hiểu cách thiết lập môi trường cần thiết, tạo nhà cung cấp xác thực tùy chỉnh để đăng nhập và đăng ký người dùng an toàn, đồng thời tích hợp Upstash Redis làm cơ sở dữ liệu để quản lý phiên.
Điều kiện tiên quyết
Bạn sẽ cần những thứ sau:
- Node.js 18 trở lên
- Tài khoản Upstash
Ngăn xếp công nghệ
Thiết lập phiên bản Upstash Redis
Trong trang tổng quan Upstash của bạn, hãy truy cập Redis tab và tạo cơ sở dữ liệu.

Cuộn xuống cho đến khi bạn tìm thấy phần REST API và chọn .env nút. Sao chép nội dung và lưu ở nơi an toàn.

Tạo ứng dụng Next.js mới
Hãy bắt đầu bằng cách tạo một dự án Next.js mới. Mở terminal của bạn và chạy lệnh sau:
npx create-next-app@latest my-app Khi được nhắc, hãy chọn:
Yeskhi được nhắc sử dụng TypeScript.Nokhi được nhắc sử dụng ESLint.Yeskhi được nhắc sử dụng CSS Tailwind.Nokhi được nhắc sử dụngsrc/thư mục.Yeskhi được nhắc sử dụng Bộ định tuyến ứng dụng.Nokhi được nhắc sử dụng Turbopack.Nokhi được nhắc tùy chỉnh bí danh nhập mặc định (@/*).
Sau khi hoàn tất, hãy chuyển vào thư mục dự án và khởi động ứng dụng ở chế độ phát triển bằng cách thực hiện lệnh sau:
cd my-app
npm run dev Ứng dụng phải chạy trên localhost:3000. Dừng máy chủ phát triển để cài đặt các phụ thuộc cần thiết bằng các lệnh sau:
npm install @upstash/redis nanoid
npm install next-auth @auth/core @auth/upstash-redis-adapter Các thư viện được cài đặt bao gồm:
nanoid:Thư viện để tạo ID duy nhất, an toàn.next-auth:Giải pháp xác thực được xây dựng cho Next.js.@auth/core:Gói cốt lõi để xử lý xác thực trong Auth.js.@upstash/redis:SDK để tương tác với Upstash Redis thông qua các yêu cầu HTTP.@auth/upstash-redis-adapter:Bộ điều hợp để tích hợp Auth.js với Upstash Redis.
Bây giờ, hãy tạo .env tập tin ở thư mục gốc của dự án của bạn. Bạn sẽ sử dụng AUTH_SECRET , UPSTASH_REDIS_REST_URL và UPSTASH_REDIS_REST_TOKEN giá trị.
.env tập tin phải có nội dung sau:
# .env
# Auth.js Environment Variable
AUTH_SECRET="..."
# Upstash Redis Environment Variables
UPSTASH_REDIS_REST_URL="https://...upstash.io"
UPSTASH_REDIS_REST_TOKEN="..." Khởi tạo ứng dụng khách Upstash Redis
Tạo một tệp có tên redis.ts trong lib thư mục có mã sau:
// File: lib/redis.ts
import { Redis } from '@upstash/redis'
export default new Redis({
url: process.env.UPSTASH_REDIS_REST_URL,
token: process.env.UPSTASH_REDIS_REST_TOKEN,
}) Trong đoạn mã trên, một phiên bản máy khách Redis tương thích với Edge được xuất để sử dụng trong toàn bộ ứng dụng.
Thiết lập Loại người dùng và Người trợ giúp thông tin xác thực
Tạo một tệp có tên types.ts trong lib thư mục có mã sau:
// File: lib/types.ts
export interface UserType {
id?: string
email: string
name?: string
image?: string
password?: string
emailVerified?: string
}
UserType giao diện xác định cấu trúc của đối tượng người dùng trong ứng dụng. Nó bao gồm:
id(tùy chọn):Mã định danh duy nhất cho người dùng.email(bắt buộc):Địa chỉ email của người dùng.name(tùy chọn):Tên người dùng.image(tùy chọn):URL hoặc đường dẫn tới ảnh hồ sơ của người dùng.password(tùy chọn):Mật khẩu băm của người dùng.emailVerified(tùy chọn):Dấu thời gian hoặc chuỗi cho biết liệu/thời điểm email của người dùng đã được xác minh hay chưa.
Giao diện này đóng vai trò định nghĩa loại cho dữ liệu người dùng trong toàn bộ ứng dụng.
Hơn nữa, tạo một tệp có tên credentials.ts trong lib thư mục có mã sau:
// File: lib/credentials.ts
export function generateRandomToken() {
const array = new Uint8Array(20)
crypto.getRandomValues(array)
return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('')
}
export function generateRandomString(inputValue: string) {
const encoder = new TextEncoder()
const data = encoder.encode(inputValue)
return crypto.subtle.digest('SHA-256', data).then((hashBuffer) => {
return Array.from(new Uint8Array(hashBuffer))
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('')
})
}
export async function hashPassword(password: string) {
const encoder = new TextEncoder()
const data = encoder.encode(password)
const hashBuffer = await crypto.subtle.digest('SHA-256', data)
return Array.from(new Uint8Array(hashBuffer))
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('')
}
export async function comparePassword(password: string, hash: string) {
const hashedPassword = await hashPassword(password)
return hashedPassword === hash
} Trong đoạn mã trên, các hàm tiện ích tương thích với Edge để tạo và quản lý mã thông báo bảo mật cũng như mật khẩu băm được xác định:
generateRandomToken:Tạo mã thông báo ngẫu nhiên được bảo mật bằng mật mã bằng cách tạo mảng ngẫu nhiên 20 byte và chuyển đổi nó thành chuỗi thập lục phân.generateRandomString:Chấp nhận một chuỗi đầu vào, mã hóa nó thành byte, băm nó bằng SHA-256 và trả về hàm băm dưới dạng chuỗi thập lục phân. Hữu ích khi tạo các chuỗi nhất quán, duy nhất bắt nguồn từ các giá trị đầu vào.hashPassword:Băm mật khẩu văn bản gốc bằng SHA-256 và chuyển đổi hàm băm kết quả thành chuỗi thập lục phân. Điều này được sử dụng để lưu trữ mật khẩu một cách an toàn.comparePassword:So sánh mật khẩu văn bản gốc với mật khẩu băm bằng cách băm dữ liệu đầu vào và kiểm tra xem nó có khớp với hàm băm được lưu trữ hay không.
Sử dụng bộ điều hợp Upstash Redis với Auth.js
Tạo một tệp có tên auth.ts trong lib thư mục có mã sau:
// File: lib/auth.ts
import { UpstashRedisAdapter } from '@auth/upstash-redis-adapter'
import NextAuth from 'next-auth'
import providers from './providers'
import redis from './redis'
export const { handlers, signIn, signOut, auth } = NextAuth(() => ({
providers,
session: { strategy: 'jwt' },
adapter: UpstashRedisAdapter(redis),
}))
Trong đoạn mã trên, xác thực đang được thiết lập thông qua việc tạo handlers , signIn , signOut , và auth hoạt động bằng cách sử dụng cấu hình tùy chỉnh. Nó sử dụng chiến lược phiên dựa trên JWT, UpstashRedisAdapter để kết nối với cơ sở dữ liệu Upstash Redis để lưu trữ dữ liệu người dùng và một loạt các nhà cung cấp xác thực được xác định trong providers mô-đun. Thiết lập này cho phép tích hợp liền mạch quá trình xác thực và quản lý phiên với Upstash Redis làm chương trình phụ trợ.
Thiết lập nhà cung cấp Xác thực tùy chỉnh với Auth.js
Tạo một tệp có tên providers.ts trong lib thư mục có mã sau:
// File: lib/providers.ts
import { nanoid } from 'nanoid'
import Credentials from 'next-auth/providers/credentials'
import { comparePassword, generateRandomString, hashPassword } from './credentials'
import redis from './redis'
import { UserType } from './types'
export default [
Credentials({
credentials: {
email: {},
password: {},
},
authorize: async (credentials, request) => {
let type
try {
const tmp = new URL(request.url).searchParams.get('kind')
if (tmp && typeof tmp === 'string') type = tmp
} catch (e) {}
if (!type || !credentials.email || typeof credentials.email !== 'string' || !credentials.password || typeof credentials.password !== 'string') return null
const randomizedPassword = await generateRandomString(credentials.password)
const userByEmail = await redis.get<string | null | undefined>(`user:email:${credentials.email}`)
if (userByEmail) {
if (type !== 'in') {
console.log(`can not sign in in a non sign-in mode.`)
throw new Error(`can not sign in in a non sign-in mode.`)
}
const user = await redis.get<UserType>(`user:${userByEmail}`)
if (!user) {
console.log(`Found the user by email from user:email:${userByEmail}, but the user object is missing at user:${userByEmail}`)
return null
}
if (user.password) {
const hashedPassword = await hashPassword(randomizedPassword)
const isPasswordCorrect = await comparePassword(user.password, hashedPassword)
if (isPasswordCorrect) {
const { password, ...rest } = user
return rest
}
throw new Error(`incorrect password for credentials.`)
}
throw new Error(`you are using some other authentication method already, but not credentials.`)
} else {
if (type !== 'up') {
console.log(`can not sign up in a non sign-up mode.`)
throw new Error(`can not sign up in a non sign-up mode.`)
}
const newUser = {
name: null,
image: null,
emailVerified: null,
email: credentials.email,
password: randomizedPassword,
}
const tmp = nanoid()
await redis.set(`user:email:${credentials.email}`, tmp)
await redis.set(`user:${tmp}`, newUser)
return newUser
}
},
}),
] Trong đoạn mã trên, một loạt nhà cung cấp xác thực dựa trên thông tin xác thực tùy chỉnh được xuất. Nhà cung cấp Thông tin xác thực xử lý cả logic đăng nhập và đăng ký:nó kiểm tra xem người dùng có tồn tại trong Redis hay không và xác thực mật khẩu của họ hoặc tạo người dùng mới. Nếu đăng nhập, nó sẽ so sánh mật khẩu được cung cấp (được băm bằng chuỗi ngẫu nhiên) với mật khẩu được lưu trữ; nếu đăng ký, nó sẽ tạo một mục nhập người dùng mới trong Upstash Redis. Mã sử dụng Upstash Redis để lưu trữ dữ liệu người dùng và đảm bảo rằng quá trình này được thực hiện ở chế độ đăng ký hoặc đăng nhập dựa trên tham số loại trong URL.
Thiết lập các tuyến API xác thực (được hỗ trợ bởi Auth.js)
Tạo một tệp có tên route.ts trong app/api/auth/[...nextauth] thư mục có mã sau:
// File: app/api/auth/[...nextauth]/route.ts
export const runtime = 'edge'
import { handlers } from '@/lib/auth'
export const { GET, POST } = handlers
Trong đoạn mã trên, hai trình xử lý điểm cuối GET và POST được xuất và được xử lý bởi handlers hàm được xuất từ @/lib/auth.ts tập tin.
Tạo một tệp có tên route.ts trong app/api/refresh thư mục có mã sau:
// File: app/api/refresh/route.ts
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export const fetchCache = 'force-no-store'
import { auth } from '@/lib/auth'
import redis from '@/lib/redis'
import { UserType } from '@/lib/types'
import { encode } from '@auth/core/jwt'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
export async function GET(request: Request) {
const useSecureCookie = request.url.startsWith('https:')
const salt = useSecureCookie ? '__Secure-authjs.session-token' : 'authjs.session-token'
if (!process.env.AUTH_SECRET) return new NextResponse(null, { status: 500 })
const [session, cookieStore] = await Promise.all([auth(), cookies()])
if (!session?.user?.email) return new NextResponse(null, { status: 400 })
const userByEmail = await redis.get(`user:email:${session.user.email}`)
const userData = await redis.get<UserType>(`user:${userByEmail}`)
if (!userData?.email) cookieStore.set(salt, toString(), { secure: useSecureCookie, path: '/', httpOnly: true, sameSite: 'lax', maxAge: 0 })
else {
const { image, password, ...rest } = userData
const saltVal = await encode({ salt, secret: process.env.AUTH_SECRET, token: { ...rest, picture: image } })
cookieStore.set(salt, saltVal, { secure: useSecureCookie, path: '/', httpOnly: true, sameSite: 'lax' })
}
return new NextResponse()
} Trong đoạn mã trên, một lộ trình API tương thích với Edge để làm mới phiên của người dùng đang được tạo. Nó tìm nạp phiên người dùng và dữ liệu liên quan từ Redis, xác minh email của người dùng và cập nhật cookie phiên. Nếu dữ liệu người dùng không hợp lệ hoặc bị thiếu, cookie phiên sẽ bị xóa; nếu không, mã thông báo đã ký mới sẽ được tạo và lưu trữ trong cookie.
Tạo một tệp có tên route.ts trong app/api/user thư mục có mã sau:
// File: app/api/user/route.ts
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export const fetchCache = 'force-no-store'
import { auth } from '@/lib/auth'
import redis from '@/lib/redis'
import { UserType } from '@/lib/types'
import { NextResponse } from 'next/server'
export async function POST(request: Request) {
try {
const session = await auth()
if (!session?.user?.email) return new NextResponse(null, { status: 400 })
const body = await request.json()
const userByEmail = await redis.get(`user:email:${session.user.email}`)
const userData = await redis.get<UserType>(`user:${userByEmail}`)
if (!userData) return new NextResponse(null, { status: 404 })
if (body.name) userData.name = body.name
if (body.image) userData.image = body.image
await redis.set(`user:${userByEmail}`, userData)
return new NextResponse()
} catch (e: any) {
const message = e.message || e.toString()
console.log(message)
return new NextResponse(message, { status: 500 })
}
} Trong đoạn mã trên, một lộ trình API tương thích với Edge để cập nhật dữ liệu người dùng đang được tạo. Nó xác thực người dùng, tìm nạp dữ liệu của họ từ Redis bằng email của họ và cập nhật thông tin của họ (ví dụ:tên hoặc hình ảnh) dựa trên nội dung yêu cầu. Nếu không tìm thấy người dùng hoặc xảy ra lỗi, mã trạng thái và phản hồi thích hợp sẽ được trả về.
Thiết lập Middleware Next.js bằng Auth.js
Tạo một tệp có tên middleware.ts trong thư mục gốc của dự án của bạn với đoạn mã sau:
// File: middleware.ts
export { auth as middleware } from '@/lib/auth'
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}
Trong đoạn mã trên, phần mềm trung gian được tạo bằng cách xuất lại auth chức năng từ @/lib/auth mô-đun. Phần mềm trung gian áp dụng xác thực cho tất cả các tuyến ngoại trừ các tuyến API, tệp tĩnh, nội dung hình ảnh và favicon, như được chỉ định bởi matcher cấu hình. Điều này đảm bảo các tuyến không bị loại trừ được bảo vệ bởi bộ logic xác thực bằng Auth.js.
Sử dụng Auth.js trong Thành phần bộ định tuyến ứng dụng Next.js
Tạo một tệp có tên NextAuthProvider.tsx trong app thư mục có mã sau:
// File: app/NextAuthProvider.tsx
'use client'
import { SessionProvider } from 'next-auth/react'
type Props = {
children?: React.ReactNode
}
export default function ({ children }: Props) {
return <SessionProvider>{children}</SessionProvider>
}
Trong đoạn mã trên, một thành phần React phía máy khách được tạo để bao bọc ứng dụng bằng SessionProvider của NextAuth . Thành phần chấp nhận children làm đạo cụ và đảm bảo rằng các thành phần được bao bọc có quyền truy cập vào ngữ cảnh phiên người dùng do NextAuth cung cấp. Thiết lập này rất cần thiết để quản lý trạng thái xác thực trên ứng dụng trong Next.js.
Tạo một tệp có tên csrf.tsx trong app thư mục có mã sau:
// File: app/csrf.tsx
'use client'
import { getCsrfToken } from 'next-auth/react'
import { useEffect, useState } from 'react'
export function CSRFInput() {
const [csrfToken, setCsrfToken] = useState<string>()
useEffect(() => {
getCsrfToken().then((res) => setCsrfToken(res))
}, [])
return <input type="hidden" name="csrfToken" defaultValue={csrfToken} />
}
Trong đoạn mã trên, một thành phần React phía máy khách được xuất để tìm nạp mã thông báo CSRF bằng getCsrfToken của NextAuth chức năng và lưu trữ nó trong một biến trạng thái. Thành phần này hiển thị trường nhập ẩn chứa mã thông báo CSRF, cho phép gửi biểu mẫu an toàn bằng cách bao gồm mã thông báo dưới dạng giá trị ẩn. Điều này hữu ích để bảo vệ chống lại các cuộc tấn công giả mạo yêu cầu trên nhiều trang web.
Tạo một tệp có tên provider.tsx trong app thư mục có mã sau:
// File: app/provider.tsx
'use client'
import { Button } from '@/components/ui/button'
import { Icon } from '@iconify/react'
import { signIn } from 'next-auth/react'
export default function ({ provider, prefix }: { prefix: string; provider: { name: string; id: string } }) {
return (
<Button onClick={() => signIn(provider.id)} key={provider.name} variant="outline" className="flex w-full gap-x-3">
{provider.id === 'google' && <Icon fontSize={18} icon="flat-color-icons:google" />}
<span className="text-black">
{prefix} with {provider.name}
</span>
</Button>
)
}
Trong đoạn mã trên, một thành phần React để hiển thị nút đăng nhập có thể tùy chỉnh cho các nhà cung cấp xác thực khác nhau sẽ được xuất. Nó chấp nhận provider (chứa name và id ) và prefix như đạo cụ. Nút kích hoạt signIn dành cho nhà cung cấp được chỉ định và hiển thị động biểu tượng và nhãn dựa trên id của nhà cung cấp .
Cập nhật file có tên layout.tsx trong app thư mục có mã sau:
// File: app/layout.tsx
import './globals.css'
import NextAuthProvider from './NextAuthProvider'
export default function ({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className="bg-white text-black antialiased">
<NextAuthProvider>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col">{children}</div>
</NextAuthProvider>
</body>
</html>
)
}
Trong đoạn mã trên, bố cục Next.js bao bọc toàn bộ trang theo kiểu chung và bối cảnh xác thực. Nó nhập globals.css để tạo kiểu toàn cục và NextAuthProvider để quản lý trạng thái xác thực. children prop đại diện cho nội dung trang lồng nhau, được bao bọc trong một thùng chứa được tạo kiểu với phần đệm đáp ứng và chiều rộng tối đa, mang lại bố cục nhất quán cho tất cả các trang.
Tải trạng thái xác thực người dùng trong trang phía máy khách
Cập nhật file có tên page.tsx trong app thư mục có mã sau:
// File: app/page.tsx
'use client'
import { signOut, useSession } from 'next-auth/react'
export default function () {
const { data, status } = useSession()
return (
<>
{JSON.stringify({ data, status })}
<button onClick={() => signOut()}>Sign Out</button>
</>
)
}
Trong đoạn mã trên, thành phần React phía máy khách hiển thị dữ liệu phiên của người dùng và cung cấp nút "Đăng xuất" sẽ được xuất. Nó sử dụng useSession của NextAuth hook để truy xuất dữ liệu và trạng thái phiên, hiển thị chúng dưới dạng chuỗi JSON. signOut chức năng được gọi khi nút được nhấp vào, cho phép người dùng đăng xuất.
Xây dựng trang Đăng nhập động (sử dụng Auth.js)
Tạo một tệp có tên page.tsx trong app/signin thư mục có mã sau:
// File: app/signin/page.tsx
export const runtime = 'edge'
import { CSRFInput } from '@/app/csrf'
import Provider from '@/app/provider'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { auth } from '@/lib/auth'
import providers from '@/lib/providers'
import { unstable_noStore } from 'next/cache'
import Link from 'next/link'
import { redirect } from 'next/navigation'
export default async function () {
unstable_noStore()
const session = await auth()
if (session) redirect('/')
return (
<div className="border md:border-white/10 flex items-center justify-center py-12">
<div className="mx-auto grid w-[350px] gap-6">
<div className="grid gap-2 text-center">
<h1 className="text-3xl font-bold">Sign In</h1>
<p className="text-balance text-muted-foreground">Enter your email below to sign in to your account</p>
</div>
{providers
.filter((provider) => (typeof provider === 'function' ? provider({}).id : provider.id) !== 'credentials')
.map((provider) => (
<Provider
prefix="Sign in"
key={typeof provider === 'function' ? provider({}).name : provider.name}
provider={typeof provider === 'function' ? provider({}) : provider}
/>
))}
<p className="text-gray-300 text-xs text-center">OR</p>
<form method="POST" className="grid gap-4" action="/api/auth/callback/credentials?kind=in">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input name="email" id="email" type="email" placeholder="m@example.com" required />
</div>
<div className="grid gap-2">
<Label htmlFor="password">Password</Label>
<Input name="password" id="password" type="password" required />
<CSRFInput />
</div>
<Button type="submit" className="w-full">
Sign In
</Button>
</form>
<div className="mt-4 text-center text-sm">
Don't have an account?{' '}
<Link href="/signup" className="underline">
Sign up
</Link>
</div>
</div>
</div>
)
} Trong đoạn mã trên, một trang đăng nhập đang được tạo. Nó kiểm tra xem phiên người dùng đã tồn tại chưa; nếu vậy, nó sẽ chuyển hướng đến trang chủ. Trang hiển thị biểu mẫu đăng nhập nơi người dùng có thể nhập email và mật khẩu của họ, cùng với các tùy chọn để đăng nhập bằng nhiều nhà cung cấp khác nhau. Nó cũng bao gồm mã thông báo CSRF để bảo mật và liên kết đến trang đăng ký cho người dùng mới.
Xây dựng trang Đăng ký động (sử dụng Auth.js)
Tạo một tệp có tên page.tsx trong app/signup thư mục có mã sau:
// File: app/signup/page.tsx
export const runtime = 'edge'
import { CSRFInput } from '@/app/csrf'
import Provider from '@/app/provider'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { auth } from '@/lib/auth'
import providers from '@/lib/providers'
import { unstable_noStore } from 'next/cache'
import Link from 'next/link'
import { redirect } from 'next/navigation'
export default async function () {
unstable_noStore()
const session = await auth()
if (session) redirect('/')
return (
<div className="border md:border-white/10 flex items-center justify-center py-12">
<div className="mx-auto grid w-[350px] gap-6">
<div className="grid gap-2 text-center">
<h1 className="text-3xl font-bold">Sign Up</h1>
<p className="text-balance text-muted-foreground">Enter your email below to sign up with an account</p>
</div>
{providers
.filter((provider) => (typeof provider === 'function' ? provider({}).id : provider.id) !== 'credentials')
.map((provider) => (
<Provider
prefix="Sign up"
key={typeof provider === 'function' ? provider({}).name : provider.name}
provider={typeof provider === 'function' ? provider({}) : provider}
/>
))}
<p className="text-gray-300 text-xs text-center">OR</p>
<form method="POST" className="grid gap-4" action="/api/auth/callback/credentials?kind=up">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input name="email" id="email" type="email" placeholder="m@example.com" required />
</div>
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
</div>
<Input name="password" id="password" type="password" required />
<CSRFInput />
</div>
<Button type="submit" className="w-full">
Sign Up
</Button>
</form>
<div className="mt-4 text-center text-sm">
Don't have an account?{' '}
<Link href="/signin" className="underline">
Sign In
</Link>
</div>
</div>
</div>
)
} Trong đoạn mã trên, một trang đăng ký đang được tạo. Nó kiểm tra xem phiên người dùng đã tồn tại chưa; nếu vậy, nó sẽ chuyển hướng đến trang chủ. Trang hiển thị biểu mẫu đăng ký nơi người dùng có thể nhập email và mật khẩu của họ, cùng với các tùy chọn để đăng nhập bằng nhiều nhà cung cấp khác nhau. Nó cũng bao gồm mã thông báo CSRF để bảo mật và liên kết đến trang đăng nhập cho người dùng hiện tại.
Đó là rất nhiều học hỏi! Bây giờ bạn đã hoàn tất ✨
Tài liệu tham khảo
Để biết thêm thông tin chi tiết, hãy khám phá các tài liệu tham khảo được trích dẫn trong blog này.
- Kho lưu trữ GitHub
- Auth.js - Xác thực thông tin xác thực
- Auth.js - Bộ điều hợp Upstash Redis
- Next.js - Cookie
Kết luận
Trong hướng dẫn này, bạn đã tìm hiểu cách triển khai xác thực người dùng trong ứng dụng Next.js bằng Auth.js và Upstash Redis. Bạn đã học cách thiết lập các biến môi trường, tạo ứng dụng khách Redis và triển khai nhà cung cấp xác thực tùy chỉnh. Ngoài ra, bạn đã tìm hiểu cách thiết lập các tuyến API trong Next.js để xử lý quá trình đăng nhập và đăng ký của người dùng cũng như quản lý phiên. Bằng cách làm theo các bước này, bạn có thể quản lý hiệu quả việc xác thực người dùng và lưu trữ dữ liệu trong các ứng dụng Next.js của mình bằng Upstash Redis.