Project

General

Profile

Bug(バグ) #3150

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

Added by Kiwa Sakai about 7 years ago. Updated over 1 year ago.

Status:
Fixed(完了)
Priority:
High(高め)
Target version:
Start date:
2012-08-07
Due date:
% Done:

100%

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

Description

現象

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 View (29.1 KB) Shinichi Urabe, 2017-06-05 15:38


Related issues

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

History

#1 Updated by Kousuke Ebihara about 7 years ago

  • Priority changed from Normal(通常) to High(高め)

#2 Updated by Yuma Sakata almost 7 years ago

  • Target version set to OpenPNE 3.9.0-old
  • 3.8 で発生するか set to Unknown (未調査)

#3 Updated by Yuma Sakata almost 7 years ago

  • Assignee set to Youichi Kimura

#4 Updated by Yuma Sakata almost 7 years ago

  • Status changed from New(新規) to Accepted(着手)

#5 Updated by Yuma Sakata almost 7 years ago

  • Status changed from Accepted(着手) to New(新規)

#6 Updated by 開 石切山 almost 7 years ago

  • 3.6 で発生するか changed from Unknown (未調査) to Yes (はい)
  • 3.8 で発生するか changed from Unknown (未調査) to Yes (はい)

#7 Updated by Youichi Kimura almost 4 years ago

  • Status changed from New(新規) to Accepted(着手)

#8 Updated by Youichi Kimura almost 4 years ago

  • Status changed from Accepted(着手) to Pending Review(レビュー待ち)
  • % Done changed from 0 to 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 Updated by Shinichi Urabe about 3 years ago

レビューします

#10 Updated by Shinichi Urabe about 3 years ago

  • Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
  • % Done changed from 50 to 70

みました

#12 Updated by isao sano over 2 years ago

  • Status changed from Pending Testing(テスト待ち) to Rejected(差し戻し)
  • % Done changed from 70 to 50

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

#13 Updated by isao sano over 2 years ago

  • Target version changed from OpenPNE 3.9.0-old to OpenPNE 3.9.0

#14 Updated by isao sano over 2 years ago

再現を確認しました。

#15 Updated by Youichi Kimura about 2 years ago

  • Description updated (diff)
  • Status changed from Rejected(差し戻し) to Pending Review(レビュー待ち)

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

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

#16 Updated by Shinichi Urabe about 2 years ago

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

#17 Updated by Shinichi Urabe about 2 years ago

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

#18 Updated by Youichi Kimura about 2 years ago

  • 古い 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 Updated by Shinichi Urabe about 2 years ago

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 Updated by Youichi Kimura about 2 years ago

  • 古い 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 Updated by Shinichi Urabe about 2 years ago

Youichi Kimura さんは書きました:

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

意図理解しました。

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

了解しました。

#22 Updated by Youichi Kimura about 2 years ago

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

#23 Updated by Youichi Kimura about 2 years ago

  • Status changed from Rejected(差し戻し) to Pending Review(レビュー待ち)

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

#24 Updated by Shinichi Urabe about 2 years ago

  • Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
  • % Done changed from 50 to 70

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

#26 Updated by kaoru n over 1 year ago

  • Status changed from Pending Testing(テスト待ち) to Fixed(完了)
  • % Done changed from 70 to 100

マージしました

Also available in: Atom PDF