// サポートされるテキストファイルタイプconst textFileTypes = ['application/javascript','text/html; charset=utf-8','text/css; charset=utf-8','text/xml; charset=utf-8'];// サポートされる画像ファイルタイプconst imageFileTypes = ['image/jpeg'];function uint8ArrayToHex(arr) {return Array.prototype.map.call(arr, (x) => (('0' + x.toString(16)).slice(-2))).join('');}/*** ここのアルゴリズムは、MD5、SHA-1、SHA-256、SHA-384、SHA-512のいずれかをサポートしており、大文字と小文字は区別されません。* 注意が必要です:ここでオリジンサーバーが署名を計算する際、ソースファイルのデータに直接署名するのではなく、難読化データを追加して、外部攻撃者による解読を防ぐ必要があります。* その後、ここでも同じ方法で計算・比較を行い、改ざん防止の目的を達成します。**/async function checkAndResponse(response, hash, algorithm) {const headers = response.headers;let checkHash = 'sorry! not match';let data = null;const contentType = headers.get('Content-Type');if (textFileTypes.includes(contentType) || imageFileTypes.includes(contentType)) {data = await response.arrayBuffer();}let ret = await crypto.subtle.digest({name: algorithm}, data);checkHash = uint8ArrayToHex(new Uint8Array(ret));headers.append(`X-Content-${algorithm}-Check`, checkHash);// リアルタイムで署名を計算し、オリジンサーバーの署名と比較します。検証に失敗した場合は416を返し、その意味はユーザーのリクエストを満たせないことです。if (checkHash !== hash) {return new Response(null, {headers,status: 416});}return new Response(data, {headers,status: 200});}async function handleEvent(event) {// オリジンサーバーから返されたコンテンツを取得します。EdgeOneノードにキャッシュが存在する場合、オリジンサーバーへのアクセスは行われません。const response = await fetch(event.request);if (response.status === 200) {const headers = response.headers;// オリジンサーバーコンテンツ署名ヘッダーconst hash = headers.get('X-Content-Sha256');if (hash) {// 署名が一致するかどうかを計算します。ここのアルゴリズムは、MD5、SHA-1、SHA-256、SHA-384、SHA-512をサポートしており、大文字と小文字は区別されません。return checkAndResponse(response, hash, 'Sha-256');}}return response;}addEventListener('fetch', event => {event.respondWith(handleEvent(event));});


フィードバック