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

สร้าง API Keys ที่ปลอดภัยด้วย Upstash Redis และ Cloudflare Workers: คู่มือขั้นตอนต่อขั้นตอน

API keys เหมือนกุญแจประตูหน้าของบริการของคุณ - มันปล่อยให้ผู้ใช้เข้าไปขณะที่รักษาความปลอดภัย ในบล็อกนี้ ผมจะพาคุณสร้าง API key generator ที่เรียบง่ายและปลอดภัย โดยใช้ Upstash Redis สำหรับจัดเก็บข้อมูลแบบ serverless ที่รวดเร็ว และ Cloudflare Workers เพื่อจัดการ requests ที่ edge ไม่ว่าคุณจะตั้งค่าบริการใหม่หรือเพิ่ม keys ให้กับแอปที่มีอยู่แล้ว คุณจะได้เรียนรู้วิธีสร้าง จัดเก็บ และตรวจสอบ API keys เพื่อให้ทุกอย่างทำงานราบรื่นและมีประสิทธิภาพ

API Key คืออะไร?

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

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

ในคู่มือนี้ เราจะสร้าง api key generator ที่ให้ 2 ฟังก์ชันหลัก:

  1. สร้าง API keys ใหม่พร้อมการตั้งค่าที่ปรับแต่งได้
  2. ตรวจสอบ API keys พร้อมดึง metadata ของมัน

คุณสมบัติหลักจะรวมถึง:

  • Customizable key prefixes
  • Expiration dates
  • Rate limiting
  • Metadata storage
  • Owner identification

ลองจินตนาการระบบ API key ของเรา

แผนภาพนี้แสดงการโต้ตอบระหว่าง client, Cloudflare Worker ของเรา และ Upstash Redis สำหรับทั้งการสร้างและตรวจสอบ API keys ด้วยภาพรวมนี้ในใจ มาเริ่มสร้างระบบของเรา

สร้าง API Keys ที่ปลอดภัยด้วย Upstash Redis และ Cloudflare Workers: คู่มือขั้นตอนต่อขั้นตอน

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

เพื่อติดตาม คุณจะต้องมี:

  • บัญชี Cloudflare Workers
  • บัญชี Upstash
  • Node.js ติดตั้งบนเครื่อง local

โครงสร้างโปรเจกต์

โปรเจกต์ของเราจะมีโครงสร้างดังนี้:

folder-name/ ├── src/ │ ├── config/ │ │ ├── generateApiKey.ts │ │ └── schema-validation.ts │ ├── lib/ │ │ └── ratelimit.ts │ ├── routes/ │ │ ├── create.ts │ │ └── verify.ts │ ├── types/ │ │ └── api.ts │ └── index.ts ├── package.json └── wrangler.toml 

ขั้นตอนที่ 1: Project Setup

เริ่มต้นด้วยการตั้งค่าโปรเจกต์และติดตั้ง dependencies ที่จำเป็น

สร้างไดเรกทอรีโปรเจกต์ใหม่

เปิดเทอร์มินัลและรันคำสั่งต่อไปนี้:

mkdir keyflow cd keyflow npm init -y

ติดตั้ง dependencies

เราจะต้องการแพ็กเกจนิดหน่อยสำหรับโปรเจกต์ของเรา:

npm install hono @upstash/redis @upstash/ratelimit @hono/zod-validator zod wrangler

@upstash/redis: Upstash Redis client สำหรับ serverless environments @upstash/ratelimit: ไลบรารี rate limiting สำหรับ Upstash Redis @hono/zod-validator: Middleware ตรวจสอบ request สำหรับ Hono zod: ไลบรารี schema validation ที่ให้ความสำคัญกับ TypeScript ก่อน wrangler: CLI ของ Cloudflare สำหรับพัฒนาและปรับใช้ Workers

ตั้งค่า Upstash Redis

  1. Login เข้าบัญชี Upstash และสร้างฐานข้อมูล Redis ใหม่

สร้าง API Keys ที่ปลอดภัยด้วย Upstash Redis และ Cloudflare Workers: คู่มือขั้นตอนต่อขั้นตอน

  1. หลังสร้างแล้ว ไปที่ส่วน "REST API"

สร้าง API Keys ที่ปลอดภัยด้วย Upstash Redis และ Cloudflare Workers: คู่มือขั้นตอนต่อขั้นตอน

  1. คัดลอก UPSTASH_REDIS_REST_URL และ UPSTASH_REDIS_REST_TOKEN ในส่วน .env

