강의

멘토링

로드맵

Programming

/

Front-end

Tiếp theo + Tạo dịch vụ SNS bằng React Query

Chúng ta sẽ tạo ra một dịch vụ mạng xã hội tương tự như Twitter (X.com) bằng cách sử dụng React19 & Next15 & ReactQuery5 & Next Auth5 & MSW2 & socket.io4 & zustand stack. Cuối cùng là SSR để tối ưu hóa công cụ tìm kiếm!

(4.4) 128 đánh giá

3,399 học viên

Độ khó Trung cấp trở lên

Thời gian Không giới hạn

  • zerocho
Next.js
Next.js
React
React
react-query
react-query
next-auth
next-auth
msw
msw
Next.js
Next.js
React
React
react-query
react-query
next-auth
next-auth
msw
msw
zerocho님의 프로필 이미지

Đã chỉnh sửa

Nhận lỗi máy chủ next-auth & Đưa dữ liệu tùy chỉnh vào session & Truy cập trang theo quyền

Xin chào. Đó là 0 giây.

Tôi nghĩ nhiều người đã trải qua nỗi đau với next-auth ít nhất một lần. Vì nó vẫn đang trong giai đoạn thử nghiệm nên có nhiều thứ hơi không ổn định , nhưng có vẻ như mọi thứ cuối cùng đã nằm trong tầm kiểm soát. Vì vậy, tôi sẽ giới thiệu ba điều đã được thêm vào trong bài giảng mà chưa được đề cập đến vì chúng không có chức năng.

Nhận được lỗi server tại quầy lễ tân khi đăng nhập

Khi đăng nhập, máy chủ có thể đưa ra nhiều lỗi khác nhau. Ví dụ: 1. Nếu không có người dùng 2. Nếu mật khẩu không chính xác 3. v.v. Nhưng chẳng phải điều này nên được chuyển đến quầy lễ tân để hiển thị một thông báo phù hợp với tình huống sao ? Tuy nhiên, tính năng cơ bản này cho đến nay vẫn còn thiếu và hiện đã được thêm vào.

