0Pricing
TypeScript Academy · บทเรียน

มิดเดิลแวร์และบริบท

เพิ่มการยืนยันตัวตนและบริบทที่ใช้ร่วมกันให้โพรซีเยอร์

มิดเดิลแวร์และบริบท เป็นบทเรียน TypeScript Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน TypeScript Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 4 บทเรียน

บริบทคืออะไร

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

export async function createContext({ req }: { req: Request }) {
  const token = req.headers.get('authorization');
  const user = await getUserFromToken(token);
  return { user };
}

การกำหนดประเภทให้บริบท

tRPC จะอนุมานประเภทบริบทจาก createContext และส่งต่อประเภทนี้ผ่านโพรซีเยอร์ทุกตัว คุณเริ่มต้นอินสแตนซ์ด้วยประเภทบริบทนั้น เพื่อให้ตัวแก้ไขมองเห็น ctx ที่มีประเภทถูกต้อง

import { initTRPC } from '@trpc/server';

type Context = Awaited<ReturnType<typeof createContext>>;
const t = initTRPC.context<Context>().create();

การอ่านบริบทในตัวแก้ไข

ภายในโพรซีเยอร์ใด ๆ บริบทจะพร้อมใช้งานในชื่อ ctx และมีประเภทครบถ้วน ในที่นี้โพรซีเยอร์จะอ่านผู้ใช้ปัจจุบันจากบริบท

const me = t.procedure.query(({ ctx }) => {
  // ctx.user is typed from createContext
  return ctx.user;
});

middleware คืออะไร

middleware จะทำงานก่อนตัวแก้ไขของโพรซีเยอร์ โดยสามารถตรวจสอบสิทธิ์ บันทึกเหตุการณ์ หรือแก้ไขบริบทได้ middleware จะเรียก next() เพื่อดำเนินการต่อ หรือโยนข้อผิดพลาดเพื่อปฏิเสธคำขอ

const logger = t.middleware(async ({ path, next }) => {
  console.log('calling', path);
  return next();
});

middleware สำหรับการยืนยันตัวตน

middleware ที่พบได้ทั่วไปใช้บังคับให้มีการยืนยันตัวตน หากไม่มีผู้ใช้ในบริบท middleware จะโยนข้อผิดพลาด UNAUTHORIZED มิฉะนั้นจะดำเนินการต่อไปยังตัวแก้ไข

import { TRPCError } from '@trpc/server';

const isAuthed = t.middleware(({ ctx, next }) => {
  if (!ctx.user) {
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }
  return next();
});

การทำให้ประเภทบริบทแคบลงด้วยขั้นตอนถัดไป

middleware สามารถปรับประเภทบริบทให้ละเอียดขึ้นได้ด้วยการส่ง ctx ใหม่ให้กับ next หลังจากตรวจสอบการยืนยันตัวตนแล้ว จะรับประกันได้ว่ามีผู้ใช้อยู่จริง ดังนั้นเราจึงปรับประเภทของ user จากอาจเป็นค่าว่างให้เป็นไม่เป็นค่าว่าง

const isAuthed = t.middleware(({ ctx, next }) => {
  if (!ctx.user) throw new TRPCError({ code: 'UNAUTHORIZED' });
  return next({ ctx: { user: ctx.user } }); // user now non-null
});

การสร้างโพรซีเยอร์ที่มีการป้องกัน

เชื่อมต่อ middleware ด้วย .use เพื่อสร้างโพรซีเยอร์ที่มีการป้องกันซึ่งนำกลับมาใช้ซ้ำได้ โพรซีเยอร์ทุกตัวที่สร้างจากสิ่งนี้จะต้องผ่านการยืนยันตัวตน และจะเห็นผู้ใช้ที่ไม่เป็นค่าว่าง

export const protectedProcedure = t.procedure.use(isAuthed);

const secret = protectedProcedure.query(({ ctx }) => {
  return 'Hello ' + ctx.user.name; // user is guaranteed
});

แบบเปิดกับแบบมีการป้องกัน

