Como configuro meu projeto mvc / webapi para que um método webapi chamado de uma exibição de navalha não retorne a página de login quando ela não é autorizada?
É um aplicativo MVC5 que também possui controladores WebApi para chamadas via javascript.
Os dois métodos abaixo
[Route("api/home/LatestProblems")]
[HttpGet()]
public List<vmLatestProblems> LatestProblems()
{
// Something here
}
[Route("api/home/myLatestProblems")]
[HttpGet()]
[Authorize(Roles = "Member")]
public List<vmLatestProblems> mylatestproblems()
{
// Something there
}
são chamados pelo seguinte código angular:
angular.module('appWorship').controller('latest',
['$scope', '$http', function ($scope,$http) {
var urlBase = baseurl + '/api/home/LatestProblems';
$http.get(urlBase).success(function (data) {
$scope.data = data;
}).error(function (data) {
console.log(data);
});
$http.get(baseurl + '/api/home/mylatestproblems')
.success(function (data) {
$scope.data2 = data;
}).error(function (data) {
console.log(data);
});
}]
);
Portanto, não estou logado e o primeiro método retorna dados com êxito. o segundo método retorna (na função de sucesso) dados que contêm o equivalente a uma página de login. ou seja, o que você obteria no mvc se solicitasse uma ação do controlador que estivesse estampada com [Autorizar] e você não estivesse logado.
Quero que ele retorne um 401 não autorizado, para que eu possa exibir dados diferentes para os usuários com base em se eles estão conectados ou não. Idealmente, se o usuário estiver conectado, desejo poder acessar a propriedade User do Controlador para que eu possa retornar dados específicos para esse Membro.
ATUALIZAÇÃO: Como nenhuma das sugestões abaixo parece funcionar mais (alterações em Identity ou WebAPI), criei um exemplo bruto no github que deve ilustrar o problema.
Brock Allen tem um bom post sobre como retornar 401 para chamadas ajax ao usar autenticação de cookie e OWIN. http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/
Coloque isso no método ConfigureAuth no arquivo Startup.Auth.cs:
fonte
/api
, você pode usar o caminho para determinar se deve redirecionar. É especialmente útil se você tiver clientes que usam outros formatos como JSON. Substitua a chamada porIsAjaxRequest
comif (!context.Request.Path.StartsWithSegments(new PathString("/api")))
.private static bool IsAjaxRequest(IOwinRequest request) { return request.Query?["X-Requested-With"] == "XMLHttpRequest" || request.Headers?["X-Requested-With"] == "XMLHttpRequest"; }
Se você estiver adicionando WebApi do asp.net no site MVC do asp.net, provavelmente desejará responder não autorizado a algumas solicitações. Mas a infraestrutura do ASP.NET entra em jogo e, quando você tenta definir o código de status da resposta como HttpStatusCode.Unauthorized, você recebe o redirecionamento 302 para a página de login.
Se você estiver usando a identidade asp.net e a autenticação baseada em owin aqui, um código que pode ajudar a resolver esse problema:
fonte
Eu tenho a mesma situação quando o OWIN sempre redireciona a resposta 401 para a página de login da WebApi. Nossa API da Web suporta não apenas chamadas ajax de Angular, mas também chamadas móveis, Win Form. Portanto, a solução para verificar se a solicitação é ajax não está realmente classificada para o nosso caso.
Suppress-Redirect
Optei por outra abordagem: injetar uma nova resposta de cabeçalho: se as respostas vierem do webApi. A implementação está no manipulador:E registre esse manipulador no nível global da WebApi:
Portanto, na inicialização do OWIN, você pode verificar se o cabeçalho de resposta possui
Suppress-Redirect
:fonte
Nas versões anteriores do ASP.NET, você precisava fazer várias coisas para fazer isso funcionar.
A boa notícia é que você está usando o ASP.NET 4.5. você pode desativar o redirecionamento da autenticação de formulários usando o novo propriedade HttpResponse.SuppressFormsAuthenticationRedirect .
Em
Global.asax
:EDIT : você também pode querer dar uma olhada neste artigo de Sergey Zwezdin, que tem uma maneira mais refinada de realizar o que você está tentando fazer.
Trechos de código relevantes e narração do autor colados abaixo. Autor original do código e narração - Sergey Zwezdin .
Primeiro - vamos determinar se a solicitação HTTP atual é uma solicitação AJAX. Se sim, devemos desativar a substituição do HTTP 401 pelo HTTP 302:
Segundo - vamos adicionar uma condição :: se o usuário for autenticado, enviaremos HTTP 403; e HTTP 401 caso contrário.
Bem feito. Agora devemos substituir todos os usos do AuthorizeAttribute padrão por esse novo filtro. Pode não ser aplicável para sime guys, que é um esteta de código. Mas não conheço outra maneira. Se você tiver, vamos aos comentários, por favor.
O último, o que devemos fazer - adicionar o tratamento HTTP 401/403 no lado do cliente. Podemos usar ajaxError no jQuery para evitar duplicação de código:
O resultado -
fonte
Se você estiver executando o seu
Web API
de dentro do seuMVC
projeto, precisará criar um personalizadoAuthorizeAttribute
para aplicar aos seusAPI
métodos. Dentro do arquivo,IsAuthorized
override
você precisa pegar a correnteHttpContext
para impedir o redirecionamento, assim:fonte
Usando a integração do Azure Active Directory, a abordagem do
CookieAuthentication
middleware não funcionou para mim. Eu tive que fazer o seguinte:Se a solicitação vier do próprio navegador (e não uma chamada AJAX, por exemplo), o cabeçalho Accept conterá a string
html
em algum lugar. Somente quando o cliente aceitar HTML, considerarei um redirecionamento algo útil.Meu aplicativo cliente pode lidar com o 401 informando ao usuário que o aplicativo não tem mais acesso e precisa recarregar para fazer login novamente.
fonte
Eu também tinha um aplicativo MVC5 (System.Web) com WebApi (usando OWIN) e só queria impedir que 401 respostas do WebApi fossem alteradas para 302 respostas.
O que funcionou para mim foi criar uma versão personalizada do WebApi AuthorizeAttribute assim:
E para usá-lo no lugar do WebApi AuthorizeAttribute padrão. Usei o MVC AuthorizeAttribute padrão para manter o comportamento do MVC inalterado.
fonte
SuppressFormsAuthenticationRedirect
bandeira fez com que ela retornasse apenas o 401 existente para mim.Basta instalar seguindo o Pacote NeGet
Pacote de instalação Microsoft.AspNet.WebApi.Owin
Escreva o seguinte código no arquivo WebApiConfig.
fonte
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
caso contrário,User.Identity.IsAuthenticated
é semprefalse
se você deseja capturar Content-Type == application / json, pode usar esse código:
Saudações!!
fonte
Eu estava com dificuldade para obter o código de status e uma resposta de texto trabalhando nos métodos OnAuthorization / HandleUnauthorizedRequest. Essa acabou sendo a melhor solução para mim:
fonte
Após muita confusão tentando evitar os redirecionamentos para a página de login, percebi que isso é realmente bastante apropriado para o atributo Autorizar. Está dizendo vá e obtenha autorização. Em vez disso, para chamadas da API que não são autorizadas, eu só queria não revelar nenhuma informação a hackers. Esse objetivo foi mais fácil de alcançar diretamente, adicionando um novo atributo derivado de Authorize, que oculta o conteúdo como um erro 404:
fonte
Misturando MVC e WebAPI, se a solicitação não for autorizada, ele será redirecionado para a página de login, mesmo na solicitação WebAPI também. Para isso, podemos adicionar o código abaixo para enviar uma resposta ao aplicativo móvel
fonte
Obrigado rapazes!
No meu caso, combinei as respostas de cuongle e Shiva e obtive algo parecido com isto:
No manipulador OnException () do controlador para exceções da API:
No código de configuração de inicialização do aplicativo:
fonte
No MVC 5 com o Dot Net Framework 4.5.2, estamos obtendo "application / json, texto de reclamação .." no cabeçalho "Aceitar" Será bom usar o seguinte:
fonte