กำหนดค่า Cloudflare Workers

สร้างไฟล์ wrangler.toml ในรากโปรเจกต์ด้วยเนื้อหาต่อไปนี้:

name = "keyflow" main = "src/index.ts" compatibility_date = "2023-05-18" [vars] UPSTASH_REDIS_REST_URL = "your-redis-url" UPSTASH_REDIS_REST_TOKEN = "your-redis-token"

แทนที่ "your-redis-url" และ "your-redis-token" ด้วยค่าที่คุณคัดลอกจาก Upstash

ขั้นตอนที่ 2: กำหนด API Types

มาเริ่มต้นด้วยการกำหนด TypeScript interfaces สำหรับ API requests และ responses ของเรา Types นี้จะช่วยให้เรารักษา type safety ทั่วทั้งแอปพลิเคชัน สร้างไฟล์ใหม่ src/types/api.ts:

export type CreateKeyRequest = { apiId: string; prefix?: string; byteLength?: number; ownerId?: string; name: string; meta?: Record<string, unknown>; expires?: number; ratelimit?: { type: "fast" | "consistent"; limit: number; refillRate: number; refillInterval: number; }; }; export type CreateKeyResponse = { key: string; keyId: string; }; export type VerifyKeyRequest = { key: string; }; export type VerifyKeyResponse = { valid: boolean; ownerId?: string; meta?: Record<string, unknown>; expires?: number; ratelimit?: { limit: number; remaining: number; reset: number; }; }; export type Env = { UPSTASH_REDIS_REST_URL: string; UPSTASH_REDIS_REST_TOKEN: string; }; 

ขั้นตอนที่ 3: นำ API Key Generation ไปใช้งาน

ตอนนี้ มาสร้าง utility function เพื่อสร้าง API keys ของเรา สร้างไฟล์ใหม่ src/config/generateApiKey.ts:

export function generateApiKey( prefix: string | undefined, byteLength: number, ): string { const randomBytes = crypto.getRandomValues(new Uint8Array(byteLength)); const key = btoa(String.fromCharCode(...new Uint8Array(randomBytes))) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=/g, ""); return prefix ? `${prefix}_${key}` : key; } 

ฟังก์ชันนี้สร้าง API key แบบสุ่มโดยใช้ cryptographically secure random bytes เข้ารหัสเป็น base64 และทำให้ URL-safe

ขั้นตอนที่ 4: นำ Rate Limiting ไปใช้งาน

สร้างไฟล์ src/lib/ratelimit.ts:

import { Ratelimit } from "@upstash/ratelimit"; import { Redis } from "@upstash/redis/cloudflare"; import type { Context, Next } from "hono"; import { env } from "hono/adapter"; import type { Env } from "../types/api"; // Middleware for rate limiting export async function rateLimitMiddleware(c: Context, next: Next) { const { UPSTASH_REDIS_REST_TOKEN, UPSTASH_REDIS_REST_URL } = env<Env>(c); const redis = new Redis({ url: UPSTASH_REDIS_REST_URL, token: UPSTASH_REDIS_REST_TOKEN, }); const ratelimit = new Ratelimit({ redis: redis, limiter: Ratelimit.slidingWindow(5, "30 s"), }); const ip = c.req.header("CF-Connecting-IP") || "127.0.0.1"; const { success, limit, remaining, reset } = await ratelimit.limit(ip); if (!success) { return c.json({ error: "Rate limit exceeded" }, 429); } c.header("X-RateLimit-Limit", limit.toString()); c.header("X-RateLimit-Remaining", remaining.toString()); c.header("X-RateLimit-Reset", reset.toString()); await next(); }

ขั้นตอนที่ 5: สร้าง API Routes

มาตั้งค่าไฟล์แอปพลิเคชันหลักและสร้าง API routes ของเรา ไฟล์นี้ตั้งค่า Hono application ของเราด้วย 2 routes หลัก: /keys/create สำหรับสร้าง API keys ใหม่ และ /keys/verify สำหรับตรวจสอบ keys ที่มีอยู่ พร้อม 3 ไฟล์แยกกัน

1. Implement Create API Key Route

สร้างไฟล์ src/routes/create.ts:

