Pergunta

Bati minha cabeça contra isso um pouco demais.Como evito que um usuário navegue nas páginas de um site depois de ter sido desconectado usando FormsAuthentication.SignOut?Eu esperaria que isso acontecesse:

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

Mas isso não acontece.Se eu digitar um URL diretamente, ainda poderei navegar até a página.Faz algum tempo que não uso a segurança do tipo roll-your-own, então esqueço por que isso não funciona.

Foi útil?

Solução

Os usuários ainda podem navegar no seu site porque os cookies não são limpos quando você liga FormsAuthentication.SignOut() E eles são autenticados em cada nova solicitação. Na MS A documentação é diz que o cookie será liberado, mas não, bug? É exatamente o mesmo com Session.Abandon(), Cookie ainda está lá.

Você deve alterar seu código para isso:

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 está no System.Web espaço para nome. Referência do MSDN.

Outras dicas

Parece -me que você não tem sua seção de autorização Web.Config configurada corretamente dentro. Veja abaixo um exemplo.

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

Usando duas das postagens acima por X64igor e Phil Haselden resolveu o seguinte:

1. X64igor deu o exemplo para fazer o logout:

  • Você primeiro precisa Limpe o cookie de autenticação e o cookie de sessão Ao repassar os cookies vazios na resposta ao logout.

    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 deu o exemplo acima de como evitar o cache após o logout:

  • Você precisa Invalidar o cache no lado do cliente através da resposta.

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

A chave aqui é que você diz "se eu digitar um URL diretamente ...".

Por padrão, em Forms Autenticação, as páginas do navegador armazenam em cache para o usuário. Portanto, selecionar um URL diretamente no suspensão da caixa de endereço dos navegadores ou digitando -o pode obter a página do cache do navegador e nunca mais voltar ao servidor para verificar a autenticação/autorização. A solução para isso é impedir o cache do lado do cliente no evento Page_load de cada página ou no Onload () da sua página base:

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Você também pode gostar de ligar:

Response.Cache.SetNoStore();

Eu já lutei com isso antes também.

Aqui está uma analogia para o que parece estar acontecendo...Um novo visitante, Joe, chega ao site e faz login através da página de login usando FormsAuthentication.ASP.NET gera uma nova identidade para Joe e lhe dá um cookie.Esse biscoito é como a chave da casa e, desde que Joe retorne com essa chave, ele poderá abrir a fechadura.Cada visitante recebe uma nova chave e um novo cadeado para usar.

Quando FormsAuthentication.SignOut() é chamado, o sistema diz a Joe para perder a chave.Normalmente isso funciona, já que Joe não tem mais a chave, ele não consegue entrar.

No entanto, se Joe voltar, e faz se tiver aquela chave perdida, ele poderá entrar novamente!

Pelo que sei, não há como dizer ao ASP.NET para alterar a fechadura da porta!

A maneira de conviver com isso é lembrar o nome de Joe em uma variável de sessão.Quando ele sai, eu abandono a Sessão e não tenho mais o nome dele.Posteriormente, para verificar se ele tem permissão para entrar, simplesmente comparo seu Identity.Name com o que a sessão atual possui e, se não corresponderem, ele não é um visitante válido.

Resumindo, para um site, NÃO confie em User.Identity.IsAuthenticated sem também verificar suas variáveis ​​de sessão!

Isso funciona para mim

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

Depois de muita pesquisa, finalmente funcionou para mim. Espero que ajude.

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>

O código que você postou parece remover corretamente o token de autenticação de formulários, por isso é possível que as pastas/páginas em questão não estejam realmente protegidas.

Você confirmou que as páginas não podem ser acessadas antes que um login ocorra?

Você pode postar as configurações do Web.config e o código de login que está usando?

Escrevi uma classe base para todas as minhas páginas e cheguei ao mesmo problema. Eu tinha código como o seguinte e não funcionou. Ao rastrear, o controle passa da instrução redirectTologInpage () para a próxima linha sem ser redirecionada.

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

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

Eu descobri que existem duas soluções. Para modificar o formSAuthentication.RedirectTologInPage (); ser

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

Ou para modificar o web.config, adicionando

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

No segundo caso, durante o rastreamento, o controle não atingiu a página solicitada. Foi redirecionado imediatamente para o URL de login antes de atingir o ponto de interrupção. Portanto, o método Signout () não é o problema, o método de redirecionamento é o único.

Espero que isso possa ajudar alguém

Cumprimentos

Acabei de experimentar algumas das sugestões aqui e, embora pude usar o botão Back do navegador, quando cliquei em uma seleção de menu, o token [Authorize] para que o [ActionResult] me enviou de volta à tela de login.

Aqui está o meu código de logout:

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

Embora a função traseira no navegador tenha me levado de volta e exibisse o menu seguro (ainda estou trabalhando nisso), não consegui fazer nada que estivesse protegido no aplicativo.

Espero que isto ajude

Eu tentei a maioria das respostas neste tópico, sem sorte. Acabou com isso:

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

Encontrei aqui: http://forums.asp.net/t/1306526.aspx/1

Esta resposta é tecnicamente idêntica a Khosro.pakmanesh. Estou postando para esclarecer como a resposta dele difere de outras respostas neste tópico e no qual o caso de uso pode ser usado.

Em geral para limpar uma sessão do usuário, fazendo

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

irá efetivamente fazer logon o usuário. No entanto, se no mesmo pedido, você precisará verificar Request.isAuthenticated (Como pode acontecer com frequência em um filtro de autorização, por exemplo), então você encontrará que

Request.isAuthenticated == true

