FormsAuthentication.SignOut()はユーザーをログアウトしません
-
03-07-2019 - |
質問
これに対して頭が長すぎました。ユーザーがFormsAuthentication.SignOutを使用してログアウトした後、サイトのページを閲覧できないようにするにはどうすればよいですか?私はこれがそれをすることを期待しています:
FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();
しかし、そうではありません。 URLを直接入力しても、ページを参照できます。私はしばらくの間、独自のセキュリティを使用していないので、なぜこれが機能しないのかを忘れています。
解決
FormsAuthentication.SignOut()を呼び出すとCookieがクリアされず、新しいリクエストごとに認証されるため、ユーザーは引き続きWebサイトを閲覧できます。 MSのドキュメントでは、クッキーはクリアされるが、バグはクリアされないと言われていますか?
Session.Abandon()
とまったく同じですが、Cookieはまだ存在しています。
これにコードを変更する必要があります:
FormsAuthentication.SignOut();
Session.Abandon();
// clear authentication cookie
HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie1.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie1);
// clear session cookie (not necessary for your current problem but i would recommend you do it anyway)
SessionStateSection sessionStateSection = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState");
HttpCookie cookie2 = new HttpCookie(sessionStateSection.CookieName, "");
cookie2.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie2);
FormsAuthentication.RedirectToLoginPage();
HttpCookie
は System.Web
名前空間にあります。 MSDNリファレンス。
他のヒント
内でweb.config承認セクションが適切に設定されていないように聞こえます。例については、以下を参照してください。
<authentication mode="Forms">
<forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
x64igorとPhil Haseldenによる上記の2つの投稿を使用して、これを解決しました:
1。 x64igorはログアウトを行う例を示しました:
-
最初に、ログアウトへの応答で空のCookieを返すことにより、認証CookieとセッションCookieをクリアする必要があります。
public ActionResult LogOff() { FormsAuthentication.SignOut(); Session.Clear(); // This may not be needed -- but can't hurt Session.Abandon(); // Clear authentication cookie HttpCookie rFormsCookie = new HttpCookie( FormsAuthentication.FormsCookieName, "" ); rFormsCookie.Expires = DateTime.Now.AddYears( -1 ); Response.Cookies.Add( rFormsCookie ); // Clear session cookie HttpCookie rSessionCookie = new HttpCookie( "ASP.NET_SessionId", "" ); rSessionCookie.Expires = DateTime.Now.AddYears( -1 ); Response.Cookies.Add( rSessionCookie );
2。 Phil Haseldenが、ログアウト後のキャッシュを防ぐ方法の例を示しました:
-
レスポンスを介してクライアント側のキャッシュを無効にする必要があります。
// Invalidate the Cache on the Client Side Response.Cache.SetCacheability( HttpCacheability.NoCache ); Response.Cache.SetNoStore(); // Redirect to the Home Page (that should be intercepted and redirected to the Login Page first) return RedirectToAction( "Index", "Home" ); }
ここで重要なのは、「URLを直接入力した場合...」と言うことです。
デフォルトでは、フォーム認証では、ブラウザーはユーザーのページをキャッシュします。そのため、ブラウザのアドレスボックスのドロップダウンからURLを直接選択するか、入力することで、ブラウザのキャッシュからページを取得し、サーバーに戻って認証/承認を確認することはできません。これに対する解決策は、各ページのPage_Loadイベント、またはベースページのOnLoad()でクライアント側のキャッシュを防ぐことです。
Response.Cache.SetCacheability(HttpCacheability.NoCache);
電話することもできます:
Response.Cache.SetNoStore();
私もこれに苦労しました。
これは何が起こっているかの類推です...新しい訪問者であるジョーがサイトに来て、FormsAuthenticationを使用してログインページからログインします。 ASP.NETはJoeの新しいIDを生成し、Cookieを提供します。そのクッキーは家の鍵のようなものであり、ジョーがその鍵で戻ってくる限り、彼は錠を開けることができます。各訪問者には、使用する新しいキーと新しいロックが与えられます。
FormsAuthentication.SignOut()
が呼び出されると、システムはJoeにキーを失うように伝えます。通常、これは機能します。Joeがキーを持たなくなったため、彼はアクセスできません。
ただし、Joeが戻ってきて、失われたキーを持っている場合、彼は戻されます!
私が知る限り、ASP.NETにドアのロックを変更するよう指示する方法はありません!
これと一緒に暮らすには、セッション変数にジョーの名前を覚えておくことです。彼がログアウトすると、私はセッションを放棄するので、彼の名前はもうありません。後で、彼が許可されているかどうかを確認するために、Identity.Nameを現在のセッションの名前と比較します。一致しない場合、彼は有効な訪問者ではありません。
要するに、Webサイトの場合、セッション変数もチェックせずに User.Identity.IsAuthenticated
に依存しないでください!
これは私のために動作します
public virtual ActionResult LogOff()
{
FormsAuthentication.SignOut();
foreach (var cookie in Request.Cookies.AllKeys)
{
Request.Cookies.Remove(cookie);
}
foreach (var cookie in Response.Cookies.AllKeys)
{
Response.Cookies.Remove(cookie);
}
return RedirectToAction(MVC.Home.Index());
}
多くの検索の後、ようやくこれがうまくいきました。役に立てば幸いです。
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return RedirectToAction("Index", "Home");
}
<li class="page-scroll">@Html.ActionLink("Log off", "LogOff", "Account")</li>
投稿したコードは、フォーム認証トークンを正しく削除するように見えるため、問題のフォルダー/ページが実際に保護されていない可能性があります。
ログインが発生する前にページにアクセスできないことを確認しましたか?
使用しているweb.config設定とログインコードを投稿できますか?
すべてのページの基本クラスを作成してきましたが、同じ問題に遭遇しました。 次のようなコードがありましたが、うまくいきませんでした。トレースにより、制御はRedirectToLoginPage()ステートメントからリダイレクトされることなく次の行に渡されます。
if (_requiresAuthentication)
{
if (!User.Identity.IsAuthenticated)
FormsAuthentication.RedirectToLoginPage();
// check authorization for restricted pages only
if (_isRestrictedPage) AuthorizePageAndButtons();
}
2つの解決策があることがわかりました。 FormsAuthentication.RedirectToLoginPage();を変更するか、
if (!User.Identity.IsAuthenticated)
Response.Redirect(FormsAuthentication.LoginUrl);
ORを追加してweb.configを変更する
<authorization>
<deny users="?" />
</authorization>
2番目のケースでは、トレース中に、要求されたページに制御が到達しませんでした。ブレークポイントに到達する前に、すぐにログインURLにリダイレクトされました。 したがって、SignOut()メソッドは問題ではなく、リダイレクトメソッドが問題です。
それが誰かの助けになることを願っています
よろしく
ここでいくつかの提案を試してみましたが、ブラウザの戻るボタンを使用することができましたが、メニュー選択をクリックすると、その[ActionResult]の[Authorize]トークンがログイン画面に戻りました。
ログアウトコードは次のとおりです。
FormsAuthentication.SignOut();
Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
HttpCookie cookie = HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
cookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(cookie);
}
ブラウザの戻る機能は、私を取り戻し、セキュリティで保護されたメニューを表示しましたが(私はまだそれに取り組んでいます)、アプリでセキュリティで保護されたものは何もできませんでした。
これが役立つことを願って
このスレッドでほとんどの答えを試しましたが、運はありません。これで終わった:
protected void btnLogout_Click(object sender, EventArgs e)
{
FormsAuthentication.Initialize();
var fat = new FormsAuthenticationTicket(1, "", DateTime.Now, DateTime.Now.AddMinutes(-30), false, string.Empty, FormsAuthentication.FormsCookiePath);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(fat)));
FormsAuthentication.RedirectToLoginPage();
}
ここで見つけました: http://forums.asp.net/t/1306526。 aspx / 1
この回答は技術的にはKhosro.Pakmaneshと同一です。彼の回答がこのスレッドの他の回答とどのように異なり、どのユースケースで使用できるかを明確にするために投稿しています。
一般的にユーザーセッションをクリアするには、次のようにします
HttpContext.Session.Abandon();
FormsAuthentication.SignOut();
ユーザーを効率的にログアウトします。 ただし、同じリクエストで Request.isAuthenticated
を確認する必要がある場合(たとえば、承認フィルターでよくあることです)、それが見つかります
Request.isAuthenticated == true
偶数_ HttpContext.Session.Abandon()
および FormsAuthentication.SignOut()
を実行した後。
機能していたのは、やることだけでした
AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
これにより、 Request.isAuthenticated = false
が効率的に設定されます。
認証&gt;フォーム&gt; Web.config
のPathプロパティ。これを削除することで問題が解決し、簡単な FormsAuthentication.SignOut();
で再びCookieが削除されました。
あるサブドメイン(sub1.domain.com)からログインしてから、別のサブドメイン(www.domain.com)からログアウトしようとしている可能性があります。
ちょうど同じ問題があり、SignOut()はチケットを適切に削除できなかったようです。ただし、他のロジックがリダイレクトを引き起こした特定の場合に限ります。この2番目のリダイレクトを削除した後(エラーメッセージに置き換えました)、問題はなくなりました。
問題は、ページが間違った時間にリダイレクトされたため、認証がトリガーされなかったことであるに違いありません。
現在、同様の問題を抱えています。私の場合、元のポスターの問題はリダイレクトが原因であると考えています。デフォルトでは、Response.Redirectによって例外が発生し、キャッチされてリダイレクトがすぐに実行されるまですぐにバブルアップします。これにより、変更されたCookieコレクションがクライアントに渡されないようになっています。使用するようにコードを変更した場合:
Response.Redirect("url", false);
これにより例外が回避され、Cookieがクライアントに適切に返送されるようになります。
ログインを押したときにセッション変数を送信してみてください。 ようこそページで、最初にページの読み込みまたは初期化イベントで次のようにそのセッションが空であるかどうかを確認します。
if(Session["UserID"] == null || Session["UserID"] == "")
{
Response.Redirect("Login.aspx");
}
私にとっては、次のアプローチが有効です。 &quot; FormsAuthentication.SignOut()&quot;の後にエラーがあると思います。ステートメント、SingOutは機能しません。
public ActionResult SignOut()
{
if (Request.IsAuthenticated)
{
FormsAuthentication.SignOut();
return Redirect("~/");
}
return View();
}
IEを使用してこの動作をテスト/確認していますか? IEがキャッシュからこれらのページを提供している可能性があります。 IEでキャッシュをフラッシュするのは難しいことで有名です。そのため、多くの場合、ログアウトした後でも、「セキュリティで保護された」いずれかのURLを入力します。ページには以前からキャッシュされたコンテンツが表示されます。
(別のユーザーとしてログインした場合でもこの動作が見られ、IEはページの上部に古いユーザーのユーザー名とともに&quot; Welcome&quot;バーを表示します。最近では通常、リロードにより更新されます、ただし、永続的な場合は、依然としてキャッシュの問題である可能性があります。)
Session.abandon()を実行してCookieを破棄することは非常に効果的です。私はmvc3を使用していますが、保護されたページに移動してログアウトし、ブラウザの履歴を表示すると問題が発生するようです。大したことではありませんが、それでもいらいらします。
私のWebアプリのリンクをたどろうとするのは正しい方法です。
ブラウザのキャッシュを行わないように設定するのがよいでしょう。
MVCの場合、これは私にとって有効です:
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true));
}
問題の理解に役立つ情報を追加したかった。フォーム認証では、ユーザーデータをCookieまたはURLのクエリ文字列に保存できます。サイトがサポートする方法は、web.configファイルで構成できます。
SignOutメソッドは、フォーム認証チケット情報を削除します CookieまたはURLから CookiesSupportedがfalseの場合 。
同時に、言う:
HttpCookieMode値の1つ。 アプリケーションはcookielessフォーム認証用に構成されています。 デフォルトはUseDeviceProfile です。
最後に、UseDeviceProfileに関して、言う:
CookieModeプロパティがUseDeviceProfileに設定されている場合、 CookiesSupportedプロパティは、ブラウザが 現在のリクエストは、CookieとCookieによるリダイレクトの両方をサポートしています 。 そうでない場合、CookiesSupportedプロパティはfalseを返します。
これをすべて組み合わせて、ユーザーのブラウザーに応じて、デフォルト構成ではCookiesSupportedが true になる可能性があります。つまり、SignOutメソッドはCookieからチケットをクリアしません。これは直感に反しているようで、なぜこのように機能するのかわかりません-SignOutがどんな状況でも実際にユーザーをサインアウトすることを期待します。
SignOutを単独で動作させる1つの方法は、Cookieモードを&quot; UseCookies&quot;に変更することです。 (つまり、Cookieが必要です)web.configファイル:
<authentication mode="Forms">
<forms loginUrl="~/Account/SignIn" cookieless="UseCookies"/>
</authentication>
私のテストによれば、これを行うと、Cookieが適切に機能するようになりますが、サイトの費用はかかりますが、SignOutは単独で動作します。
STSからのwsignoutcleanupメッセージがIISからのアプリケーションの名前のurlと一致しない場合、WIFは拒否してCookieをクリーンアップするようブラウザに指示することに注意してください。大文字と小文字を区別。 WIFは緑色のOKチェックで応答しますが、ブラウザにCookieを削除するコマンドを送信しません。
したがって、URLの大文字と小文字の区別に注意する必要があります。
たとえば、ThinkTecture Identity Serverは訪問するRPのURLを1つのCookieに保存しますが、すべてを小文字にします。 WIFは小文字でwsignoutcleanupメッセージを受信し、IISのアプリケーション名と比較します。一致しない場合、Cookieは削除されませんが、ブラウザにOKと報告されます。そのため、このIdentity Serverでは、このような問題を回避するために、web.configのすべてのURLとIISのすべてのアプリケーション名を小文字で記述する必要がありました。
また、STSのサブドメインの外部にアプリケーションがある場合は、ブラウザーでサードパーティのCookieを許可することを忘れないでください。そうしないと、WIFから通知されてもブラウザーはCookieを削除しません。