Pergunta

A minha aplicação web tem uma página de login que as credenciais de autenticação submete via uma chamada de AJAX. Se o usuário digitar o nome de usuário e senha correta, está tudo bem, mas se não, acontece o seguinte:

  1. O servidor web determina que, embora o pedido incluía um cabeçalho de autorização bem formado, as credenciais no cabeçalho não autenticar com êxito.
  2. O servidor web retorna um código de status 401 e inclui um ou mais cabeçalhos WWW-Authenticate listando os tipos de autenticação suportados.
  3. O navegador detecta que a resposta à minha chamada no objeto XMLHttpRequest é um 401 e a resposta inclui cabeçalhos WWW-Authenticate. Em seguida, aparece um diálogo de autenticação pedir, novamente, para o nome de usuário e senha.

Isto é tudo muito bem até a etapa 3. Eu não quero o diálogo de pop-up, quero querer lidar com a resposta 401 na minha função AJAX callback. (Por exemplo, ao exibir uma mensagem de erro na página de login.) Eu quero o usuário para re-inserir seu nome de usuário e senha, é claro, mas eu quero que eles vejam o meu amigável, tranquilizando formulário de login, não do navegador feio, padrão autenticação de diálogo.

A propósito, eu não tenho nenhum controle sobre o servidor, então tê-lo retornar um código de status personalizada (ou seja, algo diferente de um 401) não é uma opção.

Existe alguma maneira eu posso suprimir o diálogo de autenticação? Em particular, eu posso suprimir o diálogo Autenticação exigida no Firefox 2 ou mais tarde? Existe alguma maneira para suprimir a Connect to [host] de diálogo no IE 6 e mais tarde?


Editar
Informações adicionais do autor (18 de setembro):
Devo acrescentar que o verdadeiro problema com diálogo de autenticação do navegador aparecendo é que ele dar informações suficientes para o usuário.

O usuário acaba de entrar um nome de usuário e senha através do formulário na página de login, ele acredita que ele tenha digitado os dois corretamente, e ele clicou no botão enviar ou aperte enter. Sua expectativa é que ele será levado para a página seguinte ou talvez disse que ele entrou sua informação de forma incorreta e deve tentar novamente. No entanto, ele é em vez apresentado com uma caixa de diálogo inesperado.

A janela não faz reconhecimento do fato de ele só se digite um nome de usuário e senha. Ele não afirma claramente que havia um problema e que ele deveria tentar novamente. Em vez disso, a caixa de diálogo apresenta ao usuário informação enigmática como "O site diz: ' [reino] '." Onde [reino] é um nome de domínio curto que apenas um programador poderia amar.

projetistas broswer Web tome nota: ninguém iria perguntar como para suprimir o diálogo de autenticação se o próprio diálogo eram simplesmente mais user-friendly. O inteira 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.

Foi útil?

Solução

Eu não acho que isso é possível - se você usa implementação do cliente HTTP do navegador, ele sempre irá aparecer esse diálogo. Dois hacks vêm à mente:

  1. Talvez o Flash lida com isso de forma diferente (eu ainda não tentou), assim que ter um filme flash fazer o Pedido de Ajuda força.

  2. Você pode configurar um 'proxie' para o serviço que você está acessando em seu próprio servidor, e tê-lo modificar os cabeçalhos de autenticação um pouco, para que o navegador não reconhecê-los.

Outras dicas

Eu encontrei o mesmo problema aqui, e o engenheiro backend na minha empresa implementou um comportamento que aparentemente é considerada uma boa prática: quando uma chamada para um URL retorna um 401, se o cliente não definiu o X-Requested-With: XMLHttpRequest cabeçalho, as gotas de servidor o cabeçalho www-authenticate na sua resposta.

O efeito colateral é que o pop-up de autenticação padrão não aparece.

Certifique-se de que a sua chamada API tem o conjunto de cabeçalho X-Requested-With para XMLHttpRequest. Se assim não há nada a fazer senão mudar o comportamento do servidor de acordo com esta boa prática ...

O navegador aparece um login prompt quando ambas as seguintes condições forem atendidas:

  1. status HTTP é 4xx
  2. cabeçalho WWW-Authenticate está presente na resposta

Se você pode controlar a resposta HTTP, então você pode remover o cabeçalho WWW-Authenticate a partir da resposta, e o navegador não irá aparecer a janela de autenticação.

Se você não pode controlar a resposta, você pode configurar um proxy para filtrar o cabeçalho WWW-Authenticate a partir da resposta.

