<पी> एपीआई कुंजियाँ आपकी सेवा के सामने वाले दरवाजे की कुंजियों की तरह हैं - वे चीजों को सुरक्षित रखते हुए उपयोगकर्ताओं को अंदर जाने देती हैं। इस ब्लॉग में, मैं आपको तेज, सर्वर रहित डेटा स्टोरेज के लिए अपस्टैश रेडिस और किनारे पर अनुरोधों को संभालने के लिए क्लाउडफ्लेयर वर्कर्स का उपयोग करके एक सरल, सुरक्षित एपीआई कुंजी जनरेटर बनाने के बारे में बताऊंगा। चाहे आप एक नई सेवा स्थापित कर रहे हों या किसी मौजूदा ऐप में कुंजियाँ जोड़ रहे हों, आप सीखेंगे कि सब कुछ सुचारू और कुशलतापूर्वक चलाने के लिए एपीआई कुंजियाँ कैसे उत्पन्न करें, संग्रहीत करें और मान्य करें। एपीआई कुंजी क्या है?
<पी> एपीआई कुंजी एक अद्वितीय कोड है जो आपके एपीआई तक पहुंचने का प्रयास करने वाले उपयोगकर्ता या एप्लिकेशन को पहचानता है और प्रमाणित करता है। इसे एक व्यक्तिगत पास की तरह समझें:जब कोई आपकी सेवा का उपयोग करना चाहता है, तो उन्हें यह साबित करने के लिए यह "कुंजी" दिखानी होगी कि उन्हें इसमें अनुमति है। एपीआई कुंजी आपको यह नियंत्रित करने में मदद करती है कि आपके संसाधनों तक कौन पहुंच सकता है, और उनका उपयोग अक्सर उपयोग को ट्रैक करने, सीमाएं लागू करने या अनधिकृत पहुंच को रोकने के लिए किया जाता है। वे एपीआई एक्सेस को प्रबंधित करने और आपके डेटा को सुरक्षित रखने का एक सीधा तरीका हैं। हम क्या बनाएंगे
<पी> इस गाइड में, हम एक एपीआई कुंजी जनरेटर बनाएंगे जो दो मुख्य कार्यक्षमताएं प्रदान करता है: - कस्टम सेटिंग्स के साथ नई एपीआई कुंजी उत्पन्न करना
- अपने मेटाडेटा को पुनः प्राप्त करते समय एपीआई कुंजियों को मान्य करना
<पी> मुख्य विशेषताओं में शामिल होंगे: - अनुकूलन योग्य कुंजी उपसर्ग
- समाप्ति दिनांक
- दर सीमित करना
- मेटाडेटा भंडारण
- मालिक की पहचान
आइए हमारे एपीआई कुंजी सिस्टम की कल्पना करें
<पी> यह आरेख एपीआई कुंजी बनाने और मान्य करने दोनों के लिए क्लाइंट, हमारे क्लाउडफ्लेयर वर्कर और अपस्टैश रेडिस के बीच बातचीत को दर्शाता है। इस सिंहावलोकन को ध्यान में रखते हुए, आइए अपना सिस्टम बनाना शुरू करें। <पी>
आवश्यकताएँ
<पी> साथ चलने के लिए, आपको आवश्यकता होगी: - एक्लाउडफ्लेयर वर्कर्स खाता
- एक अपस्टैश खाता
- Node.js आपकी स्थानीय मशीन पर स्थापित है
प्रोजेक्ट संरचना
<पी> हमारे प्रोजेक्ट की संरचना निम्नलिखित होगी: 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:प्रोजेक्ट सेटअप
<पी> आइए अपना प्रोजेक्ट स्थापित करके और आवश्यक निर्भरताएँ स्थापित करके शुरुआत करें। एक नई प्रोजेक्ट निर्देशिका बनाएं
<पी> अपना टर्मिनल खोलें और निम्नलिखित कमांड चलाएँ: mkdir keyflow
cd keyflow
npm init -y
निर्भरताएं स्थापित करें
<पी> हमें अपने प्रोजेक्ट के लिए कुछ पैकेजों की आवश्यकता होगी: npm install hono @upstash/redis @upstash/ratelimit @hono/zod-validator zod wrangler
<पी> @upstash/redis :सर्वर रहित वातावरण के लिए अपस्टैश रेडिस क्लाइंट@upstash/ratelimit :अपस्टैश रेडिस@hono/zod-validator के लिए दर सीमित करने वाली लाइब्रेरी :होनोzod के लिए सत्यापन मिडलवेयर का अनुरोध करें :टाइपस्क्रिप्ट-प्रथम स्कीमा सत्यापन लाइब्रेरीwrangler :श्रमिकों के विकास और तैनाती के लिए क्लाउडफ्लेयर का सीएलआई अपस्टैश रेडिस सेट करें
- अपने अपस्टैश खाते में लॉग इन करें और एक नया रेडिस डेटाबेस बनाएं
<पी>
- एक बार बन जाने के बाद, "REST API" अनुभाग पर जाएँ
<पी>
UPSTASH_REDIS_REST_URL कॉपी करें और UPSTASH_REDIS_REST_TOKEN .env में अनुभाग
क्लाउडफ्लेयर वर्कर्स को कॉन्फ़िगर करें
<पी> एक 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" उन मानों के साथ जिन्हें आपने अपस्टैश से कॉपी किया है। चरण 2:एपीआई प्रकारों को परिभाषित करना
<पी> आइए हमारे एपीआई अनुरोधों और प्रतिक्रियाओं के लिए हमारे टाइपस्क्रिप्ट इंटरफेस को परिभाषित करके शुरुआत करें। ये प्रकार हमारे पूरे एप्लिकेशन में प्रकार की सुरक्षा बनाए रखने में हमारी सहायता करेंगे। एक नई फ़ाइल बनाएं 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:एपीआई कुंजी जनरेशन लागू करना
<पी> अब, आइए अपनी एपीआई कुंजी उत्पन्न करने के लिए एक उपयोगिता फ़ंक्शन बनाएं। एक नई फ़ाइल बनाएं 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;
}
<पी> यह फ़ंक्शन क्रिप्टोग्राफ़िक रूप से सुरक्षित यादृच्छिक बाइट्स का उपयोग करके एक यादृच्छिक एपीआई कुंजी उत्पन्न करता है, इसे बेस 64 में एन्कोड करता है, और इसे यूआरएल-सुरक्षित बनाता है। चरण 4:दर सीमित लागू करें
<पी> एक फ़ाइल 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:एपीआई रूट बनाना
<पी> आइए अपनी मुख्य एप्लिकेशन फ़ाइल सेट करें और अपना एपीआई रूट बनाएं। यह फ़ाइल हमारे होनो एप्लिकेशन को दो मुख्य मार्गों के साथ सेट करती है:/keys/create नई एपीआई कुंजी और /keys/verify उत्पन्न करने के लिए तीन अलग-अलग फ़ाइलों के साथ मौजूदा कुंजियों को मान्य करने के लिए। 1. एपीआई कुंजी रूट बनाएं लागू करें
<पी> एक फ़ाइल 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. एपीआई कुंजी रूट सत्यापित करें
लागू करें <पी> एक फ़ाइल 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. मुख्य फ़ाइल Index.ts
लागू करें <पी> मुख्य फ़ाइल src/index.ts लागू करें 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:परिनियोजन
<पी> अपने कीफ़्लो एप्लिकेशन को क्लाउडफ़ेयर वर्कर्स पर परिनियोजित करें: - <पी> रैंगलर स्थापित करें:
npm install -g wrangler
- <पी> Cloudflare से प्रमाणित करें:
wrangler login
- <पी> अपना कार्यकर्ता तैनात करें:
wrangler deploy
चरण 7:परिनियोजन
<पी> अब जबकि हमारा एप्लिकेशन तैयार है, आइए इसे क्लाउडफ्लेयर वर्कर्स पर तैनात करें: - <पी> सुनिश्चित करें कि आपके पास रैंगलर सीएलआई स्थापित है:
npm install -g wrangler
- <पी> अपने क्लाउडफ़ेयर खाते से प्रमाणित करें:
wrangler login
- <पी> अपना कार्यकर्ता तैनात करें:
wrangler deploy
चरण 8:अपने एपीआई का परीक्षण
<पी> आइए हमारी नई तैनात एपीआई का परीक्षण करें: एक नई एपीआई कुंजी बनाना
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"
}
}'
एपीआई कुंजी का सत्यापन
curl -X POST https://keyflow.<your-subdomain>.workers.dev/keys/verify \
-H "Content-Type: application/json" \
-d '{
"key": "prod_AbC123XyZ..."
}'
<पी> <your-subdomain> बदलें आपके Cloudflare Workers उपडोमेन और prod_AbC123XyZ... के साथ क्रिएट एंडपॉइंट से उत्पन्न वास्तविक कुंजी के साथ। निष्कर्ष
<पी> एपीआई कुंजी जनरेटर बनाना आपके एप्लिकेशन के एपीआई को सुरक्षित करने और यह प्रबंधित करने के लिए एक महत्वपूर्ण कदम है कि आपकी सेवाओं तक कौन पहुंच सकता है। एक ऐसी प्रणाली का निर्माण करके जो एपीआई कुंजी उत्पन्न, मान्य और प्रबंधित कर सकती है, आप एक्सेस नियंत्रण की एक मजबूत परत जोड़ते हैं जो आपके डेटा को सुरक्षित और व्यवस्थित रखने में मदद करती है। <पी> यहां एक ठोस एपीआई कुंजी जनरेटर में क्या होता है इसका एक त्वरित विवरण दिया गया है: - सुरक्षित कुंजी पीढ़ी :अद्वितीय, सुरक्षित कुंजियाँ जिनमें कस्टम उपसर्ग या सेट लंबाई जैसे विकल्प शामिल हैं, प्रत्येक कुंजी को विशिष्ट और अनुमान लगाना कठिन बनाते हैं।
- सत्यापन और समाप्ति :चेक और समाप्ति तिथियां जोड़ने से यह सुनिश्चित होता है कि प्रत्येक कुंजी केवल एक निर्धारित समय के लिए वैध है, जिससे आवश्यकतानुसार पहुंच को नियंत्रित करना और सीमित करना आसान हो जाता है।
- मेटाडेटा और दर सीमाएं :प्रत्येक कुंजी के साथ अतिरिक्त जानकारी संग्रहीत करने और दर सीमा निर्धारित करने से आप कुंजी के उपयोग की निगरानी कर सकते हैं, गतिविधि को ट्रैक कर सकते हैं और अपने एपीआई के किसी भी दुरुपयोग से बच सकते हैं।
<पी> अपस्टैश रेडिस और क्लाउडफ्लेयर वर्कर्स जैसे टूल का उपयोग करने से सर्वर रहित और विश्व स्तर पर वितरित कुंजी प्रबंधन प्रणाली बनाना आसान हो जाता है जो अच्छी तरह से स्केल करता है और कुशलता से काम करता है। <पी> इस आधार के साथ, आप अपने एपीआई तक पहुंच को सुरक्षित और प्रबंधनीय बनाए रखने के लिए तैयार हैं, जिससे आपको मानसिक शांति मिलेगी कि आपके संसाधन सुरक्षित हैं और उनकी निगरानी करना आसान है।