FormsAuthentication.SignOut ()이 사용자를 로그 아웃하지 않습니다.


143

이것에 대해 너무 오랫동안 내 머리를 부 mash 버렸다. FormsAuthentication.SignOut을 사용하여 로그 아웃 한 후 사용자가 사이트 페이지를 탐색하지 못하게하려면 어떻게합니까? 나는 이것을 할 것으로 기대합니다 :

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

그러나 그렇지 않습니다. URL을 직접 입력해도 여전히 페이지를 탐색 할 수 있습니다. 한동안 롤업 보안을 사용하지 않았기 때문에 왜 이것이 작동하지 않는지 잊어 버렸습니다.


브라우저에서 다시 클릭해도 서버의 페이지를 다시 방문하지 않고 단순히 페이지의 로컬 캐시 버전을 다시로드합니다. 아래의 모든 솔루션은 그 사실을 무시하고 실제로 여기에서 수행하는 것 이상을 수행하지 않는 것 같습니다. 간단히 말해서 ...이 질문에 대한 대답은 캐시를 보는 사용자를 해결할 것입니다 .js 또는 서버 측 명령으로 캐시를 지우는 방법이 있다고 생각하지 않습니다.
전쟁

이 답변은 특히 PEN 테스트에 실패한 사이트를 확인하는 몇 가지 방법을 제공합니다. stackoverflow.com/questions/31565632/…
Tyler S. Loeper

답변:


211

전화를 걸 때 쿠키가 지워지지 않고 FormsAuthentication.SignOut()새 요청마다 인증 되기 때문에 사용자는 여전히 웹 사이트를 탐색 할 수 있습니다 . MS 문서에서 쿠키는 지워지지 만 쿠키는 지워지지 않는다고 말합니다. Session.Abandon()쿠키 와 정확히 동일합니다 . 쿠키는 여전히 있습니다.

코드를 다음과 같이 변경해야합니다.

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 참조 .


18
이것은 나를 위해 작동합니다. 그러나 로그인 할 때 FormsAuthentication 쿠키에 Domain 속성이 설정되어 있으면 로그 아웃 할 때 쿠키가 만료 될 때 쿠키 속성도 설정해야합니다.
Phil Hale

8
또한 잊지 마십시오 cookie1.HttpOnly = true;
Dmitry Zaets

6
이것은 나에게 더 나은 해결책처럼 보인다 : Response.Cookies [FormsAuthentication.FormsCookieName] .Expires = DateTime.Now.AddDays (-1);
랜디 H.

7
@RandyH. 기존의 FormsAuthentication 쿠키를 새로운 빈 쿠키로 재정의하면 클라이언트가 시스템 시계를 되 감아도 쿠키에서 사용자 데이터를 검색 할 수 없습니다.
Tri Q Tran 2016

9
누군가이 모든 의견을 답변에 결합 할 수 있습니까?
David

22

x64igor와 Phil Haselden의 위의 두 가지 게시물을 사용하여 이것을 해결했습니다.

1. x64igor가 로그 아웃을 수행하는 예제를 제공했습니다.

  • 먼저 응답의 빈 쿠키를 로그 아웃으로 전달 하여 인증 쿠키 및 세션 쿠키 를 지워야합니다.

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

1
이 문제를 해결하기 위해 하루 종일 낭비했습니다. 일단 로그 아웃 버튼에 로그인하면 컨트롤러에서 잘못된 조치를 호출하기 시작했습니다 (로그인하지 않음). 감사합니다. 문제가 해결되었습니다. 개발 환경 : ASP.NET 4.51 MVC 5.1
Ako

1
좋은 대답입니다! 겸손한 제안 : x64igor에서 사용한 세션 쿠키를 지우려면 다음과 같은 형식을 사용하십시오 SessionStateSection sessionStateSection = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState"); HttpCookie sessionCookie = new HttpCookie(sessionStateSection.CookieName, "");. 일반적으로 세션 쿠키 이름은 "ASP.NET_SessionId"입니다.
seebiscuit