Sửa đổi auth.ts như sau:

 import NextAuth, {CredentialsSignin} from "next-auth" ... providers: [ CredentialsProvider({ async authorize(credentials) { const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, { ... }) // 여기 주목!!! 서버에서 에러가 발생할 때 그 에러 내용이 서버에 담겨 있을 겁니다. console.log(authResponse.status, authResponse.statusText) if (!authResponse.ok) { const credentialsSignin = new CredentialsSignin(); if (authResponse.status === 404) { credentialsSignin.code = 'no_user'; } else if (authResponse.status === 401) { credentialsSignin.code = 'wrong_password'; } throw credentialsSignin; } const user = await authResponse.json() console.log('user', user); // id, name, image, email만 허용 return { id: user.id, name: user.nickname, image: user.image, } }, }), ]

Bây giờ, thay vì trả về giá trị rỗng, chỉ cần đưa ra lỗi CredentialsSignin . Chỉ cần viết thông báo lỗi vào mã, đây là một thuộc tính của lỗi.

 const response = await signIn("credentials", { username: id, password, redirect: false })

Bây giờ, khi đăng nhập thất bại, phản hồi sẽ chứa mã lỗi và thông báo. Tuy nhiên, reply.ok vẫn cho kết quả đúng (nếu chuyển hướng sai thì nó đúng vô điều kiện)

Chèn dữ liệu tùy chỉnh vào đối tượng phiên

Theo tài liệu chính thức, hiện tại chỉ có thể nhập id, email, tên và hình ảnh khi trả về chức năng ủy quyền. Chỉ riêng điều này đã có một hạn chế lớn. Họ nói rằng bạn có thể nhập ID, nhưng nếu bạn làm vậy, nó sẽ biến mất khỏi dữ liệu của useSession().

  1. Thế thì id đã đi đâu?

  2. Làm cách nào để thêm dữ liệu tùy chỉnh khác?

    Bạn có thể làm điều này, nhưng bạn có thể tạo phiên trực tiếp như sau.

xác thực.ts

 export const { handlers: { GET, POST }, auth, signIn, } = NextAuth({ pages: { signIn: '/i/flow/login', newUser: '/i/flow/signup', }, callbacks: { async session({ session, token }) { console.log('session callback', session, token); const authResponse = await fetch(내정보를 가져오는 서버 API); const userData = await authResponse.json(); (session as any).userData = userData; return session; } }, providers: [ CredentialsProvider({ async authorize(credentials) { ... // id, name, image, email만 허용 return { id: user.id, name: user.nickname, image: user.image, }

Bạn có thể viết phương thức phiên không đồng bộ trong thuộc tính gọi lại như thế này. Từ đây, bạn có thể tải thông tin của mình từ máy chủ một lần nữa. Sau đó, giá trị phản hồi được đưa vào đối tượng phiên và được trả về.

  1. Id đã biến mất trước đó được chứa trong token.sub của phương thức này.

  2. Giá trị được trả về ở đây trở thành dữ liệu của auth() hoặc useSession() . Giá trị được trả về từ ủy quyền không phải là giá trị cuối cùng nhưng được sửa đổi một lần nữa ở đây.

Bằng cách này, bạn có thể kiểm tra user.userData trong auth() hoặc useSession().

Truy cập các trang theo quyền

Bây giờ bạn có thể chèn dữ liệu tùy chỉnh vào đối tượng phiên, bạn có thể truy cập các trang dựa trên quyền. Trong hàm async callbacks.session, bạn có thể nhận thông tin như vai trò từ máy chủ và nhập thông tin đó. Giả sử session.userData.role có quyền quản trị hoặc quyền thông thường. Và giả sử nếu vai trò là quản trị viên thì bạn có thể truy cập trang quản trị (/admin), nhưng nếu vai trò là bình thường thì bạn không thể. Làm thế nào tôi có thể thực hiện điều này?

Hiện tại, middleware.ts như sau. Điều này sẽ chỉ chạy trên tuyến được chỉ định trong cấu hình, vì vậy hãy xóa tất cả cấu hình.

 import { auth } from "./auth" import {NextResponse} from "next/server"; export async function middleware() { const session = await auth(); if (!session) { return NextResponse.redirect('http://localhost:3000/i/flow/login'); } } // See "Matching Paths" below to learn more export const config = { matcher: ['/compose/tweet', '/home', '/explore', '/messages', '/search'], }

Và bạn có thể viết nó theo cách thủ công bên trong chức năng phần mềm trung gian. request.nextUrl.pathname chứa tên đường dẫn bạn hiện muốn truy cập.

 import { auth } from "./auth" import {NextResponse} from "next/server"; export async function middleware() { const session = await auth(); if (['/compose/tweet', '/home', '/explore', '/messages', '/search'].includes(request.nextUrl.pathname) && !session) { return NextResponse.redirect('http://localhost:3000/i/flow/login'); } }

Sau khi thực hiện sửa đổi này, chúng ta có thể truy cập vào quyền thông qua session.userData.role trong phiên auth(), vì vậy chúng ta có thể kiểm tra và chuyển hướng như sau.

 import { auth } from "./auth" import {NextResponse} from "next/server"; export async function middleware() { const session = await auth(); if (['/compose/tweet', '/home', '/explore', '/messages', '/search'].includes(request.nextUrl.pathname) && !session) { return NextResponse.redirect('http://localhost:3000/i/flow/login'); } if (request.nextUrl.pathname.startsWith('/admin') && session?.userData.role !== 'admin') { return NextResponse.redirect('http://localhost:3000/권한없음_알리는_모달_주소'); } }

Bằng cách nào đó bạn có thể sử dụng tính năng xác thực tiếp theo còn thiếu.

Chúng tôi sẽ cho bạn biết nếu có thêm bất kỳ thông tin cập nhật nào. Cảm ơn!

Bình luận