Tạo một Middleware kiểm tra sự đăng nhập của user. Ở đây mình đã có chuẩn bị sẵn một server xử lý BackEnd rồi nhé
Nên trong bài này ta chi việc fetch api và xử lý giá trị trả về thôi. Bạn nào chưa xem bài viết trước về Middleware thì có thể vào link này xem lại:Create A Middleware In NextJS 13
# Create a api folder in Project
+ app/api/login/route.ts
Trong tệp route.ts này, ta sẽ gửi (username, password) đến server backend để check đăng nhập. Nếu đúng sẽ trả về access_token
import { NextRequest, NextResponse } from "next/server"; type RequestBody = { email: string; password: string; }; export async function POST(request: NextRequest) { const body: RequestBody = await request.json(); const value = { email: body.email, password: body.password, }; const res = await fetch("https://127.0.0.1:8000/api/auth/login", { method: "POST", mode: "cors", cache: "no-cache", credentials: "same-origin", headers: { "Content-Type": "application/json", }, body: JSON.stringify(value), }); const data = await res.json(); if (data.success) { // Then set a cookie const response = NextResponse.json( { success: data.success, }, { status: 200 } ); response.cookies.set({ name: "login", value: "true", httpOnly: true, }); response.cookies.set({ name: "access_token", value: data.access_token, //token value here httpOnly: true, maxAge: data.expires_in, }); return response; } return new NextResponse(null, { status: 404, statusText: "Bad request", headers: { "Content-Type": "text/plain", }, }); }
Backend sẽ trả về dữ liệu như ( access_token, expires_in) , chúng ta dùng dữ liệu này lưu dưới dạng cookie nhé
const response = NextResponse.json( { success: data.success, }, { status: 200 } ); response.cookies.set({ name: "login", value: "true", httpOnly: true, }); response.cookies.set({ name: "access_token", value: data.access_token, //token value here httpOnly: true, maxAge: data.expires_in, });
# Create a Middleware
+ middleware.ts : dùng để check access_token, có tồn tại hay chưa bằng việt sử dụng request.cookie.get('access_token')
import { NextRequest, NextResponse } from "next/server"; const allow_origin_lists :string[] = process.env.NODE_ENV==='production'?['https://hoanguyenit.com','https://100daysofcode.hoanguyenit.com']: ['https://www.google.com','http://localhost:3000','http://127.0.0.1:3000'] export default function middleware(request: NextRequest){ const login = request.cookies.get("login"); const check_login= !login?.value? false: true const access_token = request.cookies.get("access_token"); const check_token = !access_token?.value? false: true const origin: string | null = request.headers.get('origin') const res = NextResponse.next() // console.log(request.nextUrl.pathname); const res_404 = new NextResponse(null, { status: 404, statusText:"Bad request", headers:{ 'Content-Type':'text/plain' } }) if(origin && !allow_origin_lists.includes(origin)){ return res_404; } if(!check_login && !check_token){ return res_404; } console.log("origin",origin); res.headers.append('Access-Control-Allow-Credentials', "true") res.headers.append('Access-Control-Allow-Origin', origin) res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT') res.headers.append( 'Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version' ) return res; } export const config = { matcher:[ '/api/categories:path*', '/api/post:path*', '/api/user:path*' ] }
Trong đoạn code trên ta kiểm tra các giá trị trong cookie mà ta đã lưu ở phần login bên trên
const login = request.cookies.get("login"); const check_login= !login?.value? false: true const access_token = request.cookies.get("access_token"); const check_token = !access_token?.value? false: true //nếu không đúng trả về status 404 if(!check_login && !check_token){ return res_404; }
Còn ở đây, ta cần middleware request các đường route api sau:
export const config = { matcher:[ '/api/categories:path*', '/api/post:path*', '/api/user:path*' ] }
Okay vậy là ta đã tạo được Middleware xong.
Bây giờ ta cần tạo một folder api user để lấy thông tin của user đó. Nếu mọi thứ ở middleware điều chính xác, nó sẽ cho phép ta gọi tới api/user/
+ app/api/user/route.ts
import { NextRequest, NextResponse } from 'next/server' type ResponseBody = { errors: { message: string }[] } | { username: string }; async function getUserByValidSessionToken(token : string){ const res = await fetch('http://127.0.0.1:8000/api/auth/user-profile',{ headers: { "Content-Type": "application/json", "Authorization":"Bearer "+token }, }); const data = await res.json(); return { username: data.name } } export async function GET( request: NextRequest ): Promise<NextResponse<ResponseBody>> { const token = request.cookies.get("access_token"); const user = !token?.value ? undefined : await getUserByValidSessionToken(token.value); if (!user) { return NextResponse.json({ errors: [{ message: "User not found by session token" }], }); } return NextResponse.json({ username: user.username, });
}
Lấy giá trị chưa access_token trong cookie
const token = request.cookies.get("access_token"); const user = !token?.value ? undefined : await getUserByValidSessionToken(token.value);
Viết fucntion fetch api + token
const res = await fetch('http://127.0.0.1:8000/api/auth/user-profile',{ headers: { "Content-Type": "application/json", "Authorization":"Bearer "+token }, });
Okay như vậy là xong rồi đó , bạn có thể phát triển thêm
+ Check thời gian hết hạn của token , nếu Token hết hạn, bạn có thể bắt người dùng đăng nhập lại
+ Còn nếu bên BackEnd có kèm theo refresh_token , thì lấy refresh_token xem còn hạn không, gửi đến BackEnd, để lấy access_token mới lại
Bạn có thể xem thêm về JWT(Json Web Token) In Node.Js