Tanto quanto eu sei (sinta-se livre para me corrija se eu estiver errado), não há nenhuma maneira de evitar o login prompt de uma vez que o navegador recebe o cabeçalho WWW-Authenticate.

Sei que esta questão e suas respostas são muito antigos. Mas, acabei aqui. Talvez outros o farão também.

Se você tiver acesso ao código para o serviço Web que está retornando o 401. Basta alterar o serviço para retornar um 403 (Proibido) nesta situação, em vez 401. O navegador não solicitará credenciais em resposta a uma 403. 403 é o código correto para um usuário autenticado que não é autorizada para um recurso específico. Que parece ser a situação do OP.

A partir do documento IETF em 403:

Um servidor que recebe credenciais válidas que não são adequados para acesso ganho deve responder com a (proibido) código de status 403

Em Mozilla você pode conseguir isso com o seguinte script quando você cria o objeto XMLHttpRequest:

xmlHttp=new XMLHttpRequest();
xmlHttp.mozBackgroundRequest = true;
xmlHttp.open("GET",URL,true,USERNAME,PASSWORD);
xmlHttp.send(null);

O 2º impede de linha da caixa de diálogo ....

O que a tecnologia de servidor que você usa e se existe um produto específico que você usar para autenticação?

Uma vez que o navegador só está fazendo seu trabalho, eu acredito que você tem que mudar as coisas no lado do servidor para não retornar um código de 401 status. Isso pode ser feito usando as formas de autenticação personalizada que simplesmente devolver o formulário novamente quando a autenticação falhar.

terreno em Mozilla, definindo o parâmetro mozBackgroundRequest de XMLHttpRequest ( docs ) para true suprime esses diálogos e faz com que as solicitações para simplesmente falhar. No entanto, eu não sei o quão bom suporte cross-browser é (incluindo se a qualidade das informações de erro sobre os pedidos falhados é muito bom em todos os navegadores.)

jan.vdbergh tem a verdade, se você pode mudar a 401 no lado do servidor para outro código de status, o navegador não vai pegar e pintar o pop-up. Outra solução poderia ser alterar o cabeçalho WWW-Authenticate para outro cabeçalho personalizado. I dont't acreditar porque o navegador diferente não pode apoiá-lo, em algumas versões do Firefox que podemos fazer a solicitação xhr com mozBackgroundRequest, mas nos outros navegadores ?? aqui, há um interessante ligação com esta questão no Chromium.

Eu tenho esse mesmo problema com MVC 5 e VPN, onde sempre que estamos fora da DMZ usando a VPN, encontramo-nos ter que responder a esta mensagem browser. Usando .net Eu simplesmente lidar com o encaminhamento do erro usando

<customErrors defaultRedirect="~/Error"  >
  <error statusCode="401" redirect="~/Index"/>
</customErrors>

até agora tem funcionado porque a ação Index sob o controlador de casa valida o usuário. A vista nesta ação, se logon não for bem sucedida, tem controles de login que eu uso para fazer logon do usuário em usar usando consulta LDAP passou para serviços de diretório:

      DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain");
      DirectorySearcher Dsearch = new DirectorySearcher(entry);
      Dsearch.Filter = "(SAMAccountName=" + UserID + ")";
      Dsearch.PropertiesToLoad.Add("cn");

Enquanto isto tem funcionado muito bem até agora, e eu preciso que você saiba que eu ainda estou testando-o e o código acima não teve nenhuma razão para correr assim que é sujeito à remoção ... testando atualmente inclui tentando descobrir um caso em que o segundo conjunto de código é de mais qualquer uso. Mais uma vez, este é um trabalho em progresso, mas uma vez que poderia ser de alguma ajuda ou correr o seu cérebro para algumas idéias, eu decidi adicioná-lo agora ... Eu vou atualizá-lo com os resultados finais uma vez que todo o teste é feito.

Para aqueles C unsing aqui do # ActionAttribute que os retornos 400 vez de 401, e 'engole' Básico auth diálogo.

public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);
        filterContext.Result = new HttpStatusCodeResult(400);
    }
}

utilização como seguir:

[NoBasicAuthDialogAuthorize(Roles = "A-Team")]
public ActionResult CarType()
{
 // your code goes here
}

Hope isso poupa-lhe algum tempo.

Eu estou usando Node, Express & Passaporte e estava lutando com o mesmo problema. Eu tenho que trabalhar, definindo explicitamente o cabeçalho www-authenticate para uma cadeia vazia. No meu caso, que ficou assim:

(err, req, res, next) => {
  if (err) {
    res._headers['www-authenticate'] = ''
    return res.json(err)
  }
}

Espero que ajude alguém!

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