採番したUniqueIdをHtmlに含めてはいけない
先日レガシーシステムでトラブルにぶつかったので。
TL;DR
- Safariなど一部のブラウザはキャッシュがやたら強いので、採番した一意IDをHTML上の要素として渡すと過去に採番したものを持ってきてしまう可能性がある
- クエリパラメータでキャッシュの利用を抑制したり、jsで取得するなどcacheに影響されない工夫が必要
遭遇した事象
phpを利用した申し込みシステムにおいて、毎回新規に採番されるはずのtokenが重複した場合にのみ発生するエラーがたまに発生していました。
tokenはランダム32桁の文字列+生成時刻のエポックミリ秒のため、重複することはほぼあり得ません。
tokenの出所
token自体は申し込み画面に入るタイミングでサーバーサイドで採番され、
Html上のhiddenなinputとしてブラウザ側に渡されていました。
ヘッダにno cacheはついているので、基本的に毎回新たに採番されます。
戻るボタンではない
当初は戻るボタン関連の問題かと思ったのですが、
ログに出てきたエラー時のtokenの日付を見る限り、採番後数日経ってからエラーが発生したケースもありました。
単純に申し込み後に戻ってもう一度押してしまったわけではなさそうです。
ブラウザに依存している
基本的に問題が発生しているのはiphoneのSafari。
ただし、常に発生しているわけではない。
原因
iphoneのsafariで2回目の申し込みをした場合、
1回目の申し込みのキャッシュが残っており同一番号で重複申請してしまっていた。
iphoneのSafariのcache機構はやたらと強力で、
Headerにちょっとno cacheを加えたくらいではcacheから読み込んでくるようです。
参考:
https://www.ituki-yu2.net/entry/iPhone_no_cache
対応
レガシーシステムで仕様が不明確だったので、一旦遷移時にクエリパラメータを付けて無理やりキャッシュを利用しないように対応しました。
ただ、本来はキャッシュされる可能性のある部分を使って一意識別子を渡すこと自体を本来は避けるべきです。