web-dev-qa-db-ja.com

FormsAuthentication.SignOut()はユーザーをログアウトしません

これに対して少し長すぎる頭を打ちました。 FormsAuthentication.SignOutを使用してログアウトした後、ユーザーがサイトのページを閲覧できないようにするにはどうすればよいですか?私はこれがそれをすることを期待しています:

FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();

しかし、そうではありません。 URLを直接入力しても、ページを参照できます。私はしばらくの間、独自のセキュリティを使用していないので、なぜこれが機能しないのかを忘れています。

139
Jason

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();

HttpCookieSystem.Web名前空間にあります。 MSDNリファレンス

199
Igor Jerosimić

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" ); 
    }
    
20
justdan23

内でweb.config承認セクションが適切に設定されていないようです。例については、以下を参照してください。

<authentication mode="Forms">
  <forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
  <deny users="?" />
</authorization>
20
jwalkerjr

ここで重要なのは、「URLを直接入力した場合...」と言うことです。

デフォルトでは、フォーム認証では、ブラウザはユーザーのページをキャッシュします。そのため、ブラウザのアドレスボックスのドロップダウンから直接URLを選択するか、URLを入力すると、ブラウザのキャッシュからページを取得でき、認証/承認を確認するためにサーバーに戻ることはできません。これに対する解決策は、各ページのPage_LoadイベントまたはベースページのOnLoad()でクライアント側のキャッシュを防ぐことです。

Response.Cache.SetCacheability(HttpCacheability.NoCache);

また、電話することもできます。

Response.Cache.SetNoStore();
12
Phil Haselden

私もこれに苦労しました。

これは何が起こっているかの類推です...新しい訪問者のジョーがサイトにアクセスし、FormsAuthenticationを使用してログインページからログインします。 ASP.NETはJoeの新しいIDを生成し、彼にCookieを提供します。そのクッキーは家の鍵のようなものであり、ジョーがその鍵で戻ってくる限り、彼は錠を開けることができます。各訪問者には、使用する新しいキーと新しいロックが与えられます。

FormsAuthentication.SignOut()が呼び出されると、システムはJoeにキーを失うように伝えます。通常、これは機能します。Joeがキーを持たなくなったため、彼は入ることができません。

ただし、Joeが戻ってきて、does失われたキーを持っている場合、彼は戻されます!

私の知る限り、ASP.NETにドアのロックを変更するように指示する方法はありません。

私がこれと共存できる方法は、セッション変数にジョーの名前を記憶することです。彼がログアウトすると、私はセッションを放棄するので、彼の名前はもうありません。後で、彼が許可されているかどうかを確認するために、私は単に彼のIdentity.Nameを現在のセッションの内容と比較します。一致しない場合、彼は有効な訪問者ではありません。

要するに、Webサイトの場合、セッション変数もチェックせずにUser.Identity.IsAuthenticatedに依存しないでください!

11
Glen Little

これは私のために働く

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());
    }
6
Korayem

多くの検索の後、最終的にこれは私のために働いた。役に立てば幸いです。

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>
6

私はすべてのページの基本クラスを作成してきましたが、同じ問題に遭遇しました。次のようなコードがありましたが、うまくいきませんでした。トレースにより、制御は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);

または、次を追加してweb.configを変更します

<authorization>
  <deny users="?" />
</authorization>

2番目のケースでは、トレース中に、制御が要求されたページに到達しませんでした。ブレークポイントに到達する前に、すぐにログインURLにリダイレクトされました。したがって、SignOut()メソッドは問題ではなく、リダイレクトメソッドが問題です。

それが誰かの助けになることを願っています

よろしく

3
Wahid Shalaly

この回答は、技術的には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が効果的に設定されます。

3
seebiscuit

投稿したコードは、フォーム認証トークンを正しく削除するように見えるため、問題のフォルダー/ページが実際に保護されていない可能性があります。

ログインが発生する前にページにアクセスできないことを確認しましたか?

使用しているweb.config設定とログインコードを投稿できますか?

3
Abram Simon

ここでいくつかの提案を試してみましたが、ブラウザの戻るボタンを使用することができましたが、メニュー選択をクリックすると、その[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);
        }

ブラウザの戻る機能を使用すると、セキュリティで保護されたメニューが表示されます(まだ作業中です)が、アプリでセキュリティで保護された操作を実行できませんでした。

お役に立てれば

3
DonH

私はこのスレッドでほとんどの答えを試しましたが、運はありません。これで終わった:

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

3
stoffen

これは、Web.configauthentication> forms> Path propertyを設定したときに起こりました。これを削除すると問題が解決し、単純なFormsAuthentication.SignOut();で再びCookieが削除されました。

2
BPM

あるサブドメイン(sub1.domain.com)からログインしてから、別のサブドメイン(www.domain.com)からログアウトしようとしている可能性があります。

1
jorsh1

SignOut()がチケットを適切に削除できなかったように見える同じ問題が発生しました。ただし、他のロジックがリダイレクトを引き起こした特定の場合のみです。この2番目のリダイレクトを削除した後(エラーメッセージに置き換えました)、問題はなくなりました。

問題は、ページが間違った時間にリダイレクトされたため、認証がトリガーされなかったことであるに違いありません。

1
Peder Skou

私は今、同様の問題を抱えており、元のポスターと同様に私の場合の問題はリダイレクトによるものだと考えています。デフォルトでは、Response.Redirectにより例外が発生し、キャッチされてリダイレクトがすぐに実行されるまですぐにバブルアップします。これにより、変更されたCookieコレクションがクライアントに渡されないようになっています。使用するようにコードを変更した場合:

Response.Redirect("url", false);

これにより、例外が回避され、Cookieがクライアントに適切に送り返されるようになります。

1
lostatredrock

ログインを押したときにセッション変数を送信してみてください。そして、ようこそページで、最初にページの読み込みまたは初期化イベントでそのセッションが空であるかどうかを確認します。

if(Session["UserID"] == null || Session["UserID"] == "")
{
    Response.Redirect("Login.aspx");
}
1
Devrishi

私にとっては、次のアプローチが機能します。 「FormsAuthentication.SignOut()」ステートメントの後にエラーがある場合、SingOutは機能しません。

public ActionResult SignOut()
    {
        if (Request.IsAuthenticated)
        {
            FormsAuthentication.SignOut();

            return Redirect("~/");
        }
        return View();
     }
1
Aji

問題を理解するのに役立つ情報を追加したかった。フォーム認証では、ユーザーデータをCookieまたはURLのクエリ文字列に保存できます。サイトがサポートする方法は、web.configファイルで構成できます。

Microsoft によると:

SignOutメソッドは、CookieまたはURLからフォーム認証チケット情報を削除しますCookiesSupportedがfalseの場合

同時に、 彼らは を言う:

アプリケーションがcookielessフォーム認証用に構成されているかどうかを示すHttpCookieMode値の1つ。 デフォルトはUseDeviceProfile

最後に、UseDeviceProfileに関して、 彼らは と言います:

CookieModeプロパティがUseDeviceProfileに設定されている場合、CookiesSupportedプロパティはブラウザの現在のリクエストがCookieとCookieによるリダイレクトの両方をサポートしている場合trueを返します);それ以外の場合、CookiesSupportedプロパティはfalseを返します。

これをすべてつなぎ合わせると、ユーザーのブラウザに応じて、デフォルトの構成ではCookiesSupportedがtrueになる場合があります。これは、SignOutメソッドがCookieからチケットをクリアしないことを意味します。なぜこのように機能するのかを知ってください-SignOutはどのような状況でも実際にユーザーをサインアウトすることを期待しています。

SignOutを単独で機能させる1つの方法は、web.configファイルでCookieモードを「UseCookies」に変更することです(つまり、Cookieが必要です)。

<authentication mode="Forms">
  <forms loginUrl="~/Account/SignIn" cookieless="UseCookies"/>
</authentication>

私のテストによれば、これを行うと、Cookieが適切に機能するようになりますが、サイトの費用はかかりますが、SignOutは単独で動作します。

0
RogerMKE

MVCの場合、これは私のために機能します:

        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();
            return Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true));
        }
0
anovo

Session.abandon()を実行してCookieを破棄することは非常に効果的です。私はmvc3を使用していますが、保護されたページに移動してログアウトし、ブラウザの履歴を表示すると問題が発生するようです。大したことではありませんが、それでもいらいらします。

しかし、私のWebアプリのリンクをたどろうとすることは正しい方法です。

ブラウザーのキャッシュを行わないように設定するのがよいでしょう。

0
James

IEを使用してこの動作をテスト/表示していますか? IEがキャッシュからこれらのページを提供している可能性があります。 IEを取得してキャッシュをフラッシュするのは難しいことで有名です。そのため、多くの場合、ログアウトした後でも、「セキュリティで保護された」ページのURLを入力するとキャッシュされたコンテンツが表示されます。

(別のユーザーとしてログインした場合でも、この動作を見てきました。IEは、ページの上部に古いユーザーのユーザー名とともに「ようこそ」バーを表示します。最近では、通常、リロードが更新されますそれが、それが永続的である場合、それはまだキャッシュの問題である可能性があります。)

0
Stobor