20

에 web.config 인증 섹션이 제대로 설정되지 않은 것 같습니다. 예는 아래를 참조하십시오.

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

이것은 훨씬 간단한 해결책입니다. 나는 이것을 대답으로 표시 할 것입니다. 한 서버에서 다른 서버에서 작동하는 하나의 코드 버전을 얻었으므로 여기에 추가 한 다른 속성을 설정할 필요가 없었습니다. 따라서 코드를 수정하는 것이 올바른 해결책이 아니므로 구성을 수정하는 것이 좋습니다.
Vladimir Bozic

기본적으로 slideExpiration은 true ( msdn.microsoft.com/library/1d3t3c61(v=vs.100).aspx )로 설정되어 있습니다 . 그리고 결국 타임 아웃에 설정된 x 분 후에 쿠키가 유효하지 않게되며 사용자가 SignOut ()을 통해 로그 오프 할 때가 아닙니다. 따라서 이렇게하면 FormsAuthentication을 사용하여 사용자를 로그 오프하는 원하는 동작이 발생하지 않습니다. 내가 틀렸다면 정정 해주세요.
OlafW

12

여기서 핵심은 "URL을 직접 입력하면 ..."이라고 말합니다.

기본적으로 폼 인증에서 브라우저는 사용자의 페이지를 캐시합니다. 따라서 브라우저 주소 상자 드롭 다운에서 직접 URL을 선택하거나 입력하면 브라우저 캐시에서 페이지를 가져올 수 있으며 서버로 돌아가 인증 / 권한을 확인하지 않아도됩니다. 이에 대한 해결책은 각 페이지의 Page_Load 이벤트 또는 기본 페이지의 OnLoad ()에서 클라이언트 측 캐싱을 방지하는 것입니다.

Response.Cache.SetCacheability(HttpCacheability.NoCache);

당신은 또한 전화를 원할 수도 있습니다 :

Response.Cache.SetNoStore();

11

나는 전에도 이것으로 고투했다.

여기에 무슨 일이 일어나고 있는지에 대한 비유가 있습니다 ... 새로운 방문자 Joe가 사이트에 와서 FormsAuthentication을 사용하여 로그인 페이지를 통해 로그인합니다. ASP.NET은 Joe의 새 ID를 생성하고 쿠키를 제공합니다. 그 쿠키는 집 열쇠와 같으며 Joe가 그 열쇠로 돌아 오는 한 자물쇠를 열 수 있습니다. 각 방문자에게는 새로운 열쇠와 새로운 자물쇠가 제공됩니다.

경우 FormsAuthentication.SignOut()라고합니다, 시스템은 키를 분실 할 조를 알려줍니다. Joe는 더 이상 열쇠를 가지고 있지 않기 때문에 정상적으로 작동합니다.

조 다시 돌아오고, 그러나 않는 그 잃어버린 열쇠를 가지고, 그는 다시하자입니다!

내가 알 수 있듯이 ASP.NET에 자물쇠를 변경하도록 지시 할 수있는 방법이 없습니다!

내가 이것을 살 수있는 방법은 세션 변수에서 Joe의 이름을 기억하는 것입니다. 그가 로그 아웃 할 때 세션을 포기하므로 ​​더 이상 그의 이름이 없습니다. 나중에 허용 여부를 확인하기 위해 자신의 Identity.Name을 현재 세션의 항목과 비교하고 일치하지 않으면 유효한 방문자가 아닙니다.

즉, 웹 사이트의 경우 User.Identity.IsAuthenticated세션 변수를 확인하지 않고 의존하지 마십시오 !


8
+ 1, 이것을 '쿠키 재생 공격'이라고합니다. FormsAuthentication.SignOut의 제한 사항에 대한 기사가 있습니다. support.microsoft.com/kb/900111
Dmitry

