Vraptor 3 - Iniciando objetos de sessão condicionalmente

Tenho aqui um objeto simples de sessão que contém os dados do usuário autenticado:

@SessionScoped public class UserSession implements Serializable { private Long id; private String name; }

Na minha aplicação A o sistema faz autenticação via JAAS e todos os recursos são bloqueados como anonimo, ou seja, o usuário somente acessa as páginas autenticado. Como no JAAS tenho apenas o login do usuário e não os dados completos preciso ir no repositório buscar esses dados. Assim criei nesse mesmo objeto UserSession um método que carrega os dados do usuário.

@PostConstruct public void init() { credential = ServiceLocator.lookup(AuthenticationService.class).afterJaasAuthentication(login); }

Isso funciona muito bem na minha aplicação A, pois como todos os links necessitam de usuário autenticado sempre que o JAAS libera o acesso o vraptor chama meu interceptor de controle de sessão, e com esse UserSession está no construtor os dados do usuário são carregados.

Tenho esse interceptor que faz o controle do usuário que está autenticado.

[code]@Intercepts
@RequestScoped
public class SecurityUserSessionHolder
implements Interceptor {

private final UserSession userSession;

public SecurityUserSessionHolder(UserSession userSession) {
    this.userSession = userSession;
}

public boolean accepts(ResourceMethod method) {
    // skip ajax requests
    return !request.getHeader("accept").contains("application/json");
}

[…]

}[/code]

Porém agora eu tenho uma aplicação B que usa a mesma estrutura do projeto A com JAAS e após o login os dados completos do usuário são carregados do repositório. Porém nessa aplicação B nem todas as telas são bloqueadas. Há algumas telas que são públicas.

Sendo assim quando eu acesso uma página pública sem estar autenticado no JAAS o vraptor inicializa o interceptor SecurityUserSessionHolder, que automaticamente instancia o UserSession, que por sua vez chama o PostLoad e tenta colocar o objeto na http-session. Porém como eu ainda não tenho login no contexto JAAS levo uma null-pointer-exception na cara.

Enfim, o null-pointer é simples de fazer um if, porém eu não quero levar esse UserSession para a http-session, já que na verdade eu ainda não tenho usuário autenticado. Há como fazer isso?

Pensei em tentar algo no método Interceptor.accepts, porém o UserSession é inicializado antes de chamar o accepts, já que está no construtor.

Nao vou responder o que vc quer, mas vou falar como custumo fazer…

Apenas a UserSession nao indica que ha usuario logado… eu normalmente coloca uma propriedade neste objeto… UserSession.isLogged()

e coloco metodos de

  • login() que seria equivalente ao seu @PostLoad
  • logout() que seria equivalente a um @PostDestroy

Ainda nao aprendi a matar um objeto de sessao com vraptor, ou de dizer quando pode ou nao instanciar… pois o vraptor automaticamente cria e o coloca na sessao quando ele e’ requerido…

Ate mesmo pq, alguem pode deslogar no meio da sessao, e nem sempre vc pode dar um invalidate na sessao, pq pode ter outras coisas de sua aplicacao, que nao necessitam de login, mas que usem a sessao do usuario

Lavieri, toda a sugestão é bem vinda. Valeu.

Da forma que você fez me deu uma idéia de como resolver meu problema. O único porém é que a invocação dos métodos login e logout que populam seu UserSession é manual. Porém como minha autenticação é via JAAS, eu não tenho controle sobre isso. O JAAS faz a autenticação por ele mesmo, e eu nem mesmo consigo fazer uma espécie de metodo-a-ser-chamado-apos-jaas. Vou indagar lá nos fóruns da Snorcle para saber como ter uma chamada após autenticação do JAAS.

Quanto a matar um objeto de sessão do vraptor não tem mesmo como. Já tentei de todas as formas, e a única é você trabalhar direto com a HttpSession e fazer um session.remove. Felizmente nos meus projetos o uso de session é raro, vai para session apenas as informações do usuário, já que o JAAS armazena apenas o objeto Principal e as roles.

Abraços

Lucas, Paulo, vocês tem alguma sugestão para meu problema?

Já tentei fazer uma série de testes para somente inicializar os objetos em uma determinada condição, porém o vraptor teima em sempre iniciar meu objeto e jogar na session. Há na verdade um gap (IMHO) no vraptor sobre colocar e remover objetos da session. Seria interessante ter, por exemplo, como invocar o accepts sem colocar o objeto na sessão, e principalmente remover objetos da sessão. Isso já foi até uma reclamação minha em outro tópico.

Abraços

Já que até agora não consegui pensar em uma solução muito elegante, e o próprio vraptor não colabora no controle dos objetos de sessão fiz uma meia gambiarra.

No caso ao invés de trabalhar com o objeto UserSession no construtor o meu UserSessionHolder trabalha diretamente com a HttpSession. Assim consigo um controle melhor de quando inicializar e não inicializar, além de poder remover o objeto da HttpSession.

