Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

ในบทความนี้ เราจะสร้างบริการ Rest API ที่ผ่านการรับรองความถูกต้องขั้นต่ำแต่ใช้งานได้อย่างสมบูรณ์ โดยใช้ประโยชน์จากเส้นทาง Next.js API และ Upstash Redis ซึ่งเราจะใช้เป็นระบบจัดเก็บข้อมูล/แคชที่เร็วสุด ๆ สำหรับข้อมูลของเรา สำหรับการตรวจสอบสิทธิ์ผู้ใช้ และสำหรับการจัดการ JWT ของเรา โปรดทราบว่าโปรเจ็กต์นี้จะไม่มีส่วนหน้า แต่จะแสดงเฉพาะ API ที่สามารถสอบถามกับไคลเอนต์ที่หลากหลายได้

ข้อกำหนดเบื้องต้น

หากต้องการติดตามบทช่วยสอน คุณจะต้องมี:

  • บัญชี Upstash — ลงทะเบียนเพื่อรับบัญชีฟรีที่นี่
  • ความรู้พื้นฐานของ Redis
  • ความรู้พื้นฐานเกี่ยวกับเส้นทาง Next.js API
  • ความรู้พื้นฐานเกี่ยวกับขั้นตอนการตรวจสอบสิทธิ์และการอนุญาต
  • เครื่องมือที่คุณเลือกสำหรับส่งคำขอ HTTP

Upstash Redis คืออะไร

Upstash คือ ฐานข้อมูลระบบคลาวด์ในหน่วยความจำแบบ Serverless ขึ้นอยู่กับเรดิส เราจะใช้เพื่อจัดเก็บข้อมูลที่จะให้บริการโดย API ของเรา นอกจากนี้เรายังจะเก็บไว้ใน Upstash Redis ฐานผู้ใช้และโทเค็นผู้ใช้ของเรา

สิ่งที่เราจะสร้าง

เราจะเขียนโค้ดบริการ REST API ที่จะอนุญาตให้แอปพลิเคชันไคลเอ็นต์สามารถขอข้อมูลจากบริการนั้นได้ (ในกรณีนี้คือรายชื่อภาพยนตร์) เราจะรักษาความปลอดภัยอุปกรณ์ปลายทางโดยใช้ JWT เราจะเขียนโค้ดบริการเข้าสู่ระบบ API เพื่อรับโทเค็น และเรายังใช้เวิร์กโฟลว์โทเค็นการรีเฟรชด้วย

เราจะไม่เน้น เกี่ยวกับการพัฒนาลูกค้า (เนื่องจากเรากำลังสร้างบริการที่ 'ไม่มีความเห็น') แต่เราจะจัดเตรียมข้อกำหนดของบริการของเราเพื่อให้ทุกคนสามารถสร้างลูกค้าได้

พื้นที่เก็บข้อมูลและการสาธิต

หากต้องการติดตามคุณอาจต้องการโคลนพื้นที่เก็บข้อมูลโปรเจ็กต์

แหล่งที่มาบน GitHub

คุณยังสามารถลองสาธิตได้ที่ URL ต่อไปนี้:

https://upstash-dwov9jbiq-popland.vercel.app/api/auth/signin

หากต้องการเชื่อมต่อกับบริการ ให้ส่งคำขอ POST HTTP ผ่านชื่อผู้ใช้ (me@home.org ) และรหัสผ่าน (รหัสผ่าน ) เหมือนตัวอย่างต่อไปนี้ (ใช้บุรุษไปรษณีย์):

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

การตั้งค่าฐานข้อมูล Redis

ก่อนอื่น คุณต้องลงทะเบียนกับ Upstash Redis (แผนฟรีจะใช้ได้สำหรับวัตถุประสงค์ในการทดสอบ) เมื่อเข้าสู่ระบบในคอนโซลเสร็จแล้ว คุณจะสามารถสร้างฐานข้อมูลใหม่ได้:

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

ดำเนินการต่อโดยคลิก “สร้างฐานข้อมูล” ตั้งชื่อเป็น MovieManager และตั้งเป็น Global ตอนนี้เราเพิ่มข้อมูลจำลองโดยใช้ Upstash CLI

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

