No ASP.NET MVC, você pode marcar um método de controlador com AuthorizeAttribute
, assim:
[Authorize(Roles = "CanDeleteTags")]
public void Delete(string tagName)
{
// ...
}
Isso significa que, se o usuário conectado no momento não estiver na função "CanDeleteTags", o método do controlador nunca será chamado.
Infelizmente, para falhas, AuthorizeAttribute
retorna HttpUnauthorizedResult
, que sempre retorna o código de status HTTP 401. Isso causa um redirecionamento para a página de login.
Se o usuário não estiver logado, isso faz todo o sentido. No entanto, se o usuário já estiver conectado, mas não estiver na função necessária, é confuso enviá-lo de volta à página de login.
Parece que AuthorizeAttribute
confunde autenticação e autorização.
Isso parece um pouco de supervisão no ASP.NET MVC, ou estou faltando alguma coisa?
Eu tive que preparar um DemandRoleAttribute
que separa os dois. Quando o usuário não é autenticado, ele retorna HTTP 401, enviando-o para a página de login. Quando o usuário está conectado, mas não está na função necessária, ele cria um NotAuthorizedResult
. Atualmente, isso é redirecionado para uma página de erro.
Certamente eu não precisava fazer isso?
fonte
Respostas:
Quando foi desenvolvido, o System.Web.Mvc.AuthorizeAttribute estava fazendo a coisa certa - as revisões mais antigas da especificação HTTP usavam o código de status 401 para "não autorizado" e "não autenticado".
A partir da especificação original:
De fato, você pode ver a confusão ali - ele usa a palavra "autorização" quando significa "autenticação". Na prática cotidiana, no entanto, faz mais sentido retornar um 403 Proibido quando o usuário é autenticado, mas não autorizado. É improvável que o usuário tenha um segundo conjunto de credenciais que lhes dê acesso - má experiência do usuário.
Considere a maioria dos sistemas operacionais - quando você tenta ler um arquivo que não tem permissão para acessar, não é exibida uma tela de login!
Felizmente, as especificações HTTP foram atualizadas (junho de 2014) para remover a ambiguidade.
Em "Protocolo de transporte de hipertexto (HTTP / 1.1): Autenticação" (RFC 7235):
Em "Protocolo de transferência de hipertexto (HTTP / 1.1): Semântica e conteúdo" (RFC 7231):
Curiosamente, no momento em que o ASP.NET MVC 1 foi lançado, o comportamento do AuthorizeAttribute estava correto. Agora, o comportamento está incorreto - a especificação HTTP / 1.1 foi corrigida.
Em vez de tentar alterar os redirecionamentos da página de login do ASP.NET, é mais fácil corrigir o problema na fonte. Você pode criar um novo atributo com o mesmo nome (
AuthorizeAttribute
) no espaço de nome padrão do seu site (isso é muito importante) e o compilador o buscará automaticamente em vez do padrão do MVC. Obviamente, você sempre pode atribuir um novo nome ao atributo se preferir usar essa abordagem.fonte
filterContext.HttpContext.User.Identity.IsAuthenticated
, você pode apenas verificarfilterContext.HttpContext.Request.IsAuthenticated
, que vem com verificações nulos construído em Sé. Stackoverflow.com/questions/1379566/...Adicione isso à sua função Page_Load de login:
Quando o usuário é redirecionado para lá, mas já está logado, ele mostra a página não autorizada. Se eles não estiverem conectados, ele será exibido e exibirá a página de login.
fonte
if (User.Identity != null && User.Identity.IsAuthenticated) return RedirectToRoute("Unauthorized");
onde não autorizado é um nome de rota definido.Eu sempre pensei que isso fazia sentido. Se você estiver conectado e tentar acessar uma página que exija uma função que não possui, você será encaminhado para a tela de login solicitando que efetue login com um usuário que possui essa função.
Você pode adicionar lógica à página de login que verifica se o usuário já está autenticado. Você pode adicionar uma mensagem amigável que explica por que eles foram levados de volta para lá novamente.
fonte
Infelizmente, você está lidando com o comportamento padrão da autenticação de formulários do ASP.NET. Há uma solução alternativa (ainda não tentei) discutida aqui:
http://www.codeproject.com/KB/aspnet/Custon401Page.aspx
(Não é específico para o MVC)
Penso que, na maioria dos casos, a melhor solução é restringir o acesso a recursos não autorizados antes que o usuário tente chegar lá. Removendo / esmaecendo o link ou botão que pode levá-los a esta página não autorizada.
Provavelmente seria bom ter um parâmetro adicional no atributo para especificar para onde redirecionar um usuário não autorizado. Entretanto, olho para o AuthorizeAttribute como uma rede de segurança.
fonte
Tente isso no manipulador Application_EndRequest do seu arquivo Global.ascx
fonte
Se você estiver usando o aspnetcore 2.0, use o seguinte:
fonte
No meu caso, o problema era "a especificação HTTP usava o código de status 401 para" não autorizado "e" não autenticado "". Como o ShadowChaser disse.
Esta solução funciona para mim:
fonte