3
위의 링크를 따르려는 사람은 죽었습니다. WaybackMachine을 사용하여이 페이지의 사본을 얻을 수 있지만 즉시 사용자를 리디렉션하려고 시도합니다. web.archive.org/web/20171128133421/https://…
killa-byte

7

많은 검색 후 마침내 이것은 나를 위해 일했습니다. 도움이 되길 바랍니다.

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>

PHP로 몇 년 동안 웹 애플리케이션을 개발해 왔습니다. 그래서 나는 MVC를 처음 사용한다 ... 나는 그것을 좋아한다는 것을 인정한다. 그러나 누가 누군가를 로그 오프하는 것만 큼 단순한 것을 생각 했을까? 이 페이지의 다른 모든 스크립트를 아래로 시도했지만 이것이 유일하게 작동했습니다. 게시 해 주셔서 감사합니다!
Anthony Griggs

6

이것은 나를 위해 작동

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

3

게시 한 코드는 양식 인증 토큰을 올바르게 제거 해야하는 것처럼 보이므로 해당 폴더 / 페이지가 실제로 보호되지 않을 수 있습니다.

로그인하기 전에 페이지에 액세스 할 수 없음을 확인 했습니까?

사용중인 web.config 설정 및 로그인 코드를 게시 할 수 있습니까?


3

모든 페이지에 대한 기본 수업을 작성하고 있으며 같은 문제가 발생했습니다. 나는 다음과 같은 코드를 가지고 있었고 작동하지 않았다. 추적하면 제어가 경로 재 지정없이 RedirectToLoginPage () 문에서 다음 행으로 전달됩니다.

if (_requiresAuthentication)
{
    if (!User.Identity.IsAuthenticated)
        FormsAuthentication.RedirectToLoginPage();

    // check authorization for restricted pages only
    if (_isRestrictedPage) AuthorizePageAndButtons();
}

나는 두 가지 해결책이 있다는 것을 알았습니다. FormsAuthentication.RedirectToLoginPage ();를 수정하십시오. 되려고

if (!User.Identity.IsAuthenticated)
    Response.Redirect(FormsAuthentication.LoginUrl);

또는 추가하여 web.config를 수정하십시오.

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

두 번째 경우, 추적하는 동안 제어가 요청 된 페이지에 도달하지 않았습니다. 중단 점에 도달하기 전에 즉시 로그인 URL로 경로 재 지정되었습니다. 따라서 SignOut () 메서드는 문제가 아니며 redirect 메서드는 문제입니다.

누군가를 도울 수 있기를 바랍니다.

문안 인사


2
또한 FormsAuthentication.RedirectToLoginPage ()를 호출 한 직후 Response.End ()를 호출 할 수 있습니다
murki

MS 측에 약간의 오해가 있다고 생각합니다. 로그인 페이지로 돌아가려면 사람들을 잠 가야합니다. 그렇지 않으면 프레임 워크가 즐겁게 액세스 할 수 있습니다. 따라서이 게시물에서 솔루션 # 2를 말해야합니다.
Josh Robinson

3

방금 여기에 몇 가지 제안을 시도했지만 브라우저 뒤로 버튼을 사용할 수 있었지만 메뉴 선택을 클릭하면 해당 [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);
        }

브라우저의 뒤로 기능이 다시 돌아가서 보안 메뉴를 표시했지만 (나는 여전히 작업 중입니다) 앱에서 보호 된 작업을 수행 할 수 없었습니다.

도움이 되었기를 바랍니다


감사. 이것은 나를 위해 일한 솔루션입니다 ( <deny users="?" />web.config에서 필요 없음 )
Alexei

3

이 스레드에서 대부분의 답변을 시도했지만 운이 없습니다. 이것으로 끝났다 :

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

이 답변은 기술적으로 Khosro.Pakmanesh와 동일합니다. 그의 답변 이이 스레드의 다른 답변과 어떻게 다른지, 그리고 어떤 유스 케이스를 사용할 수 있는지 명확히하기 위해 게시하고 있습니다.

