Ignorar o redirecionamento automático de autenticação de formulários para login, como fazer?
-
09-06-2019 - |
Pergunta
Estou escrevendo um aplicativo usando asp.net-mvc, implantando no iis6.Estou usando autenticação de formulários.Normalmente, quando um usuário tenta acessar um recurso sem a devida autorização, quero que ele seja redirecionado para uma página de login.FormsAuth faz isso para mim com bastante facilidade.
Problema:Agora tenho uma ação acessada por um aplicativo de console.Qual é a maneira mais rápida de fazer com que esta ação responda com status 401 em vez de redirecionar a solicitação para a página de login?
Quero que o aplicativo de console seja capaz de reagir a este 401 StatusCode em vez de ser transparente.Também gostaria de manter o padrão, redirecionar solicitações não autorizadas para o comportamento da página de login.
Observação:Como teste, adicionei isso ao meu global.asax e não ignorou a autenticação de formulários:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpContext.Current.SkipAuthorization = true;
}
@Dale e Andy
Estou usando o AuthorizeAttributeFilter fornecido na visualização 4 do MVC.Isso está retornando um HttpUnauthorizedResult.Este resultado está configurando corretamente o statusCode como 401.O problema, pelo que entendi, é que o asp.net está interceptando a resposta (já que está marcada como 401) e redirecionando para a página de login em vez de apenas deixá-la passar.Quero ignorar essa interceptação para determinados URLs.
Solução
Ok, eu resolvi isso.Fiz um ActionResult personalizado (HttpForbiddenResult) e um ActionFilter personalizado (NoFallBackAuthorize).
Para evitar o redirecionamento, HttpForbiddenResult marca as respostas com o código de status 403.FormsAuthentication não captura respostas com este código, portanto o redirecionamento de login é efetivamente ignorado.O filtro NoFallBackAuthorize verifica se o usuário está autorizado de forma semelhante ao filtro Authorize incluído.A diferença é que retorna HttpForbiddenResult quando o acesso é negado.
O HttpForbiddenResult é bastante trivial:
public class HttpForbiddenResult : ActionResult { public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.HttpContext.Response.StatusCode = 0x193; // 403 } }
Não parece ser possível ignorar o redirecionamento da página de login no FormsAuthenticationModule.
Outras dicas
Pode ser um erro (e pode nem funcionar), mas na sua página de login veja se Request.QueryString["ReturnUrl"] != null
e se assim for definido Response.StatusCode = 401
.
Lembre-se de que você ainda precisará autenticar seu aplicativo de console de alguma forma.Você não obtém autenticação básica HTTP gratuitamente:você precisa criar o seu próprio, mas há muitas implementações por aí.
Você escreveu seu próprio atributo FormsAuth para a ação?Nesse caso, no método OnActionExecuting, você recebe o FilterExecutingContext.Você pode usar isso para devolver o código 401.
public class FormsAuth : ActionFilterAttribute
{
public override void OnActionExecuting(FilterExecutingContext filterContext)
{
filterContext.HttpContext.Response.StatusCode = 401;
filterContext.Cancel = true;
}
}
Isso deve funcionar.Não tenho certeza se você escreveu o atributo FormsAuth ou se o obteve de outro lugar.
Ainda não usei o AuthorizeAttribute que vem na Visualização 4.Eu criei o meu próprio, porque uso o framework MVC desde o primeiro CTP.Dei uma olhada rápida no atributo no refletor e ele está fazendo o que mencionei acima internamente, exceto que eles usam o equivalente hexadecimal de 401.Precisarei procurar mais adiante na chamada, para ver onde a exceção foi detectada, porque é mais do que provável que seja onde eles estão fazendo o redirecionamento.Esta é a funcionalidade que você precisará substituir.Não tenho certeza se você pode fazer isso ainda, mas postarei de volta quando encontrar e lhe darei uma solução alternativa, a menos que Haacked veja isso e publique ele mesmo.
Pesquisei no Google e foi isso que descobri:
HttpContext.Current.Response.StatusCode = 401;
Não tenho certeza se funciona ou não, não testei.De qualquer forma, vale a pena tentar, certo?:)