ตอนนี้คุณมีส่วนประกอบพื้นฐานสองแบบ ได้แก่ publicProcedure สำหรับจุดปลายทางแบบเปิด และ protectedProcedure สำหรับจุดปลายทางที่ต้องยืนยันตัวตน การเลือกพื้นฐานที่เหมาะสมจะสื่อและบังคับใช้การเข้าถึงทั้งในระดับประเภทและเวลาทำงาน

const ping = publicProcedure.query(() => 'pong');
const account = protectedProcedure.query(({ ctx }) => ctx.user);

การส่งต่อ ctx ที่มีประเภท

บริบทที่ปรับประเภทให้แคบลงจะถูกส่งต่อไปด้วย เนื่องจาก protectedProcedure รับประกันว่า ctx.user มีอยู่ ตัวแก้ไขทุกตัวที่สร้างจากสิ่งนี้จึงเห็นประเภทที่ไม่เป็นค่าว่างโดยไม่ต้องตรวจสอบซ้ำ middleware จะเข้ารหัสเงื่อนไขคงที่นี้ไว้เพียงครั้งเดียว

// In any protectedProcedure resolver:
// ctx.user is User, not User | null

การประกอบ middleware

ประกอบ middleware ได้ด้วยการเชื่อม .use ต่อกัน คุณอาจใช้การบันทึกเหตุการณ์ก่อน จากนั้นการยืนยันตัวตน แล้วจึงตรวจสอบบทบาท แต่ละส่วนจะทำงานตามลำดับ และแต่ละส่วนสามารถปรับประเภทบริบทให้แคบลงเพิ่มเติมสำหรับส่วนถัดไป

const adminProcedure = protectedProcedure.use(({ ctx, next }) => {
  if (ctx.user.role !== 'admin') {
    throw new TRPCError({ code: 'FORBIDDEN' });
  }
  return next();
});

ภาพรวมทั้งหมด

บริบทจัดเตรียมข้อมูลต่อคำขอ middleware ป้องกันและปรับประเภทข้อมูลนั้นให้ละเอียดขึ้น และโพรซีเยอร์เฉพาะทางจะฝังการรับประกันเหล่านี้ไว้ เมื่อรวมกับสคีมาอินพุตและ client ที่มีประเภทแล้ว คุณจะได้ API ที่ปลอดภัยทั้งในเวลาทำงาน และ เวลาคอมไพล์ ตั้งแต่ต้นจนจบ

// createContext -> ctx
// middleware -> auth + narrowing
// protectedProcedure -> guaranteed ctx.user
// typed client -> end-to-end safety

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจบริบทและ middleware

ทบทวน

คุณได้รักษาความปลอดภัยให้ API ของ tRPC ด้วยบริบทและ middleware

  • createContext สร้างข้อมูลร่วมต่อคำขอ โดยกำหนดประเภทผ่าน initTRPC.context
  • middleware ทำงานก่อนตัวแก้ไขเพื่อป้องกันและปรับบริบทให้ละเอียดขึ้น
  • การส่ง ctx ให้กับ next จะทำให้ประเภทของบริบทแคบลง
  • protectedProcedure ฝังการยืนยันตัวตนไว้ ทำให้ตัวแก้ไขได้รับผู้ใช้ที่ไม่เป็นค่าว่าง

คุณเรียนจบหลักสูตรความปลอดภัยด้านประเภทตั้งแต่ต้นจนจบแล้ว

คำถามที่พบบ่อย

บทเรียน “มิดเดิลแวร์และบริบท” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “มิดเดิลแวร์และบริบท” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส TypeScript Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “มิดเดิลแวร์และบริบท”

เพิ่มการยืนยันตัวตนและบริบทที่ใช้ร่วมกันให้โพรซีเยอร์ คุณปฏิบัติ TypeScript Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน TypeScript Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน TypeScript Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “มิดเดิลแวร์และบริบท” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน TypeScript Academy นี้ได้ไหม

ได้ บทเรียน TypeScript Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สถาปัตยกรรม tRPC
  2. การกำหนดเราเตอร์และโพรซีเยอร์
  3. การอนุมานชนิดข้อมูลระหว่างไคลเอนต์กับเซิร์ฟเวอร์
  4. มิดเดิลแวร์และบริบท
← กลับไปที่ TypeScript Academy