até _ depois de você fez HttpContext.Session.Abandon() e FormsAuthentication.SignOut().

A única coisa que funcionou foi fazer

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

Isso efetivamente define Request.isAuthenticated = false.

Isso começou a acontecer comigo quando eu defini o Autenticação> Forms> Propriedade do caminho dentro Web.config. Removendo que corrigiu o problema e um simples FormsAuthentication.SignOut(); novamente removeu o biscoito.

Pode ser que você esteja efetuando login a partir de um subdomínio (sub1.domain.com) e depois tentando fazer logout de um subdomínio diferente (www.domain.com).

Acabei de ter o mesmo problema, onde o Signout () aparentemente não conseguiu remover corretamente o ticket. Mas apenas em um caso específico, onde alguma outra lógica causou um redirecionamento. Depois de remover esse segundo redirecionamento (substituí -lo por uma mensagem de erro), o problema desapareceu.

O problema deve ter sido que a página foi redirecionada na hora errada, portanto, não desencadeando a autenticação.

Estou tendo um problema semelhante agora e acredito que o problema no meu caso e o pôster original é por causa do redirecionamento. Por padrão, uma resposta.Direct causa uma exceção que imediatamente borbulha até que seja capturada e o redirecionamento seja executado imediatamente, acho que isso está impedindo que a coleção de cookies modificada seja passada para o cliente. Se você modificar seu código para usar:

Response.Redirect("url", false);

Isso impede a exceção e parece permitir que o cookie seja enviado corretamente de volta ao cliente.

Basta tentar enviar uma variável de sessão ao pressionar o login. E na página de boas -vindas, verifique se a sessão está vazia assim na página Carregar ou no evento init:

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

Para mim, a seguinte abordagem funciona. Eu acho que se houver algum erro após a declaração "FormSauthentication.signout ()", Singout não funciona.

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

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

Você está testando/vendo esse comportamento usando o IE? É possível que o IE esteja servindo essas páginas do cache. É notoriamente difícil fazer com que o IE funcione seu cache e, em muitas ocasiões, mesmo depois de fazer o logout, digitar o URL de uma das páginas "garantidas" mostraria o conteúdo em cache de antes.

(Eu já vi esse comportamento mesmo quando você registra como um usuário diferente, e o IE mostra o bar "Welcome" no topo da sua página, com o nome de usuário do antigo usuário. Atualmente, geralmente um recarregamento o atualizará, mas se for persistente , ainda pode ser um problema de cache.)

Fazendo session.abandon () e destruir o cookie funciona muito bem. Estou usando o MVC3 e parece que o problema ocorre se você for a uma página protegida, logo sair e passar pelo histórico do seu navegador. Não é grande coisa, mas ainda é irritante.

Tentar passar por links no meu aplicativo da web funciona da maneira certa.

Definê -lo para não fazer o cache do navegador pode ser o caminho a seguir.

Para o MVC, isso funciona para mim:

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

Eu queria adicionar algumas informações para ajudar a entender o problema. A autenticação de formulários permite armazenar dados do usuário em um cookie ou na sequência de consulta do URL. O método que seu site suporta pode ser configurado no arquivo web.config.

De acordo com a Microsoft:

O método de inscrição remove as informações do ingresso de autenticação de formulários do cookie ou do URL Se Cookiessupported é falso.

Ao mesmo tempo, eles dizem:

Um dos valores HttpCookiemode que indica se o aplicativo está configurado para a autenticação de formulários de cozinheiro. o O padrão é usado oPROFILE.

Por fim, em relação ao UsoEviceProfile, eles dizem:

Se a propriedade Cookiemode for definida como UseviceProfile, o A propriedade CookiessUported retornará verdadeira se o navegador para o A solicitação atual suporta cookies e redirecionando com cookies; Caso contrário, a propriedade Cookiessupport retornará falsa.

Reunindo tudo isso tudo, dependendo do navegador do usuário, a configuração padrão pode resultar em ser apoiado verdadeiro, o que significa que o método de inscrição não limpa o bilhete do cookie. Isso parece contra-intuitivo e não sei por que funciona dessa maneira-eu esperaria que a inscrição assinasse o usuário em nenhuma circunstância.

Uma maneira de fazer a inscrição funcionar por si só é alterar o modo de cookie para "usecookies" (ou seja, cookies) no arquivo web.config:

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

De acordo com meus testes, fazer isso faz com que a inscrição funcione por si só, com o custo do seu site, agora exigindo que os cookies funcionem corretamente.

Esteja ciente de que wif recusa Para dizer ao navegador para limpar os cookies se a mensagem WSIGNOUTCLEANUP do STS não corresponde ao URL com o nome do aplicativo do IIS, e quero dizer MAIÚSCULAS E MINÚSCULAS. Wif responde com o verde verde, mas vai não Envie o comando para excluir cookies para o navegador.

Portanto, você precisa prestar atenção à sensibilidade do caso dos seus URLs.

Por exemplo, o ThinkTecture Identity Server salva os URLs dos RPs visitantes em um cookie, mas faz com que todos eles sejam minúsculos. WIF receberá a mensagem WSIGNOUTCLEANUP em minúsculas e a comparará com o nome do aplicativo no IIS. Se não corresponder, não exclui cookies, mas relatará ok para o navegador. Portanto, para este servidor de identidade, eu precisava escrever todos os URLs no web.config e todos os nomes de aplicativos no IIS em minúsculos, a fim de evitar esses problemas.

Além disso, não se esqueça de permitir biscoitos de terceiros no navegador se você tiver os aplicativos fora do subdomínio do STS, caso contrário, o navegador não excluirá os cookies, mesmo que WIF lhe diga.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top