Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

Vercel Edge 機能と Upstash Redis による安全で低遅延のフィルタリングでデータ漏洩を防止

データ漏洩はインターネット上の大きな問題です。 Statista によると、2022 年だけで 4 億人以上がデータ漏洩の影響を受けました。自分のデータがインターネット上に漏洩することを誰も望んでいません。そのため、ユーザーのプライバシーを尊重する安全なアプリケーションを構築することは、多くの業界で非常に重要です。

漏洩に対抗する 1 つの方法は、問題のあるデータを他のサービスやユーザーに配信する前にフィルタリングすることです。この方法では、データがすり抜けないようにするための最新のフィルタと、フィルタリングによるパフォーマンスへの影響を最小限に抑えるための低レイテンシのインフラストラクチャが必要です。

Upstash for Redis® と Vercel Edge Functions は、両方の要件を磨きながら問題に取り組むことができる強力なチームを形成しています。これらの低遅延サーバーレス ソリューションは両方とも、ユーザーの近くに導入できます。 Vercel の新しい cron 機能を使用すると、フィルタ データを定期的に更新できます。

このようなフィルターがどのように機能するかを説明するために、このサーバーレス エッジ テクノロジーを利用して冒とく的な表現をフィルターするフロントエンドとバックエンドを構築します。

機能

アプリは Vercel の cron 機能を使用して、リモート API からの現在の単語で Upstash for Redis データベースを更新します。

データを取得するには 3 つの手段があります。

