web-dev-qa-db-ja.com

ページ間でデータを渡すためのベストプラクティス

問題

プロジェクト間で再利用するスタックでは、ページ間でデータを渡すためにセッションに少し多くのデータを入れています。これは、改ざんやリプレイ攻撃などを防ぐため、理論上は良好でしたが、解決できる限り多くの問題を引き起こします。

セッションロス自体は問題ですが、ほとんどがセッションステートサーバーの実装(またはSQL Serverの使用)によって処理されます。さらに重要なことは、戻るボタンを正しく機能させるのは難しいことです。また、ユーザーが、たとえば、3つのタブで同じ画面を開いて異なるレコードで作業できる状況を作り出すことは余分な作業です。

そして、それは氷山の一角にすぎません。

これらの問題のほとんどには回避策がありますが、私が退屈するにつれて、この摩擦はすべて、セッションを使用してページ間でデータを渡すことが間違った方向であると感じています。

ここで本当にやりたいことは、私のショップが常にページ間でデータを渡すために使用できるベストプラクティスを考え出し、次に新しいアプリのために、現在Sessionに依存しているスタックの主要部分を置き換えることです。

また、最終的な解決策が定型的な配管コードの山にならない場合もいいでしょう。

提案されたソリューション

セッション

上記のように、セッションに重点を置くことは良いアイデアのように思えますが、[戻る]ボタンが壊れて他の問題が発生します。

すべての問題を回避する方法があるかもしれませんが、それは多くの余分な仕事のようです。

セッションを使用することの利点の1つは、改ざんが問題にならないという事実です。暗号化されていないQueryStringを介してすべてを渡すことに比べて、作成するガードコードははるかに少なくなります。

クロスページ投稿

事実、私はこのオプションをほとんど検討していません。私はPreviousPage.FindControl( "SomeTextBox")を実行し始めた場合、それがページをどの程度密結合しているのかという問題を抱えています。 SomeTextBoxと呼ばれるコントロール。

他の方法でも同様に制限されているようです。たとえば、リンクを介してページにアクセスしたい場合があります。

QueryString

昔のように、私は現在この戦略に傾いています。ただし、QueryStringを暗号化して改ざんを防ぎたいと思うので、リプレイ攻撃の問題にも対処したいと思います。

Rollaの4人の男性について これに関する記事があります

ただし、これをすべて処理し、ページからすべての暗号化ソーセージ作成を削除するHttpModuleを作成することは可能です。案の定、 Mads Kristensenがリリースした記事があります。 しかし、コメントは非常に一般的なシナリオに問題があるように聞こえます。

その他のオプション

もちろん、これはオプションの大げさな見方ではなく、私が検討している主なオプションです。 このリンク には、より完全なリストが含まれています。クッキーやキャッシュなど、私が言及しなかったものは、ページ間でデータを渡す目的に適していない。

閉会中...

では、ページ間でデータを渡す問題をどのように処理していますか?どのような隠れた問題を回避する必要がありましたか?また、この問題を完全に解決する既存のツールはありますか? あなたはあなたが完全に満足している解決策を手に入れたと感じていますか?

前もって感謝します!

更新:「ページ間でデータを渡す」など、十分に明確でない場合に備えて、たとえばCustomerIDを渡すCustomerSearch.aspxページからCustomers.aspxへのキー。ここで、顧客が開かれ、編集が行われます。

64
Brian MacKay

数か月後、うまくいったので、私はこの質問を最終的に私が使ったテクニックで更新すると思いました。

より複雑なセッション状態の処理(多くの壊れた戻るボタンなど)で遊んだ後、暗号化されたQueryStringsを処理するために独自のコードをロールバックすることになりました。これは大きな勝利でした-私の問題シナリオ(戻るボタン、複数のタブを同時に開く、セッション状態の喪失など)はすべて解決され、使用方法は非常によく知られているため、複雑さは最小限です。

これはまだすべてのための魔法の弾丸ではありませんが、私はあなたが遭遇するシナリオの約90%に適していると思います。

詳細

Pageを継承するCorePageというクラスを作成しました。 SecureRequestおよびSecureRedirectと呼ばれるメソッドがあります。

だからあなたは電話するかもしれません:

 SecureRedirect(String.Format("Orders.aspx?ClientID={0}&OrderID={1}, ClientID, OrderID)

CorePageはQueryStringを解析し、CoreSecureというQueryString変数に暗号化します。したがって、実際の要求は次のようになります。

Orders.aspx?CoreSecure = 1IHXaPzUCYrdmWPkkkuThEes%2fIs4l6grKaznFGAeDDI%3d

使用可能な場合、現在ログインしているユーザーIDが暗号化キーに追加されるため、リプレイ攻撃はそれほど問題になりません。

そこから、次を呼び出すことができます。

X = SecureRequest("ClientID")

結論

使い慣れた構文を使用して、すべてがシームレスに機能します。

過去数か月にわたって、このコードを、ダウンロードをトリガーするハイパーリンクなどのEdgeケースで動作するように調整しました-時には、安全なQueryStringを持つクライアントでハイパーリンクを生成する必要があります。それは本当にうまくいきます。

このコードをご覧になりたい場合はお知らせください。どこかに掲載します。

最後に考えたのは、他の人がここに投稿した非常に思慮深い投稿のいくつかに対して自分の答えを受け入れるのは奇妙なことですが、これは本当に私の問題に対する究極の答えのようです。私をそこに連れて行ってくれたみんなに感謝します。

8
Brian MacKay

まず、あなたが扱っている問題は、ステートレス環境での状態の処理に関連しています。あなたが抱えている苦労は新しいものではなく、おそらくWindows開発や実行可能ファイルの開発よりもWeb開発を難しくするものの1つです。

Web開発に関しては、私が知っている限りでは、ユーザー固有の状態を処理するための5つの選択肢があり、それらはすべて互いに組み合わせて使用​​できます。すべてに対応できるソリューションはありません。代わりに、各ソリューションをいつ使用するかを決定する必要があります。

  • クエリ文字列-クエリ文字列は、データ(主キー値など)または状態値へのポインターを渡すのに適しています。クエリ文字列自体は、リプレイのために暗号化されている場合でも、安全であると想定すべきではありません。さらに、一部のブラウザーでは、URLの長さに制限があります。ただし、クエリ文字列には、ブックマークや電子メールでの送信が可能で、他で使用しない場合は本質的にステートレスであるなどの利点があります。

  • Cookie-Cookieは、特定のユーザーのごくわずかな情報を保存するのに適しています。問題は、Cookieにもサイズ制限があり、それを超えるとデータが切り捨てられるため、Cookieにカスタムデータを配置する場合は注意が必要なことです。さらに、ユーザーはCookieを強制終了したり、使用を停止したりできます(ただし、標準のセッションも使用できなくなります)。クエリ文字列と同様に、データが小さい場合を除き、データ自体へのポインタよりも、データへのポインタの方がCookieのほうが優れています。

  • フォームデータ-フォームデータはかなりの情報を必要としますが、ポスト時間と場合によってはリロード時間がかかります。 ASP.NETのViewStateは、非表示のフォーム変数を使用して情報を維持します。 ViewStateのようなものを使用してページ間でデータを渡すことには、[戻る]ボタンを使用する方が優れているという利点がありますが、ユーザーのエクスペリエンスを遅くする巨大なページを簡単に作成できます。一般に、ASP.NETモデルはクロスページ投稿では機能しませんが(可能ですが)、代わりに同じページに戻り、そこから次のページに移動する投稿で機能します。

  • セッション-セッションは、ユーザーが進行しているプロセスに関連する情報や一般的な設定に適しています。サーバーのメモリやデータベースからのロード時間を犠牲にして、かなりの量の情報をセッションに保存できます。概念的には、セッションは、メモリまたは状態サーバーからユーザーのデータ全体を一度にロードすることにより機能します。つまり、非常に大きなデータセットがある場合は、おそらくセッションに入れたくないでしょう。セッションは、ユーザーが実際に達成しようとしていることと比較検討しなければならないバックボタンの問題を引き起こす可能性があります。一般に、戻るボタンはWeb開発者の悩みの種になります。

  • データベース-最後のソリューション(これも他のソリューションと組み合わせて使用​​できます)は、アイテムの状態を示す列を持つ適切なスキーマのデータベースに情報を保存することです。たとえば、注文の作成を処理している場合、注文が実際の注文であるかどうかを判断する「状態」列を使用して注文テーブルに保存できます。クエリ文字列またはセッションに注文識別子を保存します。 Webサイトは引き続きテーブルにデータを書き込み、さまざまなパーツと子アイテムを更新し、最終的にユーザーが完了したことを宣言し、注文の状態が実際の注文としてマークされるまで続けます。これにより、レポートとクエリはすべて、「実際の」アイテムと処理中のアイテムを区別する必要があるため、複雑になります。

後のリンクで言及されている項目の1つは、アプリケーションキャッシュでした。これはアプリケーション全体にわたるので、ユーザー固有のものとは思わないでしょう。 (明らかに、ユーザー固有のものになるように角ばったものにできますが、私はそれもお勧めしません)。 HttpContextにデータを保存することで、ハンドラーまたはモジュールに渡す以外に遊んだことはありませんが、上記のソリューションとは異なることに懐疑的です。

一般に、それらすべてを支配する唯一の解決策はありません。最善のアプローチは、各ページで、ユーザーがどこからでもそのページに移動できたと想定することです(別のページのリンクを使用してそこにたどり着いたとは対照的です)。これを行うと、戻るボタンの問題の処理が簡単になります(ただし、まだ苦労します)。私の開発では、最初の4つを広範囲に使用し、必要に応じて最後のソリューションに頼ります。

41
Thomas

さて、これで私の答えの前書きをしたいと思います。トーマスは、これまでに新鮮で始めた人々にとって最も正確で包括的な答えを明らかに持っています。この答えはまったく同じものではありません。私の答えは、「ビジネス開発者」の観点から来ています。みんなよく知っているように。時には、すでに存在し、「機能する」何かを書き直すためにお金を費やすことは、単に実行可能ではありません...少なくとも一度にすべてではありません。時折、より良い代替手段に移行できるソリューションを実装することが最善の場合があります。

私がトーマスが行方不明だと思う唯一のことは;クライアント側のJavaScript状態。私が働いている場所では、顧客はますます「Web 2.0」タイプのアプリケーションを期待するようになっています。また、この種のアプリケーションは通常、ユーザーの満足度を大幅に向上させることがわかっています。 JSONベースのREST WCFで実装されたサービスと通信するjQueryのような本当に素晴らしいjavascriptライブラリ(GWTの使用を開始し、AWESOMEであることがわかった)の助けを借りて)このアプローチは、SOAベースのアーキテクチャへの移行を開始する非常に良い方法を提供し、UIとビジネスロジックを明確に分離します。

しかし、私は脱線します。

既にアプリケーションがあり、ASP.NETのビルトインセッション状態管理の制限を既に超えているかのように聞こえます。だから...ここに私の提案があります(すでにASP.NETのアウトプロセスセッション管理を試したことがあると仮定すると、インプロセス/オンボックスセッション管理よりも大幅に優れた拡張性があります。それ); NCache。

NCacheは、ASP.NETのセッション管理オプションの「ドロップイン」置換を提供します。実装は非常に簡単で、既存のコードベースをすぐにリファクタリングするための多大な投資をせずに、アプリケーションを「バンドエイド」することができます。

余分な時間とお金を使って、すぐにビジネス価値のあるものに新しい開発を集中することで、技術的な負債の削減を開始できます-新しいアプローチ(他の回答や私の提案で提供されている選択肢など)を使用します。

ちょうど私の考え。

9
Steve

上記のすべてのシナリオと回答とこのリンクを通過した後、 データの解析方法 私の最終的なアドバイスは次のようになります。

[〜#〜] cookies [〜#〜]

  • ENCRYPT [userId's]
  • ENCRYPT [productId]
  • ENCRYPT [xyzIds ..]
  • ENCRYPT [など]

[〜#〜] database [〜#〜]

  • cOOKIE IDによるデータセット
  • クッキーIDによるデータテーブル
  • cOOKIE IDによる他のすべての大きなチャンク

私のアドバイスは、以下の統計とこのリンクの詳細にも依存します データの解析方法

enter image description here

5
sajanyamaha

私はこれを決してしません。すべてのセッションデータをデータベースに保存し、ユーザーCookieに基づいてロードする際に問題が発生したことはありません。それはセッションに関するものですが、私はそれを管理しています。 Webサーバーへのセッションデータの制御を放棄しないでください...

少しの作業で、サブセッションをサポートし、異なるタブ/ウィンドウでマルチタスクを許可できます。

3
Fosco

出発点として、顧客IDなどの重要なデータ要素を使用して、処理のためにクエリ文字列に入れるのが最適です。これらの要素から送信される不良データを簡単に追跡/フィルタリングできます。また、電子メールやその他の関連サイト/アプリケーションとの統合も可能です。

以前のアプリケーションでは、従業員またはそれらに関連する要求レコードを表示する唯一の方法は、アプリケーションにログインするか、従業員を検索するか、問題のレコードを見つけるために最近のレコードを検索することでした。これは問題になり、関連部門の誰かが監査目的でレコードを簡単に表示する必要がある場合に大きな時間の無駄になりました。

書き直しでは、従業員IDと要求IDの両方を、 "ViewEmployee.aspx?Id = XXX"および "ViewRequest.aspx?Id = XXX"の基本URLを介して利用可能にしました。アプリケーションは、A)不正なIDをフィルターで除外し、B)これらのページへのアクセスを許可する前にユーザーを認証および承認するようにセットアップされました。これにより、主にアプリケーションユーザーができることは、電子メール内のURLを使用して監査人に簡単な電子メールを送信することでした。急いでいるとき、バルク処理時間にあり、URLのリストをクリックするだけで適切な処理を行うことができました。

変更日やユーザーとアプリケーションとのやり取りの「状態」の維持など、その他のセッション関連データはもう少し複雑になりますが、これが開始点になることを願っています。

2
Dillie-O