A meia gambiarra consiste em ficar monitorando quando o JAAS anexou um usuário no seu contexto. Quando o request.userPrincipal houver um valor eu conecto no módulo EJB e carrego os dados do usuário.

A única coisa que me pareceu estranho é usar HttpSession diretamente, embora seja apenas em um interceptor.

Logo mais posto algumas considerações minhas sobre uso de JAAS com vraptor, caso alguém mais precise.

Abraços

Não faça isso…

antes disso tente o seguinte

peça um Contianer no construtor… e quando quiser a sessão, vc faz,

[code]@Resource
public class SeuController {

 private final Container container;

 public SeuController(Container container) {
     this.container = container;
 }
 
 //cria a sessão só quando invocado
 private UserSession getOrCreateUserSession() {
     container.instanceFor(UserSession.class);
 }

}[/code]

infelizmente destruir eu não sei como…

[quote=garcia-jj]Tenho aqui um objeto simples de sessão que contém os dados do usuário autenticado:

@SessionScoped public class UserSession implements Serializable { private Long id; private String name; }

Na minha aplicação A o sistema faz autenticação via JAAS e todos os recursos são bloqueados como anonimo, ou seja, o usuário somente acessa as páginas autenticado. Como no JAAS tenho apenas o login do usuário e não os dados completos preciso ir no repositório buscar esses dados. Assim criei nesse mesmo objeto UserSession um método que carrega os dados do usuário.

@PostConstruct public void init() { credential = ServiceLocator.lookup(AuthenticationService.class).afterJaasAuthentication(login); }

Isso funciona muito bem na minha aplicação A, pois como todos os links necessitam de usuário autenticado sempre que o JAAS libera o acesso o vraptor chama meu interceptor de controle de sessão, e com esse UserSession está no construtor os dados do usuário são carregados.

Tenho esse interceptor que faz o controle do usuário que está autenticado.

[code]@Intercepts
@RequestScoped
public class SecurityUserSessionHolder
implements Interceptor {

private final UserSession userSession;

public SecurityUserSessionHolder(UserSession userSession) {
    this.userSession = userSession;
}

public boolean accepts(ResourceMethod method) {
    // skip ajax requests
    return !request.getHeader("accept").contains("application/json");
}

[…]

}[/code][/quote]

Olá,

estava pensando em criar uma annotation para colocar nos meus métodos para que o intercept não agisse nos retornos json. Vendo seu post, gostei dessa forma e acho que vou utilizar tb. Mas minha dúvida é: aonde vc está recebendo a instancia request?

[quote=Vendramini87]

Olá,

estava pensando em criar uma annotation para colocar nos meus métodos para que o intercept não agisse nos retornos json. Vendo seu post, gostei dessa forma e acho que vou utilizar tb. Mas minha dúvida é: aonde vc está recebendo a instancia request?[/quote]

recebe ele no construtor… junto com o UserSession, é que ele esqueceu de escreve quando fez o código ai… mas é só receber no construtor…

[quote=garcia-jj]Lucas, Paulo, vocês tem alguma sugestão para meu problema?

Já tentei fazer uma série de testes para somente inicializar os objetos em uma determinada condição, porém o vraptor teima em sempre iniciar meu objeto e jogar na session. Há na verdade um gap (IMHO) no vraptor sobre colocar e remover objetos da session. Seria interessante ter, por exemplo, como invocar o accepts sem colocar o objeto na sessão, e principalmente remover objetos da sessão. Isso já foi até uma reclamação minha em outro tópico.

Abraços

[/quote]
Desculpa demorar pra responder isso… acabei perdendo a thread de vista =(

é… o vraptor não tem nenhuma maneira própria de colocar e tirar objetos da sessão… e não consigo ver nenhum jeito que não seja
equivalente ao HttpSession.getAttribute/removeAttribute…

a única coisa que dá pra fazer pra contornar o comportamento do VRaptor é ter métodos init e destroy no seu componente de sessão que são chamados manualmente, quando sua condição for satisfeita…

Vc tem alguma idéia de usabilidade, de como daria pra fazer o que vc quer?

Lucas, tkx :smiley:

Eu ainda não consegui ter uma idéia. Esse meu projeto entou em standby em prol de outro, e logo que eu voltar a ele vou analisar uma forma de fazer isso, embora eu também não tenha uma idéia ainda.

Lucas e garcia-jj,

Após esses anos desde esse tópico, o VRaptor agora tem alguma maneira de colocar/tirar objetos da sessão?
Se sim, como faço?

E se não, como fizeram para resolver?

Obrigado!

você pode criar uma classe @SessionScope e usá-la pra guardar o objeto que vc quer que esteja na sessão.

Ou simplesmente receber o HttpSession no construtor e fazer o setAttribute/getAttribute/removeAttribute