<オル>
  • フィルタリングされたテキストを含むウェブサイトを返します。
  • データ ストアからフィルタリングされたテキストを含む JSON を返します。
  • テキストを受け入れ、フィルタリングされたテキストを含む JSON を返します。
  • テクノロジー

    Next.js を使用してアプリを構築し、Vercel にデプロイします。このようにして、エッジ機能を使用するときにシームレスなサーバーレス開発エクスペリエンスを実現できます。

    レイテンシーが低く使いやすい Upstash for Redis® をデータ ストレージとして使用します。

    どちらのサービスにも無料枠があり、オンデマンド料金が適用されます。

    前提条件

    サービス用のアカウントが必要です:

    • Vercel がコードをダウンロードしてデプロイできるように、GitHub にコードをアップロードします
    • Vercel がホームページとエッジ機能を備えたアプリケーションをホストします
    • フィルタリングしたい単語のリストを保存するためにアップロードします

    実装

    まず、新しい GitHub リポジトリを作成して確認します。 「README ファイルを追加する」にチェックを入れているので、空ではありません。リポジトリは空ではないため、GitHub を使用してコードスペースを開始できます。これには、Node.js と Git 間接続が事前に設定されています。

    Vercel Edge 機能と Upstash Redis による安全で低遅延のフィルタリングでデータ漏洩を防止 図 1:コードスペースの開始

    まず、新しい Next.js プロジェクトを作成し、次のコマンドを使用して Upstash Redis クライアントをインストールする必要があります。

    $ npx create-next-app@latest --typescript
    $ npm i @upstash/redis

    リフレッシュ機能の実装

    実装する最初の機能は、悪い言葉のリストを更新する機能です。これを行うには、pages/api/refresh-list.ts に新しいファイルを作成します。 次の内容:

    ファイルpages/api/refresh-list.ts :

    import { Redis } from "@upstash/redis";
     
    export const config = { runtime: "edge" };
     
    const redisClient = new Redis({
     url: process.env.UPSTASH_REDIS_URL,
     token: process.env.UPSTASH_REDIS_TOKEN,
    });
     
    export default async function handler() {
     const wordResponse = await fetch(
     "https://raw.githubusercontent.com/kay-is/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/en",
     );
     const words = await wordResponse.text();
     
     const redisCommands = redisClient.pipeline();
     words
     .trim()
     .split("\n")
     .forEach((word) => redisCommands.sadd("words", word));
     await redisCommands.exec();
    }

    まず、エッジで実行されるように関数を構成します。この関数はバックグラウンドで実行されるため、ここでは必須ではありませんが、Vercel Edge Functions は Cloudflare Workers を利用しており、Node.js がネイティブにサポートしていないフェッチ メソッドを使用できるようになります。

    ハンドラーは、不適切な単語を含むテキスト ファイルを Upstash Redis にロードします。パイプライン機能により、すべての Redis コマンドで 1 つのリクエストのみが送信されることが保証されます。

    単語を保存するためにセットを使用するため、重複は発生しません。また、後で 1 つのコマンドですべての単語を文字列の配列としてロードすることもできます。

    個人データをフィルタリングしたい場合は、アカウント データベースを使用して、フィルタの基礎としてユーザーの電子メール、電話番号、名前、住所を取得できます。

    この関数を cron 関数にするように Vercel に指示するには、次の内容を含む vercel.json ファイルをプロジェクト ルートに作成する必要があります。

    ファイル vercel.json :

    {
     "crons": [
     {
     "path": "/api/refresh-list",
     "schedule": "0 10 * * *"
     }
     ]
    }

    この設定により、Vercel は毎日 10:00 UTC にリフレッシュリスト関数を実行します。

    無料の Vercel アカウントでは、1 日に 1 回の自動実行のみがサポートされます。この例ではこれで十分ですが、より頻繁に変更されるデータがある場合は、更新レートを上げる必要があります。

    フィルタ ユーティリティの実装

    次の機能は、テキスト内の単語がデータベース内の単語に一致する場合にマスクするユーティリティ関数です。 utils/word-filter.ts に新しいファイルを作成し、次のコードを追加します。

    ファイルutils/word-filter.ts :

    import { Redis } from "@upstash/redis";
     
    const redisClient = new Redis({
     url: process.env.UPSTASH_REDIS_URL,
     token: process.env.UPSTASH_REDIS_TOKEN,
    });
     
    export async function filter(text: string) {
     const filteredWords = await redisClient.smembers("words");
     
     let maskedText = text;
     for (let word of filteredWords)
     maskedText = maskedText.replaceAll(new RegExp(word, "gi"), "[REDACTED]");
     
     return maskedText;
    }

    繰り返しますが、この関数は Upstash Redis クライアントを使用しますが、今回は以前に保存したデータをロードします。

    文字列の配列を取得したので、それをループして、テキスト内のすべての不適切な単語を「[編集済み]」に置き換える置換関数を呼び出すことができます。

    この関数は、フィルターで除外する単語の種類を気にしません。この場合、その言葉は「作業には安全ではありません」ですが、フィルタ プロセスは以前に保存したデータにのみ依存します。

    ホームページの実装

    フィルターの動作を確認するには、pages/index.ts の内容を置き換えてみましょう。 以下のようにします。

    ファイルpages/index.ts :

    import Head from "next/head";
    import { filter } from "@/utils/word-filter";
     
    export const config = { runtime: "experimental-edge" };
     
    interface HomeProps {
     maskedText: string;
    }
     
    export default function Home(props: HomeProps) {
     return (
     <>
     <Head>
     <title>Text with Filtered Words</title>
     </Head>
     <div>
     <h1>Text with Filtered Words</h1>
     <p>{props.maskedText}</p>
     </div>
     </>
     );
    }
     
    export async function getServerSideProps(): Promise<{ props: HomeProps }> {
     const maskedText = await filter(
     "He slipped and fell on his butt. Well, that wasn't very sexy."
     );
     return { props: { maskedText } };
    }

    この構成により、サーバー側のレンダリングも含め、すべてがエッジで実行されるようになります。この Vercel 機能はまだ実験段階です。

    興味深い部分は getServerSideProps です。 filter を使用する関数 静的テキストに対する以前の関数。これはサーバー上でのみ呼び出されるため、フィルタリングされていないデータがクライアントに到達することはありません。

    実際のアプリケーションでは、このテキストは、表示する前にクリーンアップする必要がある個人データを含むデータベースから取得される可能性があります。

    最初の API ルートの実装

    最初の API ルートはホームページのように機能します。 JSON が返され、HTML は返されません。 pages/api/filtered-data.ts にファイルを作成します このコードを使用すると:

    ファイルpages/api/filtered-data.ts :

    import { filter } from "@/utils/word-filter";
     
    export const config = { runtime: "edge" };
     
    export default async function handler() {
     const maskedText = await filter(
     "He slipped and fell on his butt. Well, that wasn't very sexy.",
     );
     
     return new Response(JSON.stringify({ text: maskedText }), {
     status: 200,
     headers: { "content-type": "application/json" },
     });
    }

    繰り返しますが、ランタイムはエッジであり、getServerSideProps 関数の場合と同様に、静的テキストを使用します。

    2 番目の API ルートの実装

    このルートはリクエスト経由でテキストを受け取り、フィルターされたバージョンを返します。 pages/api/filter.ts に新しいファイルを作成します 次のコードを追加します。

    ファイルpages/api/filter.ts :

    import type { NextApiRequest } from "next";
     
    import { filter } from "@/utils/word-filter";
     
    export const config = { runtime: "edge" };
     
    export default async function handler(request: NextApiRequest) {
     const { text } = await new Response(request.body).json();
     const maskedText = await filter(text);
     return new Response(JSON.stringify({ text: maskedText }), {
     status: 200,
     headers: { "content-type": "application/json" },
     });
    }

    今回は、フィルタリングするテキストを取得するために本文を解析する必要があります。 Vercel の Edge 関数では、body ReadableStream です;それを Response に変換すると 、ネイティブ JSON パーサーを使用してデータを抽出できます。

    リクエストからデータを取得した後は、すべてが以前と同様に機能します。

    プッシュコードの変更

    すべてが実装されたので、次のコマンドを使用してコードを GitHub リポジトリにプッシュする必要があります。

    $ git add -A
    $ git commit -m "Init"
    $ git push

    この後、Vercel がコードをオンラインでダウンロードしてデプロイできるようになります。

    展開

    環境変数と Vercel プロジェクトの認証情報を取得するには、Upstash Redis データベースを作成する必要があります。

    Redis データベースの作成

    「データベースの作成」ボタンをクリックすると、Upstash コンソールで新しい Redis データベースを作成できます。図 2 に構成を示します。この例では、地域データベースで十分ですが、ユーザーが世界的に分散しており、レイテンシーを低く抑えたい場合は、グローバル タイプを選択することもできます。

    Vercel Edge 機能と Upstash Redis による安全で低遅延のフィルタリングでデータ漏洩を防止

    図 2:新しいデータベースを作成する

    作成後、REST API カテゴリで環境変数に必要な URL とトークンを見つけることができます。図 3 のようになります。

    Vercel Edge 機能と Upstash Redis による安全で低遅延のフィルタリングでデータ漏洩を防止

    図 3:データベース認証情報

    Vercel プロジェクトの作成

    新しい Vercel プロジェクトを作成するには、ブラウザで Vercel ダッシュボードを開き、中央にある [新しいプロジェクトの作成] をクリックします。 Vercel を GitHub アカウントに接続したら、インポートするリポジトリを選択できます。

    デフォルト構成を保持し、上記の Upstash Redis 認証情報を使用して環境変数を追加できます。図 4 は、参考のために Vercel の作成 UI を示しています。

    Vercel Edge 機能と Upstash Redis による安全で低遅延のフィルタリングでデータ漏洩を防止

    図 4:Vercel プロジェクトの作成

    環境変数の名前は UPSTASH_REDIS_URL です。 と UPSTASH_REDIS_TOKEN 。前のステップの値を使用して作成します。

    [デプロイ] をクリックすると、Vercel は GitHub リポジトリからコードをダウンロードしてデプロイします。

    アプリのテスト

    デプロイ後も、cron ジョブがまだ実行されていないため、アプリにはフィルターされていない単語が表示され続けます。ただし、最初の実行は手動で行うことができます。 [ダッシュボードに進む] ボタンをクリックし、[Cron ジョブ] タブを選択します。

    ここでは /api/refresh-list を示します。 [実行] ボタンをクリックして関数を実行します。

    関数が終了したら、[プロジェクト] タブに移動し、[ドメイン] の下にある URL の 1 つをクリックします。これにより、ブラウザーでフィルタリングされたテキストを含む Web サイトが開きます。図 5 のようになります。

    Vercel Edge 機能と Upstash Redis による安全で低遅延のフィルタリングでデータ漏洩を防止 図 5:フィルタリングされた Web サイト

    /api/filtered-data を追加すると URL にアクセスすると、これが API 応答にも機能することがわかります。これらは次の例のようになります。

    {
     "text": "He slipped and fell on his [REDACTED]. Well, that wasn't very [REDACTED]y."
    }

    最後に、cURL 経由で /api/filter にリクエストを送信すると、 エンドポイントで、カスタム テキストがフィルタリングされます。 &lt;PROJECT> を必ず置き換えてください。 Vercel プロジェクトに追加します。

    $ curl -X POST https://<PROJECT>.vercel.app/api/filter \
     -H "Content-Type: application/json" \
     -d '{"text":"He fell on his butt."}'
    

    応答:

    {
     "text": "He fell on his [REDACTED]."
    }

    次は何ですか

    After this tutorial, you might ask yourself what happens if the data is updated, but the cron job hasn't updated the database.良い観察ですね!

    A cron job triggers our refresh function, but it's still a regular API function, so we can call it however we want.

    実際のデータ フィルターの場合、データの変更に応じて関数をトリガーしたい場合がありますが、実装の詳細はフィルターのベースとして使用するデータ ストレージに大きく依存します。したがって、構築するときはそのことに留意してください。

    追加リソース

    完全なプロジェクトは GitHub で見つけることができます。


    1. Node.js と Redis 分散キャッシュを使用して高性能 URL 短縮ツールを構築する

      このチュートリアルでは、Node.js と Redis を使用してスケーラブルな URL 短縮サービスを構築します。このサービスは分散キャッシュを活用して、高トラフィックを効率的に処理し、遅延を削減し、シームレスに拡張します。システムの高速性と信頼性を確保するために、一貫性のあるハッシュ、キャッシュ無効化戦略、シャーディングなどの主要な概念について説明します。 このガイドを完了すると、分散キャッシュを使用してパフォーマンスを最適化する、完全に機能する URL 短縮サービスが完成します。また、ユーザーが URL を入力して、キャッシュのヒットやミスなどのリアルタイムの指標を確認できるインタラク

    2. 地理ベースのコンテンツ コントロール用の Next.js ミドルウェアでのエッジ フラグの実装

      Edge-Flags を使用すると、サーバーレス アプリケーションの機能フラグを簡単に管理できます。これは、強力な地理位置情報ルールを備えた Upstash Redis の上に構築されています。今日は、Next.js ミドルウェアで Edge-Flags を使用して、ユーザーの位置に基づいてリクエストを書き換える方法の非常に簡単な例を示します。 フラグを作成する このサンプル アプリでは、EU 内のユーザーのみがコンテンツを利用できるようにしたいため、新しい Redis データベースを作成して、エッジ フラグ ページに移動します。作成したデータベースと production を選択します。