เราจะเพิ่มภาพยนตร์บางเรื่องเป็นแฮช Redis (โดยพื้นฐานแล้วเป็นวัตถุ) โดยใช้คำสั่ง HMSET:

 hmset movie:’Dr. Strangelove’ director ‘Stanley Kubrick’ year 1964
 hmset movie:’2001: A Space Odyssey’ director ‘Stanley Kubrick’ year 1968
 hmset movie:’Pulp Fiction’ director ‘Quentin Tarantino’ year 1994
 hmset movie:’Django Unchained’ director ‘Quentin Tarantino’ year 2012

นอกจากนี้เรายังจะเพิ่มผู้ใช้ที่จะได้รับอนุญาตให้เข้าถึงข้อมูล ผู้ใช้จะเป็นแฮช Redis:

 hmset user:’me@home.org’ password $2b$10$zctxUVDyy3jzvSp68oKpMOnkyra4R.NzOFVh9aii3Y43X7XtetoyK level 0

โปรดทราบ :รหัสผ่านถูกเข้ารหัสด้วย 00 (โดยทั่วไปคือ รหัสผ่าน ) โดยปกติแล้ว ผู้ใช้ที่ต้องการเข้าถึงการลงทะเบียน API ผ่านทางเว็บไซต์ (หรือรับข้อมูลรับรองบนเว็บไซต์) ในตัวอย่างนี้ เราไม่ได้จัดเตรียมจุดสิ้นสุดการลงทะเบียน

ทุกคำสั่งที่ป้อนใน Upstash CLI ควรให้การตอบกลับที่ตกลง หากทุกอย่างถูกต้องและคุณไปที่ เบราว์เซอร์ข้อมูล และเลือกแฮช คุณจะมีรายการข้อมูลที่คุณใส่ไว้

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

ขั้นตอนการอนุญาต

ตามที่กล่าวไว้ก่อนหน้านี้ ตำแหน่งข้อมูลของเราไม่สามารถเข้าถึงได้แบบสาธารณะ ดังนั้นเราจึงต้องมีวิธีการตรวจสอบสิทธิ์และให้สิทธิ์ผู้ใช้ สำหรับการรับรองความถูกต้อง เราจัดให้มีจุดสิ้นสุดการเข้าสู่ระบบ สำหรับการอนุญาต จุดสิ้นสุดที่ได้รับการป้องกันจำเป็นต้องมีส่วนหัวการอนุญาตเพื่อส่งไปพร้อมกับคำขอ นี่คือวิธีการทำงานของเวิร์กโฟลว์โดยละเอียด:

  • ผู้ใช้ร้องขอปลายทางการลงชื่อเข้าใช้ โดยโพสต์ชื่อผู้ใช้และรหัสผ่าน
  • เซิร์ฟเวอร์พยายามตรวจสอบสิทธิ์ผู้ใช้ หากผู้ใช้ถูกต้อง เซิร์ฟเวอร์สร้างและส่ง JWT (JSON Web Token) และโทเค็นการรีเฟรชกลับมา โทเค็นการรีเฟรชจะถูกจัดเก็บไว้ในอินสแตนซ์ Upstash Redis ของเราด้วย
  • ลูกค้าได้รับโทเค็นกลับมาและเก็บไว้ที่ไหนสักแห่ง (เป็นความรับผิดชอบของลูกค้าว่าจะจัดเก็บอย่างไร/ที่ไหน)
  • ไคลเอนต์ร้องขอจุดสิ้นสุดที่ได้รับการป้องกัน โดยส่ง JWT ในส่วนหัว
  • เซิร์ฟเวอร์ได้รับ JWT ตรวจสอบ และหากได้รับการยืนยันแล้ว ก็จะส่งข้อมูลที่ลูกค้าร้องขอกลับมา
  • เมื่อ JWT หมดอายุหรือใกล้จะหมดอายุ ลูกค้าสามารถขอ JWT ใหม่โดยไม่ต้องเข้าสู่ระบบใหม่ โดยส่ง Refresh Token ไปยังจุดสิ้นสุดที่ระบุ
  • เซิร์ฟเวอร์ได้รับ Refresh Token ตรวจสอบ และหากการตรวจสอบเป็นบวก จะต้องออก JWT และ Refresh Token ใหม่ ให้ส่งกลับไปยังไคลเอนต์ และเก็บ Refresh Token ใหม่อีกครั้ง

