Bom Dia Pessoal,
Em meu projeto existe uma estrutura para verificar se determinado método pode ou não ser acessado pelo usuário.
A lógica é bem simples, utilizando @Intercepts, verificando se há um usuário logado na sessão, para as tentativas de acesso aos métodos anotados como @Restrito.
Até ai tudo ótimo e bonito. Porém, um item que não havia dado a devida atenção começou a me preocupar. A questão do Session TimeOut
As requisições feitas por chamadas diretas pelo navegador, caiam na rotina de verificação e eram redirecionados p/ local conforme configurado,
mas as requisições Ajax retornavam um status [color=red]302 - Moved temporarily[/color] , e não acontecia mais nada.
Pesquisei bastante sobre esse assunto e vi que não há uma solução que a comunidade tenha admitido como “padrão” p/ esse tipo de situação.
Portanto, venho compartilhar com vocês a solução que adotei, e aproveitar p/ pedir sugestões e comentários.
É bem possível que existam formas mais elegantes de fazer oq estou fazendo.
Tentei inclusive fazer um redirecionamento no @PreDestroy da minha classe @SessionScoped que guarda as informações de Login, mas ele não gostou muito de fazer um redirect a partir deste ponto, obviamente por questões do escopo. (session x request)
Bom, vamos ao que interessa… a solução aparentemente maravilhosa … (não sei porque, mas isso tá com uma cara de gambiarra… :twisted: )
:arrow: Primeiramente, a configuração do web.xml
<session-config>
<session-timeout>30</session-timeout>
</session-config>
:arrow: Definição da classe responsável por verificar se métodos anotados como @Restrito estão sendo requisitados por visitantes sem login
Caso seja validado que esta Classe realmente tem que interceptar a requisição, ele verifica ainda se o método está anotado como @ValidarComRedirectTo.
Neste caso ele entende que não é uma requisição Ajax, e faz um redirect normal na url do browser.
Se por ventura a classe não estiver anotada com @ValidarComRedirectTo ele envia um badRequest(), p/ chegar o código 400 na requisição Ajax, e não mais o 302 conforme comentado anteriormente.
[code]@Intercepts
public class AutenticacaoInterceptor implements Interceptor {
private final Result result;
private final LoginSession loginSession;
public AutenticacaoInterceptor(Result result, LoginSession loginSession) {
this.result = result;
this.loginSession = loginSession;
}
@Override
public boolean accepts(ResourceMethod method) {
return !loginSession.isUsuarioLogado() && method.containsAnnotation(Restrito.class);
}
@Override
public void intercept(InterceptorStack stack, ResourceMethod method, Object resourceInstance) throws InterceptionException {
if (method.containsAnnotation(ValidarComRedirectTo.class)) {
result.redirectTo(AppController.class).login();
} else {
result.use(Results.status()).badRequest("Sessão Expirada ou Acesso Indevido!");
}
}
}[/code]
:arrow: Registrando o comportamento das requisições Ajax ao receber um erro.
Coloquei este trecho de código em minha main.jsp (Página que contem os Menus, e onde os conteudo sao carregados) para definir como toda e qualquer requisição ajax deve se comportar ao receber um status [color=red]400 - bad request[/color]
$(document).ajaxError(function(event, jqxhr, settings, exception) {
if(jqxhr.status == 400) {
exibirAvisoTimeOut();
}
});
A função exibirAvisoTimeOut() abre uma dialog avisando que o tempo de sessao expirou e que é necessário efetuar o login novamente e executa o comando window.location.reload();
Bom, sei que desta forma, qualquer requisição que dê errado, ele (navegador) vai pensar que é por conta do TimeOut.
Como todas as outras Exceções estão com um tratamento bem seguro em minhas Controllers, estou confiante que não terei problemas em deixar desta forma.
Esta foi a solução mais prática que encontrei p/ tratar a questão de privilégio de acesso junto com a questão da perda da sessão por timeout quando está envolvido requisições ajax.
Mas como falei no inicio, acredito que existam formas mais elegantes e com certeza até mais prática de se implementar isto no VRaptor.
Fico no aguardo de sugestões…
Grande Abraço