「ブラウザの戻る」ボタンや再読み込みなどの挙動不振を防ぐための策として
「POST送信+リダイレクト」にてカートの中身を表示させようと思っています。
キャッシュをオフにすれば、戻るボタンで戻っても、常に最新のカート内容が
表示される(昔の中身に戻らない)不便さがあると思いますが、ユーザが
昔の画面で再読み込みしたり違うボタンを押したりする予想外の行動を考えると
上記の設計がいいような気がするのですが、既存のカートでは検討中のやり方は
見たことがない気がします
既存のカート例:
リロードで商品個数がどんどん増えるカート
戻ってリロードすると、昔の中身が復活するカート
戻るボタンを口頭で禁止するサイト
などなど。
inputのhiddenで返される値と、サーバ上のセッション情報とを比べて、
最新画面からの操作であるかを判断する方法もあるかと思いますが、
当方検討中の方法で何か不都合があるのでしょうか。
http://php.s3.to/man/function.session-set-save-handler.html
session_set_save_handler
>inputのhiddenで返される値と、
>サーバ上のセッション情報とを比べて、
>最新画面からの操作であるかを判断する方法もあるかと思いますが、
>当方検討中の方法で何か不都合があるのでしょうか。
とのおたずねについて。
ブラウザのバグや経路途中のプロクシの無作法など、細々したトラブルの存在は無視できません。
「POST送信+リダイレクト」を採用する場合、隠しタグによるIDチェックは必須だと思います。
私なら、ページ単位での状態遷移ID(と必要なら処理時間)による新旧チェックはします。念のために。
もっとも、(リロードによるPOSTはともかく) 古い情報がPOSTされたときは警告ページに飛ばしたあと、最新のカート画面を表示(orリダイレクト)して知らん顔します。
御質問の方法にこだわらないなら、原則的には、2番目の回答者のお答えが正解だと思います。
その上で、どうしても「戻る」や「リロード」ページを意識した制御をするなら、ちょっとややこしい方法になりますし、予想外のトラブルが起こりうるのでお薦めもしませんが、以下のような方法もあることはあります。御参考までに。
(1) セッション管理自体はphpのセッションモジュールを使う
(2) それとは別に、画面の状態遷移に合わせたIDを発行して、これは隠しタグでHTMLに埋め込んでおく
(3) 商品が追加・削除されたら、(POSTされた)状態遷移IDと処理時間をチェックする。セッション変数に格納されている状態遷移IDの処理時間より、POSTされた処理時間が早いか同時なら、(古い情報なので)警告するなりエラー処理するなり最新ページを再表示するなりする。
(4) 上記をクリアしたら、商品ID+(POSTされた)状態遷移IDをキーに追加・削除数量と処理時間をセッション変数に格納する。このとき、新たな状態遷移IDを発行し、セッション変数に格納しておく。
(4) カードの表示画面にリダイレクトする。
(5) 商品表示ページでは、商品ID毎に数量を合算して表示する。このとき、新たな状態遷移IDをHTMLに埋め込んでおく。
以上、(状態遷移IDで識別される)どの画面で何をやったかについて、各々の最新情報のみを採用する方法です。
マトモにやると、セッション変数の領域が足りなくなるので、セッション変数自体をDB上に格納するなどの処置を取ってください(^^;
根本的な解決にはなってないように思えます。
例えばリダイレクト前の処理で遅延が発生する等危険性は残りますよね。プロセスそのものをセーフにする必要があると思います。多重ポストの回避 Tips は過去何度か雑誌等に載っていたので探せば出てくると思います。また Pukiwiki のように多重ポスト対策のついたオープンソースなアプリケーションから考え方を貰うという手もあると思います。実績もありますし説得力も出ると思います。
http://www.atmarkit.co.jp/fsecurity/rensai/webhole02/webhole01.h...
@IT:Webアプリケーションに潜むセキュリティホール(2) - Page1
「全削除の全追加が基本」だと、私はプログラムを最初学んだときに教わりました。今もそうしています。
特定の商品IDのものがカートに入るアクションがユーザーから起こされた場合ば、まずその商品IDのものをユーザーのカートから削除(sqlで言えばdelete)して、次にその商品IDのものをその個数だけ追加(sqlでinsert)しています。全削除の全追加です。
その商品IDのデータがカートに既に存在しているかに関係なく、とにかくカートに入れるというアクションが取られれば、まず、その商品IDとカートIDで削除します。もちろん、POSTされたデータがSQL Injectionされるものではないかなどはチェックしての話ですが・・・。
全削除の全追加であれば、ユーザーが何回リロードしても、戻るボタンを押して、個数を修正してPOSTしても、ユーザーの思っているような表示になると思います。
例えば商品画面のフォームで「2個追加」で送信すると、
「2個足す」処理ではなく、「2個にする」処理にするということでしょうか。
余談ですが、私の偏見では、戻るボタンで(たとえ中身はそのままでも)表示は古い過去
にさかのぼるより、キャッシュクリアして常に最新の中身を表示をさせたい主義です。
というのも、ユーザーが(リロードや追加のアクションなしに)ブラウザの「戻る」「戻る」で画面を戻ると、カート中身自体は変わっていない事実は、設計者からすれば
それは明白です。しかし、素人ユーザは、「戻る」=「中身を戻す」と勘違い
している人がいるんじゃないかと私は思っていまして、戻ったところで新たに
追加ボタンを押すとゼロから1個になると期待していたのに、残っている個数+1個になり、素人ユーザは面食らう‥‥のではないかと。
要するに、ブラウザの「戻る」ボタンで戻ったときの画面と、実際の中身が違うことが
私はどうも気に入らなくて。
話がはずれますが、はてなのログイン後、ブラウザ「戻る」で戻っても、
「ようこそゲストさん」には戻らずログイン名が表示され続けますよね。
カートとログイン名表示は違うでしょうけど。それと同じにしたい主義です。
皆さんはどう思っているのでしょうか。
http://jp2.php.net/manual/ja/ref.session.php
PHP: セッション - Manual
お望みのことはsessionを利用することで可能です。session.cache_limiterをうまく調整することで、戻るボタンを利用されても、常に最新の情報が表示されます。一度試してみてください。
以下、kyoko55さんのコメントへのコメントです。
>例えば商品画面のフォームで「2個追加」で>送信すると、
>「2個足す」処理ではなく、「2個にする」
>処理にするということでしょうか。
多分、意味するところは同じでしょうが、念のため、例を出して。
1.ユーザーが商品Aを2個注文しました。
2.個数を間違っていたので、1個に修正したい。戻るボタンで戻る
3.(セッションを使ってキャッシュ制御をしていない場合)ブラウザの表示上はカートの中身は空っぽです。
4.個数を1個に修正して再送信
5.好ましくないプログラムでは3個になります。でも、それを1個にする方法として、私は全削除の全追加という方法を説明しました。
ですから、
>追加ボタンを押すとゼロから1個になると
>期待していたのに、残っている個数+1個
>になり、素人ユーザは面食らう‥‥ので
>はないかと
には同意します。このような作り方はするべきではないと思います。
ただし、「3」の画面で、キャッシュをそのまま見せるのか、キャッシュ制御で常に最新の情報を見せるかは、作り手の考え方しだいだと思います。
※ログインユーザー名のキャッシュが残っていたりするのは、場合によっては好ましくないでしょう。インターネットバンキングなどでは、大問題になりますから、当然、セッション管理によって制御していますね。
session.cache_limiterはセッション(クッキー)の保存期間だと
勘違いしていたのですが、HTTPヘッダのキャッシュの制御なんですね。
今までheader(”Pragma: no-cache”);等で制御していたんですけど、
どのみちsession関数を使うなら、session_cache_limiterで制御した方が無難
みたいですね。
> ただし、「3」の画面で、キャッシュをそのまま見せるのか、キャッシュ
> 制御で常に最新の情報を見せるかは、作り手の考え方しだいだと思います。
おっしゃる通りです。実はカートを最新表示にすることがユーザの使い勝手
が本当にいいのかどうか、ちょっと迷っています。
また、当方は色々なPC・ブラウザで動作確認していないため、
キャッシュ関係やリダイレクト関係でうまく動かないブラウザがあるのかなど
憂慮しています。
> インターネットバンキングなどでは、大問題になりますから
某銀行サイトのネット振込みをよく利用しますが、セキュリティー面というか
動作の面で設計ポリシーが凄いと関心します。ブラウザで戻るボタンを押した
だけで、振込み画面から強制ログアウトでログイン前に戻された経験があった
と記憶してます。
http://d.hatena.ne.jp/agt/20040830
2004-08-30 - アガテナ
不都合はないと思うんですが、案外使われてなくて自分も不思議に思ってました。
ポイントはいいです。
http://www.theserverside.com/articles/article.tss?l=RedirectAfte...
Enterprise Java Community: Redirect After Post
ブラウザによっては不都合があるみたいですね。でも普通URLかえるから問題はないと思うんだけど。
「POST送信+リダイレクト」は再読込みの影響を受けないやり方を練って
自分で考え付いたやり方だったんですが、
手法として紹介されているのを見て、安心しました。
ブラウザの違いによる不都合が気になりますので、URLは参考になります。
遅延とは、全く考えが及んでいませんでした。
遅延の意味は、リダイレクト先で処理を行う段階では未だ、リダイレクト前の処理が
完結していない可能性があるという意味でしょうか?
それともデータファイルのロック等で、待ち時間が生じるだけのことでしょうか?
考えたのは、POSTデータによりセッション変数のカート情報を更新し、リダイレクト先
でセッション変数を元にDBから商品情報をSELECTしてブラウザへカート中身を表示、という具合です。
とりあえずセッション関数デフォルト(ブラウザを閉じるとセッション終了)の単純な設計です。
セッション変数に値を入れると、PHPがどうやってサーバに保存しているのか、よく知らないのですが。。
この場合も遅延の問題をやはり考慮しなければならないでしょうか。
何か的外れなことを言っていたらご指摘いただきたいです。