JWT และ Refresh Token อยู่ในรูปแบบเดียวกัน ได้ข้อมูลเกือบเหมือนกันแต่ใช้ 2 คีย์ที่แตกต่างกัน (เราจะตั้งค่าใน 13 ของเรา ) และมีการหมดอายุที่แตกต่างกันสองแบบ:แบบสั้นสำหรับ JWT (เนื่องจากเป็นโทเค็นที่ใช้มากที่สุดในระหว่างเซสชัน เราจะทำให้หมดอายุเร็วๆ นี้ ในกรณีที่ถูกดักฟัง) และแบบยาวสำหรับ Refresh Token ระยะเวลาของทั้งสองอย่างขึ้นอยู่กับความปลอดภัยที่คุณต้องอยู่ โดยปกติ JWT จะหมดอายุภายในไม่ถึงหนึ่งชั่วโมง และ Refresh Token จะอยู่ได้หนึ่งเดือน หากโทเค็นทั้งสองหมดอายุ ผู้ใช้จะต้องเข้าสู่ระบบอีกครั้ง

การตั้งค่าโครงการ

เมื่อเราเสร็จสิ้นกับฐานข้อมูล Upstash Redis แล้ว เราก็สามารถเริ่มต้นโครงการของเราได้ ก่อนอื่น เราสร้างโปรเจ็กต์ Next.js ใหม่:

 npx create-next-app upstash-jwt

จากนั้นเราเข้าไปในโฟลเดอร์ที่สร้างขึ้นใหม่ 29 และเราติดตั้งโมดูลที่จำเป็น:

 npm i bcrypt jsonwebtoken @upstash/redis

สร้าง 33 ไฟล์เพื่อจัดเก็บคีย์ของคุณและกรอกข้อมูลที่ถูกต้อง

 SECRET_TOKEN=
 SECRET_RTOKEN=
 UPSTASH_REDIS_REST_URL=
 UPSTASH_REDIS_REST_TOKEN=

สร้าง SECRET_TOKEN และ SECRET_RTOKEN ที่จะใช้ในการสร้าง JWT โปรดจำไว้ว่าคีย์เหล่านี้ควรถูกเก็บเป็นความลับและควรเป็นแบบสุ่ม/คาดเดาได้ยาก คุณสามารถใช้สตริง Hex แบบ 64 บิตได้ รับ UPSTASH_REDIS_REST_URL และ UPSTASH_REDIS_REST_TOKEN จากคอนโซล Upstash แท็บรายละเอียด ส่วน Rest API:

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

ตอนนี้เราสามารถเริ่มวางโครงร่างจุดสิ้นสุดของเราได้แล้ว:

POST /auth/signin มันเข้าสู่ระบบผู้ใช้ โดยต้องส่งอีเมลและรหัสผ่านเป็นวัตถุ JSON 40 โดยจะส่งคืนออบเจ็กต์ JSON พร้อมข้อมูลผู้ใช้ JWT และโทเค็นการรีเฟรช

รับ /ภาพยนตร์/ ส่งคืนรายการภาพยนตร์เป็นออบเจ็กต์ JSON โดยต้องใช้ JWT ที่ถูกต้องซึ่งถูกส่งผ่านในส่วนหัวด้วยรูปแบบนี้:การอนุญาต:Bearer xxx

รับ /ภาพยนตร์/$ID กลับรายละเอียดของภาพยนตร์ด้วยรหัส $ID

โพสต์ /auth/รีเฟรช สร้างและส่งคืน JWT ใหม่ ควรส่งโทเค็นการรีเฟรชเป็น 51 พารามิเตอร์

โค้ดสำหรับเส้นทาง API

เราเริ่มต้นด้วยจุดสิ้นสุดการลงชื่อเข้าใช้ เรามาสร้างไฟล์ 66 กัน ดังต่อไปนี้:

import bcrypt from "bcrypt";
 
