プロジェクト

全般

プロフィール

Bug(バグ) #3150

メンバー登録時にデータが不正な状態になることがある

Kiwa Sakai11年以上前に追加. 約6年前に更新.

ステータス:
Fixed(完了)
優先度:
High(高め)
担当者:
対象バージョン:
開始日:
2012-08-07
期日:
進捗率:

100%

3.6 で発生するか:
Yes (はい)
3.8 で発生するか:
Yes (はい)

説明

現象

OpenPNEでは認証機構が複数持てるようになっており、この関係でメンバー登録時には

1. メンバー情報の登録
2. 汎用的なアカウントの有効化

という2つの処理を行なっています。

PCのメールアドレスで認証を行う設定の場合は、1においてフォームからの情報入力が行われます。

2のアカウントの有効化処理は汎用処理となっており、1の処理が不要であったり、外部Webサービスと連携のためにフォーム入力不要となるような運用形態においても利用できるような設計となっております。

ただし、ブラウザからの2重フォーム送信やネットワークの状態等、サーバーの外部の要因によってデータが不正な状態になってしまいます。

具体的な現象の例として、 opAuthMailAddressPlugin を利用していて、プロフィール登録時にsubmitボタンを複数回押下すると、 is_active=0 のメンバーが作成されてしまうことがあります。

原因

member/registerInput のフォームで「新規登録」ボタンを複数回クリックした場合に、POST /member/registerInput のリクエストが重複して行われる事で 2 回目以降のリクエストが 404 エラーとなることによるもの。
これにより、本来は最初の POST /member/registerInput のリクエストで opAuthMailAddress/registerEnd にリダイレクトされるべき所が、ブラウザ上では 2 回目以降にレスポンスとして返ってきた 404 エラーの表示のまま止まってしまい、登録が完了しない。
/opAuthMailAddress/registerEnd/token/... の URL を手動で入力して表示すると続行できる)

修正内容

member/registerInput の「新規登録」ボタンを複数回クリックできないように JavaScript で二重送信を抑制する。

regist-404.png 表示 (29.1 KB) Shinichi Urabe, 2017-06-05 15:38


関連するチケット

関連している OpenPNE 3 - Backport(バックポート) #3184: メンバー登録時にデータが不正な状態になることがある Fixed(完了) 2012-08-07
関連している OpenPNE 3 - Backport(バックポート) #3186: メンバー登録時にデータが不正な状態になることがある Fixed(完了) 2012-08-07
関連している opAuthMailAddressPlugin - Bug(バグ) #3187: メンバー登録時にデータが不正な状態になった場合のメッセージ表示が適切でない Won't fix(対応せず) 2012-08-29

関係しているリビジョン

リビジョン 4bc8a1ee (差分)
Youichi Kimuraほぼ7年前に追加