import { zValidator } from "@hono/zod-validator" import { Redis } from "@upstash/redis/cloudflare" import { Hono } from "hono" import { generateApiKey } from "../config/generateApiKey" import { createApiKeySchema } from "../config/schema-validation" import type { CreateKeyRequest, CreateKeyResponse, Env } from "../types/api" const create = new Hono<{ Bindings: Env }>() create.post( "/create", zValidator("json", createApiKeySchema, (result, c) => { if (!result.success) { return c.text("Invalid!", 400) } }), async (c) => { // Initialize Redis client const { UPSTASH_REDIS_REST_TOKEN, UPSTASH_REDIS_REST_URL } = c.env const redis = new Redis({ url: UPSTASH_REDIS_REST_URL, token: UPSTASH_REDIS_REST_TOKEN, }) const body = await c.req.json<CreateKeyRequest>() // Generate unique identifier and API key const keyId = crypto.randomUUID() const key = generateApiKey(body.prefix, body.byteLength || 16) const keyData = { ...body, key, keyId, createdAt: Date.now(), } const encodedKey = encodeURIComponent(key) try { // Store key data and lookup reference in Redis await redis.set(`key:${keyId}`, JSON.stringify(keyData)) await redis.set(`lookup:${encodedKey}`, keyId) return c.json<CreateKeyResponse>({ key, keyId }) } catch (error) { console.error("Error in /keys/create:", error) return c.json({ error: "Internal Server Error" }, 500) } } ) export default create

2. Implement Verify API Key Route

สร้างไฟล์ src/routes/verify.ts:

import { zValidator } from "@hono/zod-validator"; import { Redis } from "@upstash/redis/cloudflare"; import { Hono } from "hono"; import { verifyApiKeySchema } from "../config/schema-validation"; import type { CreateKeyRequest, Env, VerifyKeyRequest, VerifyKeyResponse, } from "../types/api"; // Initialize Hono app with environment bindings const verify = new Hono<{ Bindings: Env }>(); // Define POST route for verifying an API key verify.post( "/verify", // Validate request body against schema zValidator("json", verifyApiKeySchema, (result, c) => { if (!result.success) { return c.text("Invalid!", 400); // Return 400 if validation fails } }), async (c) => { // Set up Redis with environment variables const { UPSTASH_REDIS_REST_TOKEN, UPSTASH_REDIS_REST_URL } = c.env; const redis = new Redis({ url: UPSTASH_REDIS_REST_URL, token: UPSTASH_REDIS_REST_TOKEN, }); const body = await c.req.json<VerifyKeyRequest>(); if (!body.key) { return c.json({ error: "key is required" }, 400); // Require key in the request body } const encodedKey = encodeURIComponent(body.key); const keyId = await redis.get<string>(`lookup:${encodedKey}`); // Retrieve key ID using encoded key if (!keyId) { return c.json<VerifyKeyResponse>({ valid: false }); // Key not found } const keyDataString = await redis.get<string>(`key:${keyId}`); // Retrieve key data by key ID if (!keyDataString || typeof keyDataString !== "string") { return c.json<VerifyKeyResponse>({ valid: false }); // Key data missing or invalid } let keyData: CreateKeyRequest & { key: string; keyId: string; createdAt: number; }; try { keyData = JSON.parse(keyDataString); // Parse key data } catch (parseError) { // Handle parse error by deleting invalid data console.error("Key data parse error:", parseError); await Promise.all([ redis.del(`key:${keyId}`), redis.del(`lookup:${encodedKey}`), ]); return c.json( { error: "Invalid key data in storage", details: parseError instanceof Error ? parseError.message : "Unknown parse error", valid: false, }, 500, ); } // Check if key has expired if (keyData.expires && keyData.expires < Date.now()) { await Promise.all([ redis.del(`key:${keyId}`), redis.del(`lookup:${encodedKey}`), ]); return c.json<VerifyKeyResponse>({ valid: false }); } // Formulate response with validation status and metadata const response: VerifyKeyResponse = { valid: true, ownerId: keyData.ownerId, meta: keyData.meta, expires: keyData.expires, }; if (keyData.ratelimit) { response.ratelimit = { limit: keyData.ratelimit.limit, remaining: keyData.ratelimit.limit, reset: Date.now() + keyData.ratelimit.refillInterval, }; } return c.json(response); // Return verification response }, ); export default verify; 

3. Implement Main file index.ts

implement ไฟล์หลัก src/index.ts เพื่อ import create.ts, verify.ts, และ rateLimitMiddleWare

import { Hono } from "hono"; import { rateLimitMiddleware } from "./lib/ratelimit"; import create from "./routes/create"; import verify from "./routes/verify"; import type { Env } from "./types/api"; const app = new Hono<{ Bindings: Env; }>().basePath("/keys"); app.use("*", rateLimitMiddleware); // add the create file route and verify file route app.route("/", create); app.route("/", verify); export default app; 

ขั้นตอนที่ 6: การปรับใช้ (Deployment)

ปรับใช้แอปพลิเคชัน Keyflow ของคุณไปที่ Cloudflare Workers:

  1. ติดตั้ง Wrangler:

    npm install -g wrangler
  2. Authenticate กับ Cloudflare:

    wrangler login
  3. ปรับใช้ worker ของคุณ:

    wrangler deploy

ขั้นตอนที่ 7: การปรับใช้ (Deployment)

ตอนนี้เรามีแอปพลิเคชันพร้อมแล้ว มาปรับใช้ไปที่ Cloudflare Workers:

  1. ตรวจสอบว่าคุณมี Wrangler CLI ติดตั้งแล้ว:

    npm install -g wrangler 
  2. Authenticate กับบัญชี Cloudflare ของคุณ:

    wrangler login 
  3. ปรับใช้ worker ของคุณ:

    wrangler deploy 

ขั้นตอนที่ 8: ทดสอบ API ของคุณ

มาทดสอบ API ที่เพิ่งปรับใช้:

สร้าง API Key ใหม่

curl -X POST https://keyflow.<your-subdomain>.workers.dev/keys/create \ -H "Content-Type: application/json" \ -d '{ "apiId": "my-api", "prefix": "prod", "name": "Production API Key", "expires": 1735689600000, "meta": { "environment": "production", "team": "backend" } }' 

ตรวจสอบ API Key

curl -X POST https://keyflow.<your-subdomain>.workers.dev/keys/verify \ -H "Content-Type: application/json" \ -d '{ "key": "prod_AbC123XyZ..." }' 

แทนที่ <your-subdomain> ด้วย Cloudflare Workers subdomain ของคุณ และ prod_AbC123XyZ... ด้วย key จริงที่สร้างจาก create endpoint

สรุป

การสร้าง API key generator เป็นขั้นตอนสำคัญในการรักษาความปลอดภัย API ของแอปพลิเคชันและจัดการว่าใครสามารถเข้าถึงบริการของคุณได้ ด้วยการสร้างระบบที่สามารถสร้าง ตรวจสอบ และจัดการ API keys คุณเพิ่มชั้นการควบคุมการเข้าถึงที่แข็งแกร่งซึ่งช่วยให้ข้อมูลของคุณปลอดภัยและมีระเบียบ

นี่คือสรุปอย่างรวดเร็วของสิ่งที่เข้าสู่ API key generator ที่มั่นคง:

  1. Secure Key Generation: Keys ที่ไม่ซ้ำและปลอดภัย ซึ่งรวมตัวเลือกเช่น custom prefixes หรือความยาวที่ตั้งค่าไว้ ทำให้แต่ละ key แตกต่างและยากต่อการเดา
  2. Validation and Expiration: การเพิ่มการตรวจสอบและ expiration dates รับรองว่าแต่ละ key ถูกต้องเฉพาะในช่วงเวลาที่กำหนด ทำให้ควบคุมและจำกัดการเข้าถึงได้ง่ายตามที่ต้องการ
  3. Metadata and Rate Limits: การจัดเก็บข้อมูลเพิ่มเติมกับแต่ละ key และการตั้งค่า rate limits ให้คุณติดตามการใช้งาน key ติดตามกิจกรรม และหลีกเลี่ยงการใช้งาน API อย่างผิดปกติ

การใช้เครื่องมืออย่าง Upstash Redis และ Cloudflare Workers ทำให้ง่ายต่อการสร้างระบบจัดการ key แบบ serverless และกระจายทั่วโลก ที่ scale ได้ดีและทำงานมีประสิทธิภาพ

ด้วย foundation นี้ คุณพร้อมที่จะรักษาการเข้าถึง API ของคุณให้ปลอดภัยและจัดการได้ ให้คุณมีความรู้สึกสบายใจว่าทรัพยากรของคุณได้รับการปกป้องและติดตามได้ง่าย