import {
 addToList,
 generateAccessToken,
 generateRefreshToken,
 redis,
} from "../../../utils";
 
export default async (req, res) => {
 if (req.method === "GET") {
 res.status(405).send("Not Allowed");
 } else {
 console.log(req.body.user);
 try {
 const user = await redis.hgetall(`user:${req.body.user}`);
 if (user) {
 const validPassword = bcrypt.compare(req.body.password, user.password);
 if (validPassword) {
 const token = generateAccessToken(req.body.user, user.level);
 const refreshToken = generateRefreshToken(req.body.user, user.level);
 const refresh = await addToList(req.body.user, refreshToken);
 const content = {
 user: req.body.user,
 level: user.level,
 };
 res.status(200).json({
 message: "Logged in",
 content: content,
 JWT: token,
 refresh: refreshToken,
 });
 } else {
 res.status(400).json({ error: "Invalid Password" });
 }
 } else {
 res.status(401).json({ error: "User not found" });
 }
 } catch (error) {
 res.status(500).send("Internal Server Error");
 }
 }
};

จุดสิ้นสุดการลงชื่อเข้าใช้ของเราจะยอมรับ POST ที่มีพารามิเตอร์สองตัวเท่านั้น:ผู้ใช้ และรหัสผ่าน . ก่อนอื่น เราจะตรวจสอบว่ามีผู้ใช้อยู่ในฐานข้อมูล Redis ของเราด้วย:

 const user = await redis.hgetall(`user:${req.body.user}`);

หากมีผู้ใช้อยู่ เราจะเปรียบเทียบรหัสผ่านที่เข้ารหัส:

 const validPassword = bcrypt.compare(req.body.password, user.password);

ณ จุดนี้ หากรหัสผ่านตรงกัน เราสามารถถือว่าผู้ใช้ได้รับการรับรองความถูกต้อง และเราสามารถส่ง JWT และโทเค็นการรีเฟรชกลับมาได้ เรายังจัดเก็บโทเค็นการรีเฟรชไว้ในอินสแตนซ์ Redis ของเรา ในการทำเช่นนั้น เราใช้ฟังก์ชันบางอย่างที่อยู่ในไฟล์ภายนอกที่เรียกว่า 74

ถือเป็นความรับผิดชอบของลูกค้าในการจัดเก็บโทเค็นที่ส่งคืน ใช้โทเค็นเพื่ออนุญาตเมื่อจำเป็น และรีเฟรชเมื่อหมดอายุ

เรามีฟังก์ชั่นในการสร้าง Token ของเรา 83 หนึ่งรายการเพื่อสร้างโทเค็นการรีเฟรชของเรา 92 และอีกอันสำหรับเก็บโทเค็นการรีเฟรชใน Redis 105 ของเรา . 115 นี้ ไฟล์นี้ยังใช้เพื่อเก็บฟังก์ชันยูทิลิตีและการอ้างอิงอื่นๆ ทั้งหมด (เช่น การเชื่อมต่อ Redis การตรวจสอบโทเค็นและรีเฟรช และอื่นๆ):

import { Redis } from "@upstash/redis";
import jwt from "jsonwebtoken";
 
export const redis = new Redis({
 url: process.env.UPSTASH_REDIS_REST_URL,
 token: process.env.UPSTASH_REDIS_REST_TOKEN,
});
export function generateAccessToken(username, email, level) {
 return jwt.sign(
 { user: username, email: email, level: level },
 process.env.SECRET_TOKEN,
 {
 expiresIn: "1h",
 },
 );
}
 
export function generateRefreshToken(username, email, level) {
 return jwt.sign(
 { user: username, email: email, level: level },
 process.env.SECRET_RTOKEN,
 {
 expiresIn: "30d",
 },
 );
}
 
export async function addToList(user, refresher) {
 try {
 await redis.hset("refresh:" + user, { refresh: refresher });
 } catch (error) {
 console.log(error);
 }
}
 
