Estou usando $.post()
para chamar um servlet usando Ajax e, em seguida, usando o fragmento HTML resultante para substituir um div
elemento na página atual do usuário. No entanto, se a sessão atingir o tempo limite, o servidor envia uma diretiva de redirecionamento para enviar o usuário à página de logon. Nesse caso, o jQuery está substituindo o div
elemento pelo conteúdo da página de login, forçando os olhos do usuário a testemunhar uma cena rara.
Como gerenciar uma diretiva de redirecionamento de uma chamada Ajax com o jQuery 1.2.6?
javascript
jquery
ajax
redirect
Elliot Vargas
fonte
fonte
HttpContext.Response.AddHeader
e check no sucesso do ajaxsetup é o caminho a seguirRespostas:
Li essa pergunta e implementei a abordagem que foi declarada em relação à configuração do código de status HTTP da resposta como 278, a fim de evitar que o navegador manipule de maneira transparente os redirecionamentos. Embora isso tenha funcionado, fiquei um pouco insatisfeito, pois é um pouco complicado.
Após mais pesquisas, abandonei essa abordagem e usei o JSON . Nesse caso, todas as respostas às solicitações AJAX têm o código de status 200 e o corpo da resposta contém um objeto JSON que é construído no servidor. O JavaScript no cliente pode então usar o objeto JSON para decidir o que ele precisa fazer.
Eu tive um problema semelhante ao seu. Realizo uma solicitação AJAX com 2 respostas possíveis: uma que redireciona o navegador para uma nova página e outra que substitui um formulário HTML existente na página atual por um novo. O código jQuery para fazer isso se parece com:
O objeto JSON "data" é construído no servidor para ter 2 membros:
data.redirect
edata.form
. Eu achei essa abordagem muito melhor.fonte
Resolvi esse problema:
Incluindo um cabeçalho personalizado na resposta:
Vinculando uma função JavaScript ao
ajaxSuccess
evento e verificando se o cabeçalho existe:fonte
Nenhum navegador manipula as respostas 301 e 302 corretamente. E, de fato, o padrão até diz que eles devem lidar com eles "de forma transparente", o que é uma enorme dor de cabeça para os fornecedores da Biblioteca Ajax. No Ra-Ajax , fomos forçados a usar o código de status de resposta HTTP 278 (apenas alguns códigos de sucesso "não utilizados") para manipular redirecionamentos transparentes do servidor ...
Isso realmente me irrita, e se alguém aqui tem alguma "puxar" em W3C Eu apreciaria que você poderia deixar W3C saber que nós realmente precisamos para lidar com 301 e 302 códigos de nós mesmos ...! ;)
fonte
A solução que acabou sendo implementada foi usar um wrapper para a função de retorno de chamada da chamada Ajax e, nesse wrapper, verifique a existência de um elemento específico no pedaço HTML retornado. Se o elemento foi encontrado, o wrapper executou um redirecionamento. Caso contrário, o wrapper encaminhará a chamada para a função de retorno de chamada real.
Por exemplo, nossa função de wrapper era algo como:
Então, ao fazer a chamada do Ajax, usamos algo como:
Isso funcionou para nós porque todas as chamadas do Ajax sempre retornavam HTML dentro de um elemento DIV que usamos para substituir um pedaço da página. Além disso, precisamos apenas redirecionar para a página de login.
fonte
Gosto do método de Timmerz com um leve toque de limão. Se você receber um contentType de texto / html retornado quando espera JSON , provavelmente será redirecionado. No meu caso, simplesmente recarrego a página e ela é redirecionada para a página de login. Ah, e verifique se o status do jqXHR é 200, o que parece bobagem, porque você está na função de erro, certo? Caso contrário, os casos de erro legítimos forçarão uma recarga iterativa (oops)
fonte
Use a
$.ajax()
chamada de baixo nível :Tente isso para um redirecionamento:
fonte
Eu só queria compartilhar minha abordagem, pois isso pode ajudar alguém:
Basicamente, incluí um módulo JavaScript que lida com as coisas de autenticação, como exibir o nome de usuário e, neste caso, manipular o redirecionamento para a página de login .
Meu cenário: Basicamente, temos um servidor ISA entre o qual ouve todas as solicitações e responde com um cabeçalho 302 e um local na nossa página de login.
No meu módulo JavaScript, minha abordagem inicial foi algo como
O problema (como muitos aqui já mencionados) é que o navegador lida com o redirecionamento por si só, portanto, meu
ajaxComplete
retorno de chamada nunca foi chamado, mas recebi a resposta da página de login já redirecionada, que obviamente era umastatus 200
. O problema: como você detecta se a resposta 200 bem-sucedida é sua página de login real ou apenas alguma outra página arbitrária?A solução
Como não consegui capturar 302 respostas de redirecionamento, adicionei um
LoginPage
cabeçalho na minha página de login que continha o URL da própria página de login. No módulo, agora escuto o cabeçalho e faço um redirecionamento:... e isso funciona como charme :). Você pode se perguntar por que eu incluo o URL no
LoginPage
cabeçalho ... bem, basicamente porque não encontrei uma maneira de determinar o URLGET
resultante do redirecionamento automático de localização doxhr
objeto ...fonte
X-
um cabeçalho melhor para usarX-LoginPage: http://example.com/login
.X-
.Sei que esse tópico é antigo, mas darei outra abordagem que encontrei e descrevi anteriormente aqui . Basicamente, estou usando o ASP.MVC com WIF (mas isso não é realmente importante para o contexto deste tópico - a resposta é adequada, independentemente de quais estruturas sejam usadas. A pista permanece inalterada - lidando com problemas relacionados a falhas de autenticação durante a execução de solicitações de ajax ) .
A abordagem mostrada abaixo pode ser aplicada a todas as solicitações de ajax prontas para uso (se elas não redefinirem antes do evento SendS obviamente).
Antes de qualquer solicitação ajax ser executada, o
CheckPulse
método é chamado (o método do controlador, que pode ser qualquer coisa mais simples):Se o usuário não estiver autenticado (o token expirou), esse método não poderá ser acessado (protegido pelo
Authorize
atributo). Como a estrutura lida com autenticação, enquanto o token expira, coloca o status http 302 na resposta. Se você não deseja que seu navegador lide com a resposta 302 de forma transparente, pegue-o no Global.asax e altere o status da resposta - por exemplo, para 200 OK. Além disso, adicione o cabeçalho, que instrui você a processar essa resposta de maneira especial (posteriormente no lado do cliente):Finalmente, no lado do cliente, verifique esse cabeçalho personalizado. Se presente - o redirecionamento completo para a página de logon deve ser feito (no meu caso,
window.location
é substituído por url da solicitação, que é tratada automaticamente pela minha estrutura).fonte
Eu acho que a melhor maneira de lidar com isso é aproveitar os códigos de resposta do protocolo HTTP existentes, especificamente
401 Unauthorized
.Aqui está como eu resolvi:
Lado do cliente: vincular-se aos eventos do ajax
Na IMO, isso é mais genérico e você não está escrevendo algumas novas especificações / cabeçalho personalizados. Você também não deve modificar nenhuma das chamadas ajax existentes.
Edit: Pelo comentário de @ Rob abaixo, 401 (o código de status HTTP para erros de autenticação) deve ser o indicador. Consulte 403 Respostas HTTP proibidas vs 401 não autorizadas para obter mais detalhes. Com isso dito, algumas estruturas da Web usam 403 para erros de autenticação e autorização - portanto, adapte-se de acordo. Obrigado Rob.
fonte
Resolvi esse problema da seguinte maneira:
Adicione um middleware para processar a resposta; se for um redirecionamento para uma solicitação ajax, altere a resposta para uma resposta normal com o URL de redirecionamento.
Em ajaxComplete, se a resposta contiver redirecionamento, ele deverá ser um redirecionamento; portanto, altere o local do navegador.
fonte
Eu tenho uma solução simples que funciona para mim, não é necessário alterar o código do servidor ... basta adicionar uma colher de chá de noz-moscada ...
Verifico a presença da tag html, mas você pode alterar o indexOf para procurar por qualquer string exclusiva que exista na sua página de login ...
fonte
Outra solução que eu encontrei (especialmente útil se você quiser definir um comportamento global) é usar o
$.ajaxsetup()
método em conjunto com astatusCode
propriedade . Como outros apontaram, não use um código de status de redirecionamento (3xx
), use um4xx
código de status e lide com o redirecionamento do lado do cliente.Substitua
400
pelo código de status que você deseja manipular. Como já mencionado,401 Unauthorized
pode ser uma boa ideia. Uso o400
dado que é muito inespecífico e posso usá-lo401
para casos mais específicos (como credenciais de logon incorretas). Portanto, em vez de redirecionar diretamente, o back-end deve retornar um4xx
código de erro quando a sessão expirar e você lida com o redirecionamento do lado do cliente. Funciona perfeito para mim, mesmo com estruturas como o backbone.jsfonte
A maioria das soluções fornecidas usa uma solução alternativa, usando um cabeçalho extra ou um código HTTP inapropriado. Essas soluções provavelmente funcionarão, mas parecerão um pouco "hacky". Eu vim com outra solução.
Estamos usando o WIF configurado para redirecionar (passiveRedirectEnabled = "true") em uma resposta 401. O redirecionamento é útil ao lidar com solicitações normais, mas não funciona para solicitações AJAX (já que os navegadores não executam o 302 / redirecionamento).
Usando o código a seguir no seu global.asax, você pode desativar o redirecionamento para solicitações AJAX:
Isso permite que você retorne 401 respostas para solicitações AJAX, que seu javascript pode manipular recarregando a página. Recarregar a página lançará um 401, que será tratado pelo WIF (e o WIF redirecionará o usuário para a página de login).
Um exemplo de javascript para manipular erros 401:
fonte
Esse problema pode aparecer em seguida, usando o método ASP.NET MVC RedirectToAction. Para impedir que o formulário exiba a resposta em div, você pode simplesmente fazer algum tipo de filtro de resposta ajax para respostas recebidas com $ .ajaxSetup . Se a resposta contiver redirecionamento MVC, você poderá avaliar esta expressão no lado JS. Exemplo de código para JS abaixo:
Se os dados forem: "window.location = '/ Acount / Login'" acima do filtro, será capturado e avaliado para fazer o redirecionamento em vez de permitir que os dados sejam exibidos.
fonte
data
está no corpo ou no cabeçalho da resposta?Reunindo o que Vladimir Prudnikov e Thomas Hansen disseram:
Isso faz com que o navegador trate a resposta como um sucesso e entregue-a ao seu Javascript.
fonte
fonte
Tentar
Coloque-o na página de login. Se ele foi carregado em uma div na página principal, será redirecionado até a página de login. "#site" é um ID de uma div localizada em todas as páginas, exceto na página de login.
fonte
Embora as respostas pareçam funcionar para as pessoas, se você estiver usando o Spring Security, achei a extensão do LoginUrlAuthenticationEntryPoint e a adição de código específico para lidar com o AJAX de maneira mais robusta. A maioria dos exemplos intercepta todos os redirecionamentos, não apenas falhas de autenticação. Isso era indesejável para o projeto em que trabalho. Talvez seja necessário estender o ExceptionTranslationFilter e substituir o método "sendStartAuthentication" para remover a etapa de armazenamento em cache se você não desejar que a solicitação AJAX com falha seja armazenada em cache.
Exemplo AjaxAwareAuthenticationEntryPoint:
Fontes: 1 , 2
fonte
Resolvi isso colocando o seguinte na minha página login.php.
fonte
Deixe-me apenas citar novamente o problema, conforme descrito por @Steg
IMHO, este é um desafio real e terá que ser oficialmente estendido aos padrões HTTP atuais.
Acredito que o novo Http Standard será usar um novo código de status. significado: atualmente
301/302
diz ao navegador para buscar o conteúdo desta solicitação em um novolocation
.No padrão estendido, ele dirá que, se a resposta
status: 308
(apenas um exemplo), o navegador deve redirecionar a página principal para o diretóriolocation
fornecida.Dito isto; Estou inclinado a imitar esse comportamento futuro e, portanto, quando um document.redirect é necessário, o servidor responde como:
Quando JS obtém o "
status: 204
", ele verifica a existência dox-status: 308
cabeçalho e faz um document.redirect para a página fornecida nolocation
cabeçalho.Isso faz algum sentido para você?
fonte
Alguns podem achar o útil abaixo:
Eu queria que os clientes fossem redirecionados para a página de login para qualquer ação de descanso enviada sem um token de autorização. Como todas as minhas ações restantes são baseadas no Ajax, eu precisava de uma boa maneira genérica de redirecionar para a página de login, em vez de manipular a função de sucesso do Ajax.
Isto é o que eu fiz:
Em qualquer solicitação do Ajax, meu servidor retornará uma resposta do Json 200 "PRECISA AUTENTICAR" (se o cliente precisar se autenticar).
Exemplo simples em Java (lado do servidor):
No meu Javascript, adicionei o seguinte código:
E é sobre isso.
fonte
no servlet que você deve colocar
response.setStatus(response.SC_MOVED_PERMANENTLY);
para enviar o status xmlHttp '301' necessário para um redirecionamento ...e na função $ .ajax você não deve usar a
.toString()
função ..., apenasif (xmlHttp.status == 301) { top.location.href = 'xxxx.jsp'; }
o problema é que não é muito flexível, você não pode decidir para onde deseja redirecionar.
o redirecionamento através dos servlets deve ser o melhor caminho. mas ainda não consigo encontrar o caminho certo para fazê-lo.
fonte
Eu só queria me apegar a quaisquer solicitações de ajax para a página inteira. @SuperG me começou. Aqui está o que eu acabei com:
Eu queria verificar especificamente determinados códigos de status http para basear minha decisão. No entanto, você pode simplesmente associar-se ao ajaxError para obter algo que não seja sucesso (talvez apenas 200?). Eu poderia ter escrito:
fonte
Se você também deseja passar os valores, também pode definir as variáveis da sessão e acessar, por exemplo: No jsp, você pode escrever
E então você pode armazenar esse valor temporário na sua variável javascript e brincar
fonte
Não tive sucesso com a solução do cabeçalho - eles nunca foram detectados no meu método ajaxSuccess / ajaxComplete. Usei a resposta de Steg com a resposta personalizada, mas modifiquei algumas das JS. Eu configurei um método que chamo em cada função para poder usar o padrão
$.get
e os$.post
métodos.Exemplo disso em uso ...
fonte
Finalmente, resolvo o problema adicionando um costume
HTTP Header
. Logo antes da resposta para cada solicitação no lado do servidor, adiciono o URL solicitado atual ao cabeçalho da resposta.Meu tipo de aplicativo no servidor é
Asp.Net MVC
e ele tem um bom lugar para fazer isso. emGlobal.asax
eu implementei oApplication_EndRequest
evento para:Funciona perfeito para mim! Agora, em todas as respostas do
JQuery
$.post
i, temos osurl
cabeçalhos de resposta solicitados e também outros que resultam doPOST
método por status302
,303
....e outra coisa importante é que não há necessidade de modificar o código no servidor nem no cliente.
e a próxima é a capacidade de obter acesso a outras informações da ação posterior, como erros, mensagens e ..., dessa maneira.
Eu postei isso, talvez ajude alguém :)
fonte
Eu estava tendo esse problema em um aplicativo de django com o qual estou mexendo (aviso: estou mexendo para aprender e não sou de forma alguma um especialista). O que eu queria fazer era usar o jQuery ajax para enviar uma solicitação DELETE para um recurso, excluí-lo no lado do servidor e enviar um redirecionamento de volta para (basicamente) a página inicial. Quando enviei a
HttpResponseRedirect('/the-redirect/')
partir do script python, o método ajax do jQuery estava recebendo 200 em vez de 302. Então, o que fiz foi enviar uma resposta 300 com:Em seguida, enviei / processei a solicitação no cliente com jQuery.ajax da seguinte forma:
Talvez usar 300 não esteja "certo", mas pelo menos funcionou exatamente como eu queria.
PS: foi uma grande dor editar na versão móvel do SO. O ISP estúpido atendeu meu pedido de cancelamento de serviço quando terminei minha resposta!
fonte
Você também pode conectar o protótipo de envio XMLHttpRequest. Isso funcionará para todos os envios (jQuery / dojo / etc) com um manipulador.
Eu escrevi esse código para lidar com um erro expirado de 500 páginas, mas deve funcionar da mesma maneira para interceptar um redirecionamento 200. Pronto a entrada da wikipedia no XMLHttpRequest ao alterar a estatística sobre o significado de readyState.
fonte
Além disso, você provavelmente desejará redirecionar o usuário para o URL indicado nos cabeçalhos. Então, finalmente, ficará assim:
UPD: Opps. Tem a mesma tarefa, mas não funciona. Fazendo essas coisas. Mostrarei a você a solução quando a encontrar.
fonte
Eu tenho uma solução de trabalho usando as respostas de @John e @Arpad link e @RobWinch ligação
Eu uso o Spring Security 3.2.9 e o jQuery 1.10.2.
Estenda a classe do Spring para causar resposta 4XX apenas de solicitações AJAX:
applicationContext-security.xml
Nos meus JSPs, adicione um manipulador de erros AJAX global, como mostrado aqui
Além disso, remova os manipuladores de erro existentes das chamadas AJAX nas páginas JSP:
Espero que ajude os outros.
Update1 Eu descobri que precisava adicionar a opção (sempre use-default-target = "true") à configuração de login do formulário. Isso foi necessário, pois depois que uma solicitação AJAX é redirecionada para a página de login (devido à sessão expirada), o Spring lembra a solicitação AJAX anterior e redireciona automaticamente para ela após o login. Isso faz com que o JSON retornado seja exibido na página do navegador. Claro, não é o que eu quero.
Atualização2 Em vez de usar
always-use-default-target="true"
, use o @RobWinch exemplo de bloqueio de solicitações AJAX do requstCache. Isso permite que os links normais sejam redirecionados para o destino original após o login, mas o AJAX vai para a página inicial após o login.fonte