NAV_MENU
賽は投げられた。人事尽くして天命待つと言うか、転がりだした物は止められないというか。まぁ、ちょとは覚悟しとけよ。
基本的に毎日更新。出来なかったときは遡ってやります。多分。きっと。出来たら良いな

nginx のsecure_linkを使ってみる

セキュアリンクは一時的に有効なURLを生成して、時間が来るとURLそのものを無効することができる便利な機能なんだけど
Module ngx_http_secure_link_module

基本的にここに書いてある通り。

日本語(等のマルチバイトとか非ASCII)がURLに含むときはハッシュ生成前にデコードしておかないとハマる…

nginx側の変数$uriは正規化されるのが問題を起こしているので
正規化されない$request_uriからquerystring切り離してみたら %は%25にエンコードされて %2520 とかになる始末…
正規化されないrequest_fileみたいな変数があると迷わないんだけどな

nginx.conf

location /secure/ {
# シークレットキーを設定
set $secretkey 'secretsecretsecretsecret';
# MD5ハッシュと有効期限を認証情報として設定
# -- URLクエリ hash={md5_hash} , expires={epoch_time} をそれぞれ設定しています。
secure_link $arg_hash,$arg_expires;
# ハッシュ値計算用の元データ、クエリパラメタも制限する場合はそれもここに含める
secure_link_md5 $secretkey$uri$arg_expires;

# MD5ハッシュが不一致なら $secure_link は''値の設定(未設定ともいう)
if ($secure_link = "") {
return 403;
}
# MD5ハッシュが一致するが、有効期限切れの場合 $secure_link は0が設定される
if ($secure_link = "0") {
return 403;
}

#ここには、実際の処理内容 proxy_passとか、もろもろ…

}


makeURL.php

$url = '/secure/%E6%97%A5%E6%9C%AC%E8%AA%9E/text.txt'; // URLエンコードされたものを渡す
$expires=time()+3600; // 発効から1時間有効なリンクを生成
$secretkey='secretsecretsecretsecret'; // nginx側で設定した シークレットキー

// nginx側で設定した secure_link_md5 と同じ平文を与える事。クエリパラメタも制限する場合はそれもここに含める
// URLにURLエンコードが含まれる場合は、nginx側で正規化時にデコードされるので、先にデコードしておく
$regulerURL=str_replace(array('%2f','%2F'),'/',$url);
$hashBase=$secretkey.$regulerURL.$expires;

// MD5でハッシュ化&base64URLエンコード
$hash=strtr(rtrim(base64_encode(hash('md5',$hashBase,1)),'='), '+/', '-_');

echo $url.'?hash='.$hash.'&expires='.$expires;