일반적으로 사용자 세션을 지우려면

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

효과적으로 사용자를 로그 아웃합니다. 그러나 동일한 요청에서 확인 Request.isAuthenticated필터에서 종종 발생할 수있는 것처럼 확인해야하는 경우 다음을 확인할 수 있습니다.

Request.isAuthenticated == true

심지어 _after 당신은했다 HttpContext.Session.Abandon()하고 FormsAuthentication.SignOut().

효과가 있었던 유일한 것은

AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);

효과적으로 설정합니다 Request.isAuthenticated = false.


2

에서 인증> 양식> 경로 속성 을 설정할 때이 문제가 발생 했습니다 Web.config. 이를 제거하면 문제가 해결되었으며 간단한 FormsAuthentication.SignOut();쿠키를 다시 제거했습니다.


1

하나의 하위 도메인 (sub1.domain.com)에서 로그인 한 다음 다른 하위 도메인 (www.domain.com)에서 로그 아웃하려고 할 수 있습니다.


1

방금 SignOut ()이 티켓을 올바르게 제거하지 못하는 것처럼 동일한 문제가 발생했습니다. 그러나 다른 논리가 리디렉션을 일으킨 특정 경우에만 해당됩니다. 이 두 번째 리디렉션을 제거한 후 (오류 메시지로 대체) 문제가 사라졌습니다.

문제는 페이지가 잘못된 시간에 리디렉션되어 인증을 트리거하지 않는 것입니다.


1

나는 지금 비슷한 문제를 겪고 있으며 원래의 포스터뿐만 아니라 제 경우의 문제는 리디렉션 때문이라고 생각합니다. 기본적으로 Response.Redirect는 예외가 발생하여 즉시 잡히고 리디렉션이 즉시 실행될 때까지 예외가 발생하여 수정 된 쿠키 모음이 클라이언트로 전달되는 것을 막고 있다고 생각합니다. 사용할 코드를 수정 한 경우 :

Response.Redirect("url", false);

이것은 예외를 방지하고 쿠키가 클라이언트로 올바르게 다시 전송되도록 허용하는 것 같습니다.


1

로그인을 누를 때 세션 변수를 보내십시오. 시작 페이지에서 먼저 페이지로드 또는 초기화 이벤트에서 해당 세션이 비어 있는지 확인하십시오.

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

1

나를 위해 다음과 같은 접근 방식이 효과적입니다. "FormsAuthentication.SignOut ()"문 뒤에 오류가 있으면 SingOut이 작동하지 않는다고 생각합니다.

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

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

0

IE를 사용하여이 동작을 테스트 /보고 있습니까? IE가 캐시에서 해당 페이지를 제공하고있을 수 있습니다. IE가 캐시를 플러시하도록하는 것은 악명 높으며, 로그 아웃 한 후에도 "보안 된"페이지 중 하나의 url을 입력하면 이전부터 캐시 된 컨텐츠가 표시됩니다.

(다른 사용자로 로그인 한 경우에도이 동작을 보았으며 IE는 페이지 상단에 이전 사용자의 사용자 이름과 함께 "환영"막대를 표시합니다. 요즘에는 일반적으로 새로 고침이 업데이트되지만 업데이트가 지속되는 경우 캐싱 문제 일 수 있습니다.)


0

Session.abandon ()하고 쿠키를 파괴하는 것은 꽤 효과적입니다. mvc3을 사용하고 있는데 보호 된 페이지로 이동하여 로그 아웃 한 후 브라우저 기록을 통해 문제가 발생하는 것 같습니다. 큰 문제는 아니지만 여전히 성가시다.

내 웹 앱의 링크를 통해 이동하려고하면 올바른 방식으로 작동합니다.

브라우저 캐싱을하지 않도록 설정하는 것이 좋습니다.


0

MVC의 경우 다음과 같이 작동합니다.

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

0

