Upstash Redis と Cloudflare Workers を使用して安全な API キーを作成する:ステップバイステップ ガイド
API キーはサービスへの玄関の鍵のようなもので、安全な状態を保ちながらユーザーをアクセスさせます。このブログでは、高速なサーバーレスデータストレージとして Upstash Redis を使用し、エッジでリクエストを処理するために Cloudflare Workers を使用して、シンプルで安全な API キージェネレーターを構築する方法を説明します。新しいサービスを設定する場合でも、既存のアプリにキーを追加する場合でも、すべてをスムーズかつ効率的に実行し続けるために API キーを生成、保存、検証する方法を学びます。
API キーとは何ですか?
API キーは、API にアクセスしようとするユーザーまたはアプリケーションを識別および認証する一意のコードです。これは個人パスのようなものだと考えてください。誰かがあなたのサービスを使用したいとき、その人がアクセスを許可されていることを証明するためにこの「キー」を提示する必要があります。API キーは、リソースにアクセスできるユーザーを制御するのに役立ち、使用状況の追跡、制限の強制、または不正アクセスの防止によく使用されます。 API アクセスを管理し、データを安全に保つための簡単な方法です。
何を構築するか
このガイドでは、次の 2 つのコア機能を提供する API キー ジェネレーターを作成します。
<オル>主な機能は次のとおりです。
- カスタマイズ可能なキープレフィックス
- 有効期限
- レート制限
- メタデータ ストレージ
- 所有者の身元確認
API キー システムを視覚化してみましょう
この図は、API キーの作成と検証の両方を行う、クライアント、Cloudflare Worker、および Upstash Redis の間の対話を示しています。この概要を念頭に置いて、システムの構築を始めましょう。

前提条件
この手順を進めるには、次のものが必要です。
- Cloudflare ワーカー アカウント
- アップスタッシュ アカウント
- ローカル マシンにインストールされている 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 Redis クライアント@upstash/ratelimit :Upstash Redis@hono/zod-validator のレート制限ライブラリ :Honozod のリクエスト検証ミドルウェア :TypeScript ファーストのスキーマ検証ライブラリwrangler :Workers の開発と展開のための Cloudflare の CLI
Upstash Redis をセットアップする
<オル>


UPSTASH_REDIS_REST_URL をコピーします。 と UPSTASH_REDIS_REST_TOKEN .env 内 セクションCloudflare ワーカーを構成する
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 タイプの定義
API リクエストとレスポンス用の TypeScript インターフェイスを定義することから始めましょう。これらの型は、アプリケーション全体で型の安全性を維持するのに役立ちます。新しいファイル 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 キー生成の実装
次に、API キーを生成するユーティリティ関数を作成しましょう。新しいファイル 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 キーを生成し、base64 でエンコードして、URL セーフにします。
ステップ 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:API ルートの作成
メイン アプリケーション ファイルを設定し、API ルートを作成しましょう。このファイルは、2 つのメイン ルートを使用して Hono アプリケーションを設定します:/keys/create 新しい API キーと /keys/verify を生成するため 3 つの個別のファイルを使用して既存のキーを検証します。
1. API キー作成ルートの実装
ファイル 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. API キー ルートの検証を実装する
ファイル 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:導入
Keyflow アプリケーションを Cloudflare Workers にデプロイします。
<オル>Wrangler をインストールします:
npm install -g wrangler Cloudflare で認証します:
wrangler login ワーカーをデプロイします:
wrangler deploy ステップ 7:導入
アプリケーションの準備ができたので、Cloudflare Workers にデプロイしましょう。
<オル>Wrangler CLI がインストールされていることを確認してください。
npm install -g wrangler
Cloudflare アカウントで認証します:
wrangler login
ワーカーをデプロイします:
wrangler deploy
ステップ 8:API をテストする
新しくデプロイした API をテストしてみましょう:
新しい API キーの作成
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 キーの確認
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... を使用します。 作成エンドポイントから生成された実際のキーを使用します。
結論
API キー ジェネレーターの作成は、アプリケーションの API を保護し、サービスにアクセスできるユーザーを管理するための重要な手順です。 API キーを生成、検証、管理できるシステムを構築することで、データを安全かつ整理された状態に保つための強力なアクセス制御層を追加できます。
ここでは、堅牢な API キー ジェネレーターの内容を簡単にまとめます。
<オル>Upstash Redis や Cloudflare Workers などのツールを使用すると、拡張性が高く効率的に動作する、サーバーレスでグローバルに分散された鍵管理システムを簡単に構築できます。
この基盤により、API へのアクセスを安全かつ管理しやすくするように設定され、リソースが保護され、監視が容易になるという安心感を得ることができます。
-
Redis HGETALL –ハッシュ値に含まれるすべてのフィールド/値のペアを取得する方法
このチュートリアルでは、キーに格納されているハッシュ値に含まれるすべてのフィールドと値のペアを取得する方法について学習します。このために、Redis HGETALLを使用します コマンド。 HGETALLコマンド このコマンドは、キーに格納されているハッシュ値に含まれるすべてのフィールドとそれに関連する値を返します。キーが存在しない場合は空のリストが返され、キーは存在するがキーに格納されている値がハッシュデータ型ではない場合はエラーが返されます。 RedisHGETALLコマンドの構文は次のとおりです。- 構文:- redis host:post> HGETALL <ke
-
Upstash Redis Python SDK v1.0.0 の紹介 – コネクションレス、サーバーレス対応クライアント
本日、v1.0.0 をリリースします。 upstash-redis のバージョン Pythonのパッケージ。現在、GitHub と PyPi で利用可能です。 このパッケージは、Upstash Redis 用のコネクションレス型 HTTP ベースのクライアントで、AWS Lambda、Google Cloud Functions などのサーバーレス環境、または TCP よりも HTTP が優先される環境で使用できるように設計されています。 新機能は何ですか? 新しいバージョンでは、パッケージには各コマンドの使用例を含む Python docstring が付属しています。 また、up