目的
- URLにユーザーごとのパラメータを埋め込んで公開したい
- Twitterなどに投稿されたとき、パラメータが改ざんされているかをチェックしたい
- 改ざん検知のために、DBなどの仕組みを使用したくない
- (単純に、パラメータが書き換えられていないかのチェックでよい)
使用例
上記の目的がわかりにくいと思うので、実例を説明します。
三点リーダー症候群チェッカーというWebサービスを作りました。
自分の過去のツイートに、どのくらい三点リーダー(…)が使用されているかを表示できます。
Twitterへのシェア機能が実装されており、自分の分析結果を動的OGP画像として共有できます。
ユーザーごとのシェアURL:https://santen-leader.nankakaku.com/share/Misa_Fd/32/169/FX174A
シェアURLは、以下のような構成をしています。
/share/{ユーザー名}/{スコア分子}/{スコア分母}/{ハッシュ値}
もしパラメータに改ざんを検出した場合は、デフォルトのOGP画像が表示されます。
改ざんされたシェアURL:https://santen-leader.nankakaku.com/share/Misa_Fd/100/169/FX174A
このユーザ名・スコア分子・スコア分母の値を使用して動的OGP画像を作成しますが、
改ざん検出の仕組みを入れないと、ユーザーが自分のスコアを偽装できてしまいます。
分析結果をサーバに保存していないため、実際のデータと比較することもできません。
そのため、末尾にハッシュ値を付加して対策しています。
実装概要
大まかには、以下のような仕組みを採用しています。
**URL作成時:**シェアURL生成時に、「ユーザ名」「スコア分子」「スコア分母」「ハッシュ化文字列」を使用してハッシュ値を生成する
改ざんチェック時:「ユーザ名」「スコア分子」「スコア分母」「ハッシュ値」が改ざんされていないか、「ハッシュ化文字列」を使用して検証する
実装詳細
URL生成時
下記ような関数を使用して、パラメータからハッシュを作成しています。
public static function generateShortHash($screenName, $matchCount, $totalCount, $algo = 'CRC32') {
$hashSource = $screenName . "/" . $matchCount . "/" . $totalCount . "/STRING_FOR_HASHING";
return strtr(rtrim(base64_encode(pack('H*', hash($algo, $hashSource))), '='), '+/', '-_');
}
短いハッシュを作成するための方法は、下記の記事を参考にさせていただきました。ありがとうございました。
https://qiita.com/koriym/items/efc1c419e4b7772b65c0
改ざんチェック時
上記の関数を用いて、送信されたハッシュ値が一致するかを検証しています。
一致する場合は動的OGP画像を生成し、一致しない場合はデフォルトの静的OGP画像を、シェアURLのOGP画像に指定しています。