export async function tokenRefresh(refreshtoken, res) {
 var decoded = "";
 try {
 decoded = jwt.verify(refreshtoken, process.env.SECRET_RTOKEN);
 } catch (error) {
 return res.status(401).send("Can't refresh. Invalid Token");
 }
 if (decoded) {
 try {
 const rtoken = await redis.hget("refresh:" + decoded.user, "refresh");
 console.log(rtoken);
 if (rtoken !== refreshtoken) {
 return res.status(401).send("Can't refresh. Invalid Token");
 } else {
 const user = await redis.hgetall(`user:${decoded.user}`);
 console.log(user);
 const token = generateAccessToken(decoded.user, user.level);
 const refreshToken = generateRefreshToken(decoded.user, user.level);
 
 const refresh = await addToList(decoded.user, refreshToken);
 
 const content = {
 user: decoded.user,
 level: user.level,
 };
 return {
 message: "Token Refreshed",
 content: content,
 JWT: token,
 refresh: refreshToken,
 };
 }
 } catch (error) {
 console.log(error);
 }
 }
}
 
export async function verifyToken(token, res) {
 try {
 const decoded = jwt.verify(token, process.env.SECRET_TOKEN);
 return decoded;
 } catch (err) {
 return res.status(405).send("Token is invalid");
 }
}

ตอนนี้เราสามารถใช้เครื่องมือ (เช่นบุรุษไปรษณีย์) เพื่อทดสอบกระบวนการลงนามได้โดยการโพสต์ไปที่ 129 และส่งชื่อผู้ใช้ (me@home.org ) และรหัสผ่าน (รหัสผ่าน ) คุณควรส่งคืนออบเจ็กต์ JSON ที่มีรายละเอียดผู้ใช้ พร้อมด้วย JWT และโทเค็นการรีเฟรช:

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

หากทุกอย่างถูกต้อง ในฐานข้อมูล Redis ของคุณ ตอนนี้คุณควรเห็นรายการแฮชใหม่สำหรับโทเค็นการรีเฟรชที่สร้างขึ้นใหม่:

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

ต่อไป เรากำลังดำเนินการขั้นตอนการรับรองความถูกต้องให้เสร็จสิ้น โดยการเข้ารหัสเส้นทางการรีเฟรชโทเค็น 133

import { redis, tokenRefresh } from "../../../utils";
 
export default async (req, res) => {
 if (req.method === "GET") {
 res.status(405).send("Not Allowed");
 } else {
 console.log(req.body.refresh);
 const refresp = await tokenRefresh(req.body.refresh, res);
 res.status(200).json(refresp);
 }
};

มันใช้ tokenRefresh ฟังก์ชั่นจาก 148 เริ่มต้นด้วยการตรวจสอบว่าโทเค็นนั้นถูกต้องและสามารถถอดรหัสได้ จากนั้นจะตรวจสอบ Redis ว่าผู้ใช้ได้รับโทเค็นการรีเฟรชหรือไม่ (อันที่เราเก็บไว้ก่อนหน้านี้ด้วย addToList ) หากทุกอย่างถูกต้องจะสร้าง JWT ใหม่ โทเค็นการรีเฟรชใหม่ (และจัดเก็บอีกครั้งใน Redis) และส่งทุกอย่างกลับไปยังไคลเอนต์

เราสามารถทดสอบตำแหน่งข้อมูลนี้โดยใช้เครื่องมือของเรา โดยโพสต์ไปที่ 159 และส่งโทเค็นการรีเฟรชเป็นพารามิเตอร์:

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

ตอนนี้ ไคลเอนต์สมมติของเราสามารถเข้าสู่ระบบและรีเฟรชโทเค็นได้ มาดูกันว่าโทเค็นสามารถใช้เพื่อส่งคำขอที่มีการตรวจสอบสิทธิ์ได้อย่างไร

สร้างเส้นทาง API ใหม่:168 ที่จะใช้ในการรับรายชื่อภาพยนตร์และรับรายละเอียดภาพยนตร์:

import { redis, verifyToken } from "../../../utils";
 