prevent double submission on member/registerInput form (fixes #3150)

リビジョン dd803a3c
kaoru n約6年前に追加

Merge pull request #468 from upsilon/t-3150

prevent double submission on member/registerInput form (fixes #3150)

履歴

#1 Kousuke Ebihara11年以上前に更新

  • 優先度Normal(通常) から High(高め) に変更

#2 Yuma Sakata11年以上前に更新

  • 対象バージョンOpenPNE 3.9.0-old にセット
  • 3.8 で発生するかUnknown (未調査) にセット

#3 Yuma Sakata11年以上前に更新

  • 担当者Youichi Kimura にセット

#4 Yuma Sakata11年以上前に更新

  • ステータスNew(新規) から Accepted(着手) に変更

#5 Yuma Sakata11年以上前に更新

  • ステータスAccepted(着手) から New(新規) に変更

#6 開 石切山11年以上前に更新

  • 3.6 で発生するかUnknown (未調査) から Yes (はい) に変更
  • 3.8 で発生するかUnknown (未調査) から Yes (はい) に変更

#7 Youichi Kimura8年以上前に更新

  • ステータスNew(新規) から Accepted(着手) に変更

#8 Youichi Kimura8年以上前に更新

  • ステータスAccepted(着手) から Pending Review(レビュー待ち) に変更
  • 進捗率0 から 50 に変更

当チケットの修正のための Pull Request を送信しました。
https://github.com/openpne/OpenPNE3/pull/282

修正内容の詳細は下記の通りです。

(参考) 通常の登録フロー

[30/Oct/2015:21:01:47 +0900] "GET /member/register/token/230144fcee6e171ed5ff531f7d4007efa HTTP/1.1" 200 2206
[30/Oct/2015:21:01:57 +0900] "GET /member/registerInput/token/230144fcee6e171ed5ff531f7d4007efa HTTP/1.1" 200 3868
[30/Oct/2015:21:03:49 +0900] "POST /member/registerInput/token/230144fcee6e171ed5ff531f7d4007efa HTTP/1.1" 302 929
[30/Oct/2015:21:03:49 +0900] "GET /opAuthMailAddress/registerEnd/token/230144fcee6e171ed5ff531f7d4007efa HTTP/1.1" 302 685
[30/Oct/2015:21:03:50 +0900] "GET / HTTP/1.1" 200 3696

プロフィール入力画面 (member/registerInput) の「送信」ボタンをクリックすると、
"POST /member/registerInput""GET /opAuthMailAddress/registerEnd""GET /" とリダイレクトされホーム画面が表示されます。

IE7 で member/registerInput の「送信」ボタンを連打した場合

[30/Oct/2015:21:29:07 +0900] "GET /member/register/token/33668edc9e77cff2cadcaabcdf5392e59 HTTP/1.1" 200 2213
[30/Oct/2015:21:29:10 +0900] "GET /member/registerInput/token/33668edc9e77cff2cadcaabcdf5392e59 HTTP/1.1" 200 3699
[30/Oct/2015:21:30:04 +0900] "POST /member/registerInput/token/33668edc9e77cff2cadcaabcdf5392e59 HTTP/1.1" 302 929
[30/Oct/2015:21:30:04 +0900] "POST /member/registerInput/token/33668edc9e77cff2cadcaabcdf5392e59 HTTP/1.1" 404 3782
[30/Oct/2015:21:30:05 +0900] "POST /member/registerInput/token/33668edc9e77cff2cadcaabcdf5392e59 HTTP/1.1" 404 3782

プロフィール入力画面 (member/registerInput) で「送信」ボタンを連打すると "POST /member/registerInput" が連続して発行されます。
"POST /member/registerInput" は 2 回目以降のリクエストでは、$this->getUser()->isRegisterBegin() が false になるため 404 エラーが返されます。
この場合、"GET /opAuthMailAddress/registerEnd" に遷移しないままエラー画面で止まるためメンバー登録は完了しません(is_active = 0 のまま)

このユーザーはリダイレクト等で "GET /opAuthMailAddress/registerEnd" に誘導することができればメンバー登録を完了できます(アドレスバーに直接入力しても正常に完了します)

Firefox で member/registerInput の「送信」ボタンを連打した場合

[02/Nov/2015:20:36:22 +0900] "GET /member/register/token/48c745a912ad5add51a0d9d197d234908 HTTP/1.1" 200 2321
[02/Nov/2015:20:36:26 +0900] "GET /member/registerInput/token/48c745a912ad5add51a0d9d197d234908 HTTP/1.1" 200 3706
[02/Nov/2015:20:36:53 +0900] "POST /member/registerInput/token/48c745a912ad5add51a0d9d197d234908 HTTP/1.1" 302 961
[02/Nov/2015:20:36:54 +0900] "GET /opAuthMailAddress/registerEnd/token/48c745a912ad5add51a0d9d197d234908 HTTP/1.1" 302 685
[02/Nov/2015:20:36:54 +0900] "POST /member/registerInput/token/48c745a912ad5add51a0d9d197d234908 HTTP/1.1" 404 3948

Firefox からプロフィール入力画面 (member/registerInput) で「送信」ボタンを連打すると、"POST /member/registerInput" へのリクエストが複数回行われる点は同じですが、その間に裏で "GET /opAuthMailAddress/registerEnd" へのリダイレクトも行われています。
見かけ上は最後の "POST /member/registerInput" の 404 エラーに遷移して止まる点で他のブラウザと同じですが、"GET /opAuthMailAddress/registerEnd" へのリクエストが行われているためメンバー登録が完了している状態となっています(is_active = 1 の状態)

このユーザーはメンバー登録が完了しログイン済みの状態となっているため、リダイレクト等で "GET /" に誘導できれば正常にホーム画面が表示されます。

修正内容

--- a/lib/action/opMemberAction.class.php
+++ b/lib/action/opMemberAction.class.php
@@ -170,6 +170,9 @@ public function executeRegisterInput(opWebRequest $request)
   {
     $this->forward404Unless(opToolkit::isEnabledRegistration((sfConfig::get('app_is_mobile') ? 'mobile' : 'pc')));

+    $this->redirectIf($this->getUser()->isSNSMember(), array('sf_route' => 'homepage'));
+    $this->redirectIf($this->getUser()->isRegisterFinish(), $this->getUser()->getRegisterEndAction());
+
     $this->token = $request['token'];
     $member = $this->getUser()->setRegisterToken($this->token);

それぞれ、$this->getUser()->isMember() は Firefox 向け、$this->getUser()->isRegisterFinish() はその他のブラウザ向けのリダイレクトとなっています。
setRegisterToken() より前に追加しているため、この判定は URL に含まれる register_token ではなく Cookie に含まれる現在のセッションに紐付くユーザーに対して判定されます。

#9 Shinichi Urabe7年以上前に更新

レビューします

#10 Shinichi Urabe7年以上前に更新

  • ステータスPending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
  • 進捗率50 から 70 に変更

みました

#12 isao sanoほぼ7年前に更新

  • ステータスPending Testing(テスト待ち) から Rejected(差し戻し) に変更
  • 進捗率70 から 50 に変更

対象バージョン変更により修正内容の確認が必要であるため差し戻します。

#13 isao sanoほぼ7年前に更新

  • 対象バージョンOpenPNE 3.9.0-old から OpenPNE 3.9.0 に変更

#14 isao sanoほぼ7年前に更新

再現を確認しました。

#15 Youichi Kimuraほぼ7年前に更新

  • 説明 を更新 (diff)
  • ステータスRejected(差し戻し) から Pending Review(レビュー待ち) に変更

#3150-8 のリダイレクトによる対処では IE10 での検証でエラー表示を防ぐことができなかったため、クライアント側で JavaScript によってフォームの二重送信を抑制する方法に変更して改めて修正を行いました。

下記 Pull Request にて修正しました。
https://github.com/openpne/OpenPNE3/pull/468

#16 Shinichi Urabeほぼ7年前に更新

  • ステータスPending Review(レビュー待ち) から Rejected(差し戻し) に変更
  • 古い JS ファイルがブラウザキャッシュに残っているとキャッシュが削除されるまで動作しないと思いますので、 apps/pc_frontend/config/view.yml の記述を例えば、 util.js?20170605 とさせるなど対策をしておいたほうがよりよいと思います
  • 再現するか確認が難しいかもしれませんが、フィーチャーフォン向けの対策は不要でしょうか。

#17 Shinichi Urabeほぼ7年前に更新

モバイルシミュレータ (Firefox の アドオン) ですが 、メンバー登録時の携帯個体識別番号取得設定 を 「登録時に取得しない」しておくと、再現はしました [取得する設定の場合、アラートがでるので、連投の抑止になるため]

#18 Youichi Kimuraほぼ7年前に更新

  • 古い JS ファイルがブラウザキャッシュに残っているとキャッシュが削除されるまで動作しないと思いますので、 apps/pc_frontend/config/view.yml の記述を例えば、 util.js?20170605 とさせるなど対策をしておいたほうがよりよいと思います

これは #4025 で指定されているサポート対象ブラウザにおいて発生する現象なのでしょうか?

具体的には util.js は静的ファイルとして Apache 等から直接配信されるため、ブラウザがキャッシュを利用する際に Last-ModifiedETag ヘッダを適切に扱っているかどうかに左右されます。
例えば IE9 (サポート対象外) においては以下の仕様のため Cache-Control ヘッダーによって明示的にキャッシュを使用しないように指定する必要がありました。
https://support.microsoft.com/ja-jp/help/2530998

  • 再現するか確認が難しいかもしれませんが、フィーチャーフォン向けの対策は不要でしょうか。

mobile_frontend で同様の現象が生じるかどうかについては確認します。
(フォームの二重送信が可能であるかどうかは実機でなければ検証できないと思います)

#19 Shinichi Urabeほぼ7年前に更新

Youichi Kimura さんは書きました:

  • 古い JS ファイルがブラウザキャッシュに残っているとキャッシュが削除されるまで動作しないと思いますので、 apps/pc_frontend/config/view.yml の記述を例えば、 util.js?20170605 とさせるなど対策をしておいたほうがよりよいと思います

これは #4025 で指定されているサポート対象ブラウザにおいて発生する現象なのでしょうか?

Google Chrome バージョン 58.0.3029.110 (64-bit) にて確認をしています。

具体的には util.js は静的ファイルとして Apache 等から直接配信されるため、ブラウザがキャッシュを利用する際に Last-Modified や ETag ヘッダを適切に扱っているかどうかに左右されます。

静的ファイルは Apache や Nginx などの設定によって左右されるのは把握していますが、
ミドルウェア側で Last-Modified, Etag が適切に出力設定されるかどうか、に関わらず、アプリ側でもできる限りの配慮をしておいたほうがよいという意図です。

フォームの二重送信が可能であるかどうかは実機でなければ検証できないと思います

念のため実機での確認をお願いします

#20 Youichi Kimuraほぼ7年前に更新

  • 古い JS ファイルがブラウザキャッシュに残っているとキャッシュが削除されるまで動作しないと思いますので、 apps/pc_frontend/config/view.yml の記述を例えば、 util.js?20170605 とさせるなど対策をしておいたほうがよりよいと思います

これは #4025 で指定されているサポート対象ブラウザにおいて発生する現象なのでしょうか?

Google Chrome バージョン 58.0.3029.110 (64-bit) にて確認をしています。

Google Chrome 58 は Stable channel の最新バージョンであることからサポート対象ブラウザに含まれます。
このブラウザで再現するのであれば対処の必要があると思います。

具体的には util.js は静的ファイルとして Apache 等から直接配信されるため、ブラウザがキャッシュを利用する際に Last-Modified や ETag ヘッダを適切に扱っているかどうかに左右されます。

静的ファイルは Apache や Nginx などの設定によって左右されるのは把握していますが、
ミドルウェア側で Last-Modified, Etag が適切に出力設定されるかどうか、に関わらず、アプリ側でもできる限りの配慮をしておいたほうがよいという意図です。

まず、URL に util.js?20170605 のようなタイムスタンプを付与する方法は、抜け漏れが生じやすく良い方法ではないと考えています。
もしキャッシュに関する HTTP ヘッダーを適切に付与することで対処することが可能なのであれば、その方法を用いることがより望ましいのではないかと考えています。
そして #3150-18 の意図は、これは Apache の仕事だから OpenPNE では一切関知する話ではないという意味ではなく、例えばサポート対象外の古いブラウザについて対処するための workaround ならば必須ではないだろうという考えによるものでした。

Chrome 58 で再現するとのことですが、どうやら私の認識が間違っていたようで Last-Modified や ETag ヘッダを出力していても Cache-Control: must-revalidate などを明示的に指定しなければ(サーバーへのリクエストを行わずに)キャッシュを優先して使用するようです。
そのため、.htaccess に適切な Cache-Control ディレクティブを付与する修正を行うのが今後の静的ファイルの更新のためにも良さそうだと思いました。

#21 Shinichi Urabeほぼ7年前に更新

Youichi Kimura さんは書きました:

そして #3150-18 の意図は、これは Apache の仕事だから OpenPNE では一切関知する話ではないという意味ではなく、例えばサポート対象外の古いブラウザについて対処するための workaround ならば必須ではないだろうという考えによるものでした。

意図理解しました。

Chrome 58 で再現するとのことですが、どうやら私の認識が間違っていたようで Last-Modified や ETag ヘッダを出力していても Cache-Control: must-revalidate などを明示的に指定しなければ(サーバーへのリクエストを行わずに)キャッシュを優先して使用するようです。
そのため、.htaccess に適切な Cache-Control ディレクティブを付与する修正を行うのが今後の静的ファイルの更新のためにも良さそうだと思いました。

了解しました。

#22 Youichi Kimuraほぼ7年前に更新

静的ファイルのキャッシュ動作について新規チケット #4200 を作成しました。
mobile_frontend での動作については引き続き当チケットで扱います。

#23 Youichi Kimuraほぼ7年前に更新

  • ステータスRejected(差し戻し) から Pending Review(レビュー待ち) に変更

member/registerInput のフォームについて F001 (au), KC3Q (au) の各端末で確認した所、ボタンの連打によって複数のリクエストが送信されることはなく、登録も正常に完了しました。

#24 Shinichi Urabeほぼ7年前に更新

  • ステータスPending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
  • 進捗率50 から 70 に変更

確認ありがとうございました
レビューOKです

#26 kaoru n約6年前に更新

  • ステータスPending Testing(テスト待ち) から Fixed(完了) に変更
  • 進捗率70 から 100 に変更

マージしました

他の形式にエクスポート: Atom PDF