フォーム認証を使用するasp.net Webサイトがあります。ユーザー名、ユーザーID、メールなど、セッションで維持していることがいくつかあります。
認証Cookieに長い有効期限を設定することで、ユーザーがWebサイトにログインしたままになることを許可します。したがって、ユーザーがまだ認証されている間にセッションが期限切れになることは非常に一般的です。
私が遭遇している問題は、ユーザーのセッションが時々タイムアウトするが、それらはまだ認証されているということです。したがって、たとえば、ユーザーのページの1つ(認証が必要)は、セッションがアクティブになると「Welcome Mike」と表示しますが、有効期限が切れると、情報がセッションに存在しないため「Welcome [空白]」と表示します。まだ認証されています。
これを処理する最良の方法は何ですか?情報がなくなったときにセッション情報を再同期する必要がありますか?または、ユーザー情報(ユーザー名、ユーザーID、電子メール)をCookieに移動して、セッションのタイムアウトを気にする必要はありませんか?
セッションの長さを60分以上に設定したくありません。 ユーザーが一度ログインできるようにして、明示的にログアウトするまで再度ログインする必要がないことを望んでいます。
セッションをできる限り使用しないでください。見苦しくなくて済む場合は、マルチサーバーの導入が少し簡単になります。おそらく、名前と電子メールはCookieの簡単な候補です。 Cookieを偽造するのは簡単なので、セキュリティのニーズによっては、userIDは適切ではない場合があります。
フォーム認証Cookieは暗号化されており、これらのCookieにデータを追加できます(詳細は以下を参照)。おそらくハッキング可能ですが、単純なクッキーほど簡単ではありません。
これは、プロジェクト固有の詳細を削除するために過去に少し変更したコードです。ログインコントロールのLoggedInイベントでこれを呼び出します。
void AddUserIDToAuthCookie(string userID)
{
//There is no way to directly set the userdata portion of a FormAuthenticationTicket
//without re-writing the login portion of the Login control
//
//I find it easier to pull the cookie that the Login control inserted out
//and create a new cookie with the userdata set
HttpCookie authCookie = Response.Cookies[AUTH_COOKIE];
if(authCookie == null)
{
return;
}
Response.Cookies.Remove(AUTH_COOKIE);
FormsAuthenticationTicket oldTicket = FormsAuthentication.Decrypt(authCookie.Value);
var newTicket =
new FormsAuthenticationTicket(oldTicket.Version, oldTicket.Name, oldTicket.IssueDate, oldTicket.Expiration,
oldTicket.IsPersistent, userID, oldTicket.CookiePath);
authCookie.Value = FormsAuthentication.Encrypt(newTicket);
Response.Cookies.Add(authCookie);
}
参考までに、これを古いプロジェクトからコピーし、ここで編集してプロジェクト固有のビットをいくつか削除したので、コンパイルされない可能性がありますが、非常に近くなります。
WebページでIDを取得するには...
FormsAuthenticationTicket ticket = ((FormsIdentity) Page.User.Identity).Ticket;
string id = ticket.UserData;
このメカニズムを使用して、aspnetdbユーザーデータの一部ではないIDを保存しました。すべてのIDデータがaspnetdbによって処理される場合、Page.User.Identityオブジェクトにアクセスするだけでよい場合があります。
個人的には、20分のデフォルトを維持し、「キープアライブ」機能をサイトに追加します。セッションを存続させるために、5分ごとにポーリングするハートビート.aspxなどの単純なJavaScriptを作成します。これにより、クレイジーな認証トークンを保持せずにセッションと認証が拡張されます。
これを行う方法のいくつかの例(私の意見では悪い)があります。私は AjaxLinesのセッションタイムアウト防止 に基づいたものを使用することになりました。ただし、ajaxライブラリを使用する代わりに、xhtmlリクエストを直接使用しました。ハートビートページのGET
への時間指定されたjavascript呼び出し以外には何も必要ありません。
技術的にはasp.netセッションのタイムアウトにより、ユーザーはログアウトされません。これは、フォーム認証Cookieによって制御される必要があります。
ユーザー認証に関連するすべての重要な情報は、フォーム認証チケットのUSERDATAプロパティに保持する必要があります。この値は、セッションとしてセッション中に保持されるべきではありません。
これらの値は、再作成可能なセッションでのみ保持します。
したがって、フォーム認証Cookieを作成するときに、すべての重要な情報をチケットの一部として渡すことができます。
-
あなたができる簡単なことは、セッションとフォーム認証の両方のタイムアウトを同じに保つことです。これは良い習慣になります。
セッションタイムアウトは、サイトへのリクエストごとに自動的に延長されます。
一方、フォーム認証では、時間の50%が経過した後にのみ時間が延長されます。
これに関する詳細情報は次のとおりです。 フォーム認証に関するFAQ
最も簡単なことは、デザインが何であれ、カスタムHttpModuleまたはベースページでフォーム認証時間を延長することです。
このようにして、タイムアウトは常に同期しますが、多少のギャップがある場合があります。
実際に自分で何も試さなくても、チェックしたいことがいくつかあります。
永続的なCookieを設定できるようにするFormsAuthenticationクラスのメソッド/オーバーロードを使用します。ただし、私見では、ユーザーに強制的にログインさせるのではなく、「覚えておく」ボックスをチェックすることを選択できるようにするのが一般的な礼儀です。必要な動作に基づいてこれを実行できるようにする方法がいくつかあります- SetAuthenticationCookie()とRedirectFromLoginPage()が最初に思い浮かぶものです。
FormsAuthentication.GetAuthenticationCookie()を確認してください。これにより、認証トークンを使用してHTTP Cookieが生成されますが、実際には設定されませんすべき必要なものを変更できます-FormsAuthenticationモジュールが特定の値を探している場合、それをいじる可能性があります認証を破る。次に、手動でレスポンスのCookieコレクションにCookieを追加する必要があります。
私の好ましい方法は、キャッシュのようなセッションを使用することです。つまり、値が存在する場合はセッションからの読み取りを試み、値が存在する場合はそれを返します。存在しない場合は、永続ストア(データベースなど)から読み取り、セッションに入れてそれを返します。
これを簡略化するには、クラスを作成し、セッションで各変数のプロパティを追加し、クラスのインスタンスをセッションで格納します。次に、静的メソッドを作成して、クラスのインスタンスを取得します。できれば後で例を追加します。