export default async (req, res) => {
 var id;
 console.log(req.query);
 if (req.query.id) {
 id = req.query.id[0];
 }
 
 var decoded = "";
 const authHeader = req.headers["authorization"];
 const token = authHeader && authHeader.split(" ")[1];
 if (!token) {
 return res.status(403).send("A token is required for authentication");
 } else {
 decoded = await verifyToken(token, res);
 }
 if (decoded) {
 if (id) {
 try {
 const result = await redis.hgetall(id);
 console.log(result);
 return res.status(200).json(result);
 } catch (error) {
 return res.status(500).send("Internal Server Error");
 }
 } else {
 try {
 const result = await redis.scan(0, { match: "movie:*" });
 return res.status(200).json(result);
 } catch (error) {
 return res.status(500).send("Internal Server Error");
 }
 }
 }
};

การใช้ verifyToken ฟังก์ชั่นจาก 171 ของเรา เราสามารถจำกัดการเข้าถึงตำแหน่งข้อมูล API ของเราได้เฉพาะผู้ใช้ที่ให้โทเค็นที่ถูกต้องเท่านั้น เราทำแบบสอบถามตัวอย่างสองสามข้อ โดยข้อแรกเพื่อรับรายชื่อภาพยนตร์

 const result = await redis.scan(0, { match: ‘movie:*’ });

และรายการที่สองเพื่อรับรายละเอียดของภาพยนตร์เรื่องเดียว โดยอิงตามพารามิเตอร์รหัสในคำขอ URL:

const result = await redis.hgetall(id);

คำขอทั้งสองขึ้นอยู่กับสถานะผู้ใช้ที่ตรวจสอบผ่าน verifyToken แต่คุณสามารถผสมและจับคู่ได้ เช่น รายการสามารถเปิดเผยต่อสาธารณะ และสามารถป้องกันรายละเอียดได้ เนื่องจากเรามีระดับที่เก็บไว้ในผู้ใช้ (และในโทเค็น) เราจึงสามารถมีระดับการอนุญาตได้มากขึ้น ลองรับรายชื่อภาพยนตร์:

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

และรายละเอียดภาพยนตร์เรื่องเดียว:

สร้าง API ที่ปลอดภัยและรวดเร็วที่ผ่านการรับรองความถูกต้องโดยใช้เส้นทาง Next.js และ Upstash Redis

มุมมองของลูกค้า

ดังที่เราได้กล่าวไว้ก่อนหน้านี้ เราเพียงมุ่งเน้นไปที่ส่วนของเซิร์ฟเวอร์ นี่คือขอบเขตหลักของ API ซึ่งควรเป็นนามธรรม ไม่ใช่เว็บไซต์ วิธีที่ไคลเอ็นต์ร้องขอข้อมูล (ภาษาการเขียนโปรแกรม ไลบรารี และอื่นๆ) เป็นทางเลือกของนักพัฒนาไคลเอ็นต์ เราจะจัดเตรียมรายการตำแหน่งข้อมูล สิ่งที่ปลายทางของเราคาดหวัง และสิ่งที่ปลายทางของเราส่งคืนไปยังไคลเอ็นต์ การจัดการข้อมูล ความล่าช้าในการรีเฟรช และอื่นๆ ทั้งหมดเป็นกลยุทธ์ของลูกค้า

อะไรต่อไป

นี่เป็นเพียงตัวอย่างพื้นฐานของเวิร์กโฟลว์ของ API ที่ได้รับการป้องกัน จากที่นี่ สิ่งที่สามารถปรับปรุงได้เท่านั้น:เพิ่มประสิทธิภาพวิธีการจัดเก็บข้อมูลบน Redis, ปรับปรุงความปลอดภัยในการเข้าสู่ระบบโดยจัดเก็บข้อมูลผู้ใช้บนอินสแตนซ์ Redis อื่น, ตรวจสอบและตรวจสอบความถูกต้องของข้อมูลที่ผู้ใช้ส่งก่อนหน้านี้, เพิ่มจุดสิ้นสุดเพิ่มเติม, การส่งคืนข้อมูลในรูปแบบ GraphQL, สร้างไคลเอนต์สำหรับ API ของคุณ, จำกัดการเข้าถึงจำนวนการโทรสูงสุดต่อชั่วโมง, ใช้ระดับเพื่อจำกัดการเข้าถึง… ส่วนขยายและการปรับปรุงไม่มีที่สิ้นสุด!