문제를 이해하는 데 도움이되는 정보를 추가하고 싶었습니다. 양식 인증을 사용하면 쿠키 또는 URL의 쿼리 문자열에 사용자 데이터를 저장할 수 있습니다. 사이트가 지원하는 방법은 web.config 파일에서 구성 할 수 있습니다.

Microsoft에 따르면 :

SignOut 메소드는 CookiesSupported가 false 인 경우 쿠키 또는 URL에서 양식 인증 티켓 정보를 제거합니다 .

동시에 그들은 말합니다 :

응용 프로그램이 쿠키없는 양식 인증을 위해 구성되었는지 여부를 나타내는 HttpCookieMode 값 중 하나입니다. 기본값은 UseDeviceProfile입니다 .

마지막으로 UseDeviceProfile과 관련하여 다음과 같이 말합니다 .

CookieMode 속성이 UseDeviceProfile로 설정되어 있으면 현재 요청 의 브라우저가 쿠키와 쿠키로 리디렉션을 모두 지원 하는 경우 CookiesSupported 속성이 true를 반환합니다 . 그렇지 않으면 CookiesSupported 속성이 false를 반환합니다.

사용자 브라우저에 따라이 구성을 모두 적용하면 기본 구성으로 인해 CookiesSupported가 true 가 될 수 있습니다 . 이는 SignOut 메소드가 쿠키에서 티켓을 지우지 않음을 의미합니다. 이것은 직관적이지 않은 것처럼 보이며 왜 이런 식으로 작동하는지 모르겠습니다. 실제로 SignOut이 어떤 상황에서도 사용자를 로그 아웃 할 것으로 기대합니다.

SignOut 자체를 작동시키는 한 가지 방법은 web.config 파일에서 쿠키 모드를 "UseCookies"(즉, 쿠키가 필요함)로 변경하는 것입니다.

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

내 테스트에 따르면 이렇게하면 쿠키가 제대로 작동하기 위해 사이트 비용으로 SignOut이 자체적으로 작동합니다.


나는 당신이 그것을 잘못 읽고 있다고 생각합니다. SignOut ()과 관련하여 CookiesSupported가 false 인 경우 URL에서 지워지고 그렇지 않으면 쿠키에서 지워진다는 것이 확실합니다. 즉, "SignOut 메소드는 쿠키에서 또는 쿠키에서 CookiesSupported가 false 인 경우 URL에서 폼 인증 티켓 정보를 제거합니다."라고 작성해야합니다.
Oskar Berggren

-1

WIF는 점에 유의 거부 STS에서 wsignoutcleanup 메시지가 IIS에서 응용 프로그램의 이름과 URL을 일치하지 않는 경우 정리에 쿠키를 브라우저에게, 그리고 평균 대소 문자를 구분합니다 . WIF는 녹색 확인 검사로 응답하지만 쿠키를 브라우저로 삭제하라는 명령을 보내지 않습니다 .

따라서 URL의 대소 문자 구분에주의를 기울여야합니다.

예를 들어, ThinkTecture Identity Server는 방문 RP의 URL을 하나의 쿠키에 저장하지만 모두 소문자로 만듭니다. WIF는 wsignoutcleanup 메시지를 소문자로 받아 IIS의 응용 프로그램 이름과 비교합니다. 일치하지 않으면 쿠키는 삭제되지 않지만 브라우저에 확인을보고합니다. 따라서이 Identity Server의 경우 이러한 문제를 피하기 위해 web.config의 모든 URL과 IIS의 모든 응용 프로그램 이름을 소문자로 작성해야했습니다.

또한 STS의 하위 도메인 외부에 응용 프로그램이있는 경우 브라우저에서 타사 쿠키를 허용하는 것을 잊지 마십시오. 그렇지 않으면 WIF가 알려주더라도 브라우저가 쿠키를 삭제하지 않습니다.


1
WIF? STS? ThinkTecture Identity Server? 이 모든 것이 무엇이며,이 질문과 어떻게 관련이 있습니까?
Oskar Berggren
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.