Meu aplicativo da web tem uma página de login que envia credenciais de autenticação por meio de uma chamada AJAX. Se o usuário inserir o nome de usuário e a senha corretos, está tudo bem, mas se não, acontece o seguinte:
- O servidor da web determina que, embora a solicitação inclua um cabeçalho de autorização bem formado, as credenciais no cabeçalho não são autenticadas com êxito.
- O servidor da web retorna um código de status 401 e inclui um ou mais cabeçalhos WWW-Authenticate listando os tipos de autenticação suportados.
- O navegador detecta que a resposta à minha chamada no objeto XMLHttpRequest é um 401 e a resposta inclui cabeçalhos WWW-Authenticate. Em seguida, ele exibe uma caixa de diálogo de autenticação pedindo, novamente, o nome de usuário e a senha.
Isso está tudo bem até a etapa 3. Não quero que a caixa de diálogo seja exibida, quero lidar com a resposta 401 em minha função de retorno de chamada AJAX. (Por exemplo, exibindo uma mensagem de erro na página de login.) Quero que o usuário insira novamente seu nome de usuário e senha, é claro, mas quero que eles vejam meu formulário de login amigável e reconfortante, não o padrão feio do navegador caixa de diálogo de autenticação.
A propósito, não tenho controle sobre o servidor, portanto, fazer com que ele retorne um código de status personalizado (ou seja, algo diferente de 401) não é uma opção.
Existe alguma maneira de suprimir a caixa de diálogo de autenticação? Em particular, posso suprimir a caixa de diálogo Autenticação necessária no Firefox 2 ou posterior? Existe alguma maneira de suprimir a caixa de diálogo Conectar a [host] no IE 6 e posterior?
Editar
Informações adicionais do autor (18 de setembro):
Devo acrescentar que o verdadeiro problema com a caixa de diálogo de autenticação do navegador que aparece é que ela fornece informações insuficientes ao usuário.
O usuário acabou de inserir um nome de usuário e senha através do formulário na página de login, ele acredita que digitou ambos corretamente e clicou no botão enviar ou apertou enter. Sua expectativa é que ele seja levado para a próxima página ou talvez seja informado de que inseriu suas informações incorretamente e deve tentar novamente. No entanto, ele é apresentado a uma caixa de diálogo inesperada.
O diálogo não faz reconhecimento do fato de que ele apenas fez entrar um nome de usuário e senha. Não indica claramente que houve um problema e que ele deve tentar novamente. Em vez disso, a caixa de diálogo apresenta ao usuário informações criptografadas como "O site diz: ' [reino] '." Onde [realm] é um nome curto de domínio que apenas um programador poderia amar.
Os designers do navegador da Web, tome nota: ninguém perguntaria como suprimir a caixa de diálogo de autenticação se a caixa de diálogo em si fosse simplesmente mais amigável. O toda razão que eu estou fazendo um formulário de login é que nossa equipe de gerenciamento de produto considera justamente diálogos de autenticação dos navegadores para ser terrível.
Respostas:
Eu não acho que isso seja possível - se você usar a implementação de cliente HTTP do navegador, essa caixa de diálogo sempre aparecerá. Dois hacks vêm à mente:
Talvez o Flash lide com isso de forma diferente (eu não tentei ainda), então ter um filme em flash para fazer o pedido pode ajudar.
Você pode configurar um 'proxy' para o serviço que está acessando em seu próprio servidor e fazer com que ele modifique um pouco os cabeçalhos de autenticação, para que o navegador não os reconheça.
fonte
Encontrei o mesmo problema aqui, e o engenheiro de back-end da minha empresa implementou um comportamento que aparentemente é considerado uma boa prática: quando uma chamada para um URL retorna um 401, se o cliente definiu o cabeçalho
X-Requested-With: XMLHttpRequest
, o servidor descarta owww-authenticate
cabeçalho em resposta.O efeito colateral é que o pop-up de autenticação padrão não aparece.
Certifique-se de que sua chamada de API tenha o
X-Requested-With
cabeçalho definido comoXMLHttpRequest
. Nesse caso, não há nada a fazer exceto mudar o comportamento do servidor de acordo com esta boa prática ...fonte
DelegatingAuthenticationEntryPoint
tratará desse comportamento para você.O navegador exibe um prompt de login quando as duas condições a seguir são atendidas:
WWW-Authenticate
cabeçalho está presente na respostaSe você puder controlar a resposta HTTP, poderá remover o
WWW-Authenticate
cabeçalho da resposta e o navegador não abrirá a caixa de diálogo de login.Se você não pode controlar a resposta, você pode configurar um proxy para filtrar o
WWW-Authenticate
cabeçalho da resposta.Pelo que eu sei (sinta-se à vontade para me corrigir se eu estiver errado), não há como evitar o prompt de login depois que o navegador recebe o
WWW-Authenticate
cabeçalho.fonte
WWW-Authenticate
valores de cabeçalho válidos , consulte stackoverflow.com/a/1748451/225217Eu percebo que essa pergunta e suas respostas são muito antigas. Mas, acabei aqui. Talvez outros o façam também.
Se você tiver acesso ao código para o serviço da web que está retornando o 401. Basta alterar o serviço para retornar um 403 (Proibido) nesta situação em vez de 401. O navegador não solicitará as credenciais em resposta a um 403. 403 é o código correto para um usuário autenticado que não está autorizado para um recurso específico. Qual parece ser a situação do OP.
Do documento IETF em 403:
Um servidor que recebe credenciais válidas que não são adequadas para obter acesso deve responder com o código de status 403 (Proibido)
fonte
No Mozilla, você pode conseguir isso com o seguinte script ao criar o objeto XMLHttpRequest:
xmlHttp=new XMLHttpRequest(); xmlHttp.mozBackgroundRequest = true; xmlHttp.open("GET",URL,true,USERNAME,PASSWORD); xmlHttp.send(null);
A 2ª linha impede a caixa de diálogo ....
fonte
Qual tecnologia de servidor você usa e há um produto específico que você usa para autenticação?
Como o navegador está apenas fazendo seu trabalho, acredito que você tenha que mudar as coisas no lado do servidor para não retornar um código de status 401. Isso pode ser feito usando formulários de autenticação personalizados que simplesmente retornam o formulário novamente quando a autenticação falha.
fonte
No Mozilla Land, definir o parâmetro mozBackgroundRequest de XMLHttpRequest ( docs ) como true suprime esses diálogos e faz com que as solicitações simplesmente falhem. No entanto, não sei quão bom é o suporte para vários navegadores (incluindo se a qualidade das informações de erro nessas solicitações com falha é muito boa em todos os navegadores).
fonte
jan.vdbergh tem a verdade, se você puder alterar o 401 no lado do servidor por outro código de status, o navegador não pegará e pintará o pop-up. Outra solução poderia ser alterar o cabeçalho WWW-Authenticate para outro cabeçalho personalizado. Não acredito porque o navegador diferente não suporta isso, em algumas versões do Firefox podemos fazer a solicitação xhr com mozBackgroundRequest, mas nos outros navegadores ?? aqui, há um link interessante com esse problema no Chromium.
fonte
Eu tenho esse mesmo problema com MVC 5 e VPN, onde sempre que estamos fora da DMZ usando a VPN, temos que responder a esta mensagem do navegador. Usando .net, eu simplesmente lido com o roteamento do erro usando
<customErrors defaultRedirect="~/Error" > <error statusCode="401" redirect="~/Index"/> </customErrors>
até agora funcionou porque a ação Index no controlador home valida o usuário. A visualização nesta ação, se o logon não for bem-sucedido, tem controles de login que eu uso para fazer o login do usuário usando a consulta LDAP passada nos serviços de diretório:
DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain"); DirectorySearcher Dsearch = new DirectorySearcher(entry); Dsearch.Filter = "(SAMAccountName=" + UserID + ")"; Dsearch.PropertiesToLoad.Add("cn");
Embora tenha funcionado bem até agora, devo informar que ainda estou testando e o código acima não teve nenhum motivo para ser executado, por isso está sujeito a remoção ... o teste atualmente inclui tentar descobrir um caso em que o segundo conjunto de código é mais útil. Novamente, este é um trabalho em andamento, mas como pode ser de alguma ajuda ou estimular seu cérebro para algumas ideias, decidi adicioná-lo agora ... Vou atualizá-lo com os resultados finais quando todos os testes forem concluídos.
fonte
Estou usando o Node, Express e Passport e estava lutando com o mesmo problema. Comecei a trabalhar definindo explicitamente o
www-authenticate
cabeçalho como uma string vazia. No meu caso, era assim:(err, req, res, next) => { if (err) { res._headers['www-authenticate'] = '' return res.json(err) } }
Espero que ajude alguém!
fonte
Para aqueles C # unsing, aqui está
ActionAttribute
que retorna em400
vez de401
e 'engole' a caixa de diálogo de autenticação básica.public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { base.HandleUnauthorizedRequest(filterContext); filterContext.Result = new HttpStatusCodeResult(400); } }
use como a seguir:
[NoBasicAuthDialogAuthorize(Roles = "A-Team")] public ActionResult CarType() { // your code goes here }
Espero que isso economize algum tempo.
fonte