Hướng dẫn chi tiết: Sử dụng Middleware trong Next.js 14 để chuyển hướng trang đăng nhập

2026-05-28 · Uncategorized · 읽는데 23분

Hướng dẫn chi tiết: Sử dụng Middleware trong Next.js 14 để chuyển hướng trang đăng nhập

썸네일

Middleware trong Next.js 14 là gì và tại sao bạn cần nó?

Bạn có bao giờ tự hỏi làm thế nào để kiểm soát quyền truy cập vào các trang web chỉ dành cho người dùng đã đăng nhập một cách mượt mà? Tôi nhớ hồi mới làm quen với Next.js, mình từng phải viết một đống logic kiểm tra auth ở từng component riêng lẻ.

Kết quả là code rối như mớ bòng bong. Sau đó, mình phát hiện ra Middleware – một thứ thay đổi hoàn toàn cách tiếp cận.

Middleware trong Next.js 14 hoạt động như một lớp chặn giữa request và response. Nó chạy trước khi route được render, giúp kiểm tra cookie, session, token, và quyết định có cho phép truy cập hay không.

Điều này cực kỳ hữu ích cho việc chuyển hướng người dùng chưa đăng nhập về trang login. Hãy tưởng tượng bạn có một ứng dụng quản lý đơn hàng.

Nếu ai đó gõ thẳng đường dẫn /dashboard vào trình duyệt, Middleware sẽ kiểm tra ngay lập tức. Nếu không có token hợp lệ, người dùng sẽ bị đá về /login trong chớp mắt.

Dưới đây là bảng so sánh trực quan giữa cách làm cũ và cách dùng Middleware:

Tiêu chí Kiểm tra auth trong từng component Dùng Middleware
Thời điểm kiểm tra Sau khi component render Trước khi render
Số dòng code trung bình 10-20 dòng mỗi file 20-30 dòng tổng thể
Hiệu suất Chậm hơn do phải render rồi mới check Nhanh hơn nhờ kiểm tra sớm
Bảo trì Khó, phải sửa nhiều file Dễ, chỉ cần sửa một file
Khả năng xử lý redirect Phức tạp, dễ gây lỗi Đơn giản, tự động

Nhờ có Middleware, bạn có thể tập trung logic xác thực vào một chỗ duy nhất. Sau khi hiểu được khái niệm cơ bản, việc tiếp theo là cài đặt và cấu hình như thế nào.

Cài đặt và cấu hình Middleware trong dự án Next.js 14

Để bắt đầu, bạn cần tạo file middleware.ts ở thư mục gốc của dự án (cùng cấp với thư mục app). Đừng nhầm lẫn với việc đặt nó trong app/ nhé – nó phải nằm ở root.

Trong quá trình phát triển thực tế, tôi từng gặp khá nhiều lỗi vì đặt sai vị trí file. Ngồi mò mẫm cả tiếng mới phát hiện ra.

Bài học rút ra: hãy kiểm tra kỹ cấu trúc thư mục trước. Dưới đây là bảng các bước cần làm khi khởi tạo Middleware:

Bước Hành động Lưu ý
1 Tạo file middleware.ts tại thư mục gốc Không được đặt trong app/
2 Export hàm middleware mặc định Bắt buộc đúng tên
3 Import NextResponse và NextRequest Từ thư viện next/server
4 Định nghĩa matcher để chỉ định route Giúp Middleware không chạy toàn bộ
5 Xử lý logic auth và redirect Dùng NextResponse.redirect()

Ví dụ code cơ bản cho Middleware chuyển hướng login:

```typescript import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) { const token = request.cookies.get('auth_token')?.value; const url = request.nextUrl.clone();

if (!token && !url.pathname.includes('/login')) { url.pathname = '/login'; return NextResponse.redirect(url); }

return NextResponse.next(); }

export const config = { matcher: ['/dashboard/:path', '/profile/:path', '/admin/:path*'] }; ```

Đoạn code trên kiểm tra cookie auth_token. Nếu không có và người dùng cố vào các route như /dashboard, /profile, hay /admin, họ sẽ bị chuyển về /login.

Sau khi cài đặt xong, bạn sẽ thấy Middleware hoạt động ngay lập tức. Nhưng câu hỏi đặt ra là: làm sao để chuyển hướng thông minh hơn, giữ lại URL gốc để sau khi đăng nhập quay lại đúng trang?

Xem thêm #1

Kỹ thuật chuyển hướng thông minh Giữ lại đường dẫn gốc

Một trong những tính năng tôi thích nhất ở Middleware là khả năng redirect kèm tham số. Thay vì chỉ chuyển về /login một cách khô khan, bạn có thể đính kèm URL gốc vào query string.

Ví dụ: nếu người dùng đang cố vào /dashboard/orders/123, bạn muốn sau khi đăng nhập, họ tự động quay lại đúng trang đó, chứ không phải trang chủ. Cách thực hiện khá đơn giản:

```typescript export function middleware(request: NextRequest) { const token = request.cookies.get('auth_token')?.value; const url = request.nextUrl.clone();

if (!token && !url.pathname.includes('/login')) { const loginUrl = new URL('/login', request.url); loginUrl.searchParams.set('redirect', request.nextUrl.pathname + request.nextUrl.search); return NextResponse.redirect(loginUrl); }

return NextResponse.next(); } ```

Ở phía trang login, bạn chỉ cần đọc tham số redirect từ URL và dùng nó làm đích đến sau khi xác thực thành công. Dưới đây là bảng so sánh giữa redirect cơ bản và redirect thông minh:

Đặc điểm Redirect cơ bản Redirect thông minh
Trải nghiệm người dùng Không tốt, mất vị trí Tốt, quay lại đúng trang
Xử lý URL Chỉ redirect thẳng Kèm query string redirect
Code phức tạp Đơn giản Hơi phức tạp hơn
Tỷ lệ giữ chân người dùng Thấp Cao hơn 30-40% (theo kinh nghiệm)
Thời gian triển khai 5 phút 15 phút

Kinh nghiệm thực tế: sau khi áp dụng redirect thông minh cho một dự án thương mại điện tử, tỷ lệ người dùng hoàn tất đăng nhập và tiếp tục mua hàng tăng lên đáng kể. Đơn giản vì họ không phải mò mẫm tìm lại trang cũ.

Xử lý các trường hợp ngoại lệ và tối ưu hiệu suất

Không phải route nào cũng cần kiểm tra auth. Các trang như /login, /register, /forgot-password hay landing page công khai nên được bỏ qua.

Nếu không, bạn sẽ tạo ra vòng lặp redirect vô tận. Để tránh điều này, hãy cập nhật matcher và thêm điều kiện kiểm tra trong Middleware:

typescript export const config = { matcher: [ '/((?!api|_next/static|_next/image|favicon.ico|login|register|forgot-password).*)', ], };

Regex trên loại trừ các route công khai. Nhưng lưu ý rằng matcher chỉ hoạt động ở cấp độ route, không kiểm tra được logic phức tạp.

Vì vậy, bên trong hàm middleware, bạn vẫn nên kiểm tra thêm. Bảng dưới đây liệt kê các route nên và không nên chặn:

Loại route Ví dụ Hành động
Công khai /, /about, /contact Cho phép truy cập
Auth /login, /register Cho phép truy cập
Tài nguyên tĩnh /_next/static/*, /favicon.ico Cho phép truy cập
API /api/* Có thể kiểm tra riêng
Bảo vệ /dashboard/*, /profile/* Kiểm tra auth
Admin /admin/* Kiểm tra auth + role

Về hiệu suất, Middleware trong Next.js 14 chạy ở Edge Runtime, rất nhanh. Tuy vậy, tránh đặt logic nặng như gọi database hay fetch API trong Middleware.

Việc này làm tăng thời gian phản hồi. Thay vào đó, chỉ nên kiểm tra cookie hoặc JWT token cục bộ.

Nếu cần xác thực sâu hơn, hãy để route handler hoặc API route xử lý.

Kết hợp Middleware với các thư viện xác thực phổ biến

Trong thực tế, ít ai tự viết logic xác thực từ đầu. Các thư viện như NextAuth.js, Clerk, Auth0, hoặc Supabase đã giải quyết phần lớn vấn đề.

Tuy vậy, Middleware vẫn đóng vai trò quan trọng trong việc điều phối luồng. Ví dụ, nếu dùng NextAuth.js, Middleware có thể kiểm tra session như sau:

```typescript import { getToken } from 'next-auth/jwt'; import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server';

export async function middleware(request: NextRequest) { const token = await getToken({ req: request }); const url = request.nextUrl.clone();

if (!token && !url.pathname.includes('/login')) { url.pathname = '/api/auth/signin'; return NextResponse.redirect(url); }

return NextResponse.next(); } ```

Bảng so sánh các thư viện xác thực khi tích hợp với Middleware:

Thư viện Cách kiểm tra trong Middleware Hỗ trợ JWT Hỗ trợ session
NextAuth.js getToken() Có Có
Clerk auth() từ @clerk/nextjs Có Có
Auth0 getSession() từ @auth0/nextjs-auth0 Có Có
Supabase createRouteHandlerClient() Có Có
Firebase Auth admin.auth().verifyIdToken() Có Không

Lời khuyên: nếu dự án của bạn có nhiều role phức tạp, hãy kết hợp Middleware với API route để kiểm tra quyền chi tiết hơn. Middleware chỉ nên làm nhiệm vụ "gác cổng", không phải "quản lý nội bộ".

Xem thêm #2

Những lỗi thường gặp và cách khắc phục

Sau nhiều năm vật lộn với Next.js, tôi đã đúc kết được một số lỗi phổ biến khi dùng Middleware cho chuyển hướng login. Chia sẻ để bạn tránh mất thời gian.

Lỗi 1: Vòng lặp redirect vô tận

Nguyên nhân: Middleware chuyển hướng đến /login, nhưng route /login cũng bị kiểm tra auth. Giải pháp: Thêm điều kiện loại trừ /login trong logic hoặc matcher.

Lỗi 2: Middleware không chạy trên một số route

Nguyên nhân: matcher không đúng cú pháp regex hoặc thiếu đường dẫn. Giải pháp: Kiểm tra kỹ regex pattern.

Dùng tool online để test trước. Lỗi 3: Cookie không được gửi kèm request

Nguyên nhân: Middleware chạy ở Edge, cookie có thể bị chặn bởi CORS.

Giải pháp: Đảm bảo cookie được set với httpOnly: false nếu cần đọc từ client. Bảng tổng hợp lỗi và thời gian sửa lỗi trung bình:

Lỗi Mức độ phổ biến Thời gian sửa trung bình Cách phòng tránh
Vòng lặp redirect Rất cao 30 phút Luôn loại trừ route auth
Middleware không chạy Cao 15 phút Test với console.log
Cookie không gửi kèm Trung bình 1 giờ Kiểm tra cấu hình cookie
Lỗi khi dùng async Thấp 20 phút Dùng async đúng cách
Xung đột với thư viện auth Trung bình 2 giờ Đọc docs kỹ trước khi tích hợp

Kinh nghiệm xương máu: luôn test Middleware trên môi trường development với nhiều tình huống khác nhau. Đừng chủ quan chỉ vì nó chạy trên local.

Tổng kết và lộ trình học tiếp theo

Middleware trong Next.js 14 là công cụ mạnh mẽ giúp bạn kiểm soát luồng chuyển hướng đăng nhập một cách gọn gàng và hiệu quả. Qua bài viết này, tôi hy vọng bạn đã nắm được:

  • Cách cài đặt và cấu hình Middleware cơ bản
  • Kỹ thuật redirect thông minh giữ lại URL gốc
  • Cách xử lý ngoại lệ và tối ưu hiệu suất
  • Tích hợp với các thư viện xác thực phổ biến
  • Những lỗi thường gặp và cách khắc phục

Để đi sâu hơn, bạn có thể tìm hiểu thêm về:

  • Middleware kết hợp với role-based authorization
  • Sử dụng Middleware để A/B testing
  • Middleware cho i18n và localization
  • Middleware trong kiến trúc micro-frontend

Cuối cùng, tôi muốn nhấn mạnh rằng, dù công nghệ có thay đổi thế nào, tư duy về bảo mật và trải nghiệm người dùng vẫn là quan trọng nhất. Middleware chỉ là công cụ, còn bạn mới là người quyết định cách sử dụng nó sao cho hiệu quả.

Nếu bạn có thắc mắc hoặc muốn chia sẻ kinh nghiệm, đừng ngần ngại để lại bình luận. Chúc bạn thành công với dự án Next.js của mình!

Video liên quan

Bài viết liên quan