Programador ajudante e aprendiz da comunidade open source.

Controle de Login com VRaptor 3

Atualizado em 17 de Setembro de 2011.

Vamos abordar um assunto que todo desenvolvedor em algum momento irá precisar: controle de login. Hoje em dia é normal você acessar um sistema e lá estar uma telinha para ser digitado o nome de usuário e senha.

Por tempos achei complicado trabalhar com login em uma aplicação JSP / Servlet pura, ou criar filtros e mais filtros, mas estou pra dizer que se você já passou por isso, irá ficar satisfeito com o VRaptor e seus Interceptadores. (:

Objetivo:

Criar uma tela de autenticação e uma página de boas vindas disponível apenas para usuários logados.

Precisamos de ter nossa JPA configurada para acesso ao banco de dados. Se você ainda não sabe como fazer isso, da uma passadinha no artigo JPA e VRaptor 3.

Criando a classe Usuario:

@Entity
public class Usuario {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nome;
    private String email;
    private String senha;

    // getters e setters

}

Dissemos que a classe Usuario é uma entidade que deverá ser mapeada no banco e o atributo id será a chave primária com o seu incremento feito pelo próprio banco de dados. Iremos utilizar o email como identificação do usuário junto com a sua respectiva senha.

Criando a classe UsuarioBusiness:

private EntityManager manager;

    public UsuarioBusiness(EntityManager manager) {
        this.manager = manager;
    }

    public Usuario autenticar(String email, String senha) {
        try {
            Query query = manager.createQuery("from Usuario where email = :email and senha = :senha");
            query.setParameter("email", email);
            query.setParameter("senha", senha);
            return (Usuario) query.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }
}

Fizemos uma consulta procurando um registro que tenha um e-mail e senha igual ao digitado pelo usuário. Se for encontrado alguma ocorrência, este usuário é retornado, caso contrário um valor nulo será.

Vamos criar uma classe com escopo de sessão para mantermos o nosso usuário.

Criando a classe UserSession:

@Component
@SessionScoped
public class UserSession {

    private Usuario user;

    public boolean isLogged() {
        return user != null;
    }

    public void logout() {
        user = null;
    }

    // get e set

}

Este componente servirá para manter o usuário na sessão, por isso ele deve ser anotado com @SessionScoped e como de costume o @Component por também se tratar de um componente. Criamos um método que verifica se o usuário esta na sessão, ou seja, é diferente de nulo e outro método para retirar o usuário da sessão, que neste caso é o logout.

Agora precisamos identificar os métodos que são protegidos por login e os que são públicos. Por isso iremos criar uma annotation para indicar os método públicos chamada @Public.

Não se assuste se nunca tiver criado uma annotation em sua vida, muitos desenvolvedores, mesmos os mais experiêntes ainda não tiveram esta oportunidade.

Criando a anotação pública (Public.java):

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface Public {

}

Para criarmos uma anotação utilizamos o modificador @interface. Além disso anotamos esta classe com uma @Retention para especificar qual será a política de retenção. Neste caso utilizaremos a RetentionPolicy.RUNTIME, que nos disponibiliza as informações em tempo de execução. Outra anotação importante para utilizarmos é a @Target, que configuramos onde esta anotação de permissão poderá ser utilizada, que em nosso caso será em classes (TYPE) e métodos (METHOD).

Para aprender um pouco mais sobre annotation você pode ler o artigo "Trabalhando com Annotations em Java" do nosso amigo Francisco Souza. (:

Com isso podemos utilizar anotações em classes e métodos de forma simples para indicar que tais recursos poderão ser utilizados sem que o usuário esta logado.

Precisamos de uma página para o usuário digitar o e-mail e senha.

Criando a página de Login (login.jsp):

<form action="${pageContext.request.contextPath}/autenticar" method="post">
    E-mail: <input type="text" name="usuario.email"/>
    Senha: <input type="password" name="usuario.senha"/>
    <input type="submit" value="Acessar"/>
</form>

Temos um formulário que submete o e-mail e senha para um método do LoginController que por sua vez fará a autenticação.

Criando a classe LoginController:

@Resource
public class LoginController {

    private Result result;
    private UserSession userSession;
    private UsuarioBusiness business;

    public LoginController(Result result, UserSession userSession, UsuarioBusiness business) {
        this.result = result;
        this.userSession = userSession;
        this.business = business;
    }

    @Public
    @Get("/login")
    public void login() {

    }

    @Public
    @Post("/autenticar")
    public void autenticar(Usuario usuario) {
        Usuario user = business.autenticar(usuario.getEmail(), usuario.getSenha());

        if (user != null) {
            userSession.setUser(user);

            result.redirectTo(IndexController.class).index();
        } else {
            result.include("error", "E-mail ou senha incorreta!").redirectTo(this).login();
        }
    }

    @Get("/logout")
    public void logout() {
        userSession.logout();
        result.redirectTo(this).login();
    }

}

Nosso controller tem três métodos:

  • O @Get /login apenas nos leva para a página de autenticação;
  • O @Post /autenticar é o método que recebe o e-mail e senha do formulário e faz a consulta no banco. Se o usuário existir, então este é colocado na sessão e redirecionado para dentro do sistema; e
  • O /logout desloga o usuário colocando um valor nulo na sessão e o redireciona para a página de login.

Repare que o método que leva à página de login e o método para autenticação estão anotados com @Public, isso evitará que o sistema faça o bloqueio do recurso, já que o usuário necessita dessas ações para se autenticar. Já o método logout, apenas quem esta logado poderá ter acesso a ele.

Criando o IndexController:

@Resource
public class IndexController {

    @Get("/")
    public void index() {
    }

}

Temos apenas um método para nos redirecionar para a página inicial interna do sistema. Sendo que este controller não possibilita acesso público.

Criando a página inicial (index.jsp):

Nossa página inicial terá apenas uma mensagem de boas vindas ao usuário logado que estará na sessão e um link para ser desfeito o login (logout).

...
Olá, ${userSession.user.nome} <a href="${pageContext.request.contextPath}/logout">Logout
...

Com isso terminamos a parte um pouco mais trabalhosa que já estamos acostumados a fazer, sobrando a cereja do bolo, a qual será de fato o controle e restrição de acesso ao sistema.

Todo esse controle será feito por uma classe chamada de Interceptor, na qual irá interceptar todas ações efetuadas no sistema fazendo uma auditoria que de acordo com sua regra tomará uma atitude.

Criaremos esta classe que estenderá Interceptor e receberá injetado o UserSession para nos disponibilizar o usuário da sessão.

Esta classe deve ser anotada com @Intercepts para conseguir interceptar as chamadas.

Criando a classe LoginInterceptor:

@Intercepts
public class LoginInterceptor implements Interceptor {

    private Result result;
    private UserSession userSession;

    public LoginInterceptor(Result result, UserSession userSession) {
        this.result = result;
        this.userSession = userSession;
    }

    public boolean accepts(ResourceMethod method) {
        return 
            !(method.getMethod().isAnnotationPresent(Public.class) ||
            method.getResource().getType().isAnnotationPresent(Public.class));
    }

    public void intercept(InterceptorStack stack, ResourceMethod method, Object resourceInstance) {
        if (userSession.isLogged()) {
            stack.next(method, resourceInstance);
        } else {
            result.redirectTo(LoginController.class).login();
        }
    }

}

Todo interceptor tem um método accepts no qual podemos fazer regras para indicar se o recurso acesso será ou não interceptado. Nós já pensamos em uma forma de excluir alguns recursos do filtro do interceptor através da anotação @Public. Logo verificamos se o método ou o controller esta anotado com ela, se estiver será retornado true, então negamos o resultado para false dizendo: "Não aceitamos a interceptação desta ação!". Aqui pode entrar qualquer regra que lhe convenha.

Caso o recurso seja interceptado, o método intercept irá ser executado para o tratamento. Este método recebe como argumento um InterceptorStack que será responsável por dar continuidade ao fluxo da execução através do método next. Há também outros dois argumentos que serão discutidos em outro artigo e não são necessárias por hora. Repare que capturamos a sessão e verificamos se o usuário esta logado, através do método que criarmos no componente, dando continuidade ao fluxo, caso contrário é feito um redirecionamento para a página de login para que o usuário se autentique.

Ok! Nosso controle de login esta pronto, e cá pra nós: se você souber um jeito mais fácil de fazer isso em Java, por favor, me mostre como é que eu te pago um saquinho de jujubas. (;

Link do projeto

http://github.com/wbotelhos/controle-login-vraptor-3

  1. Ricardo Salim 31 Ago 2015 13:48

    Olá, obrigado pelo post.
    Sei que ele é um pouco velho e não sei se alguém vai ver, mas ele atendeu perfeitamente o que eu precisava. Só estou com duvida em uma coisa...
    Eu não estou conseguindo fazer retornar o usuário que está preso na sessão.
    Eu debuguei e na classe UserSession e na Controller ele tá lá, preenchido.. mas na jsp ele não aparece.
    Alguma ideia do que pode ser?

    Obrigado e aguardo realmente uma resposta

  2. sagggh 1 Fev 2015 18:26

    cara esse seu logins.jsp ta confuso de mais e nao esta funconando

    javax.servlet.ServletException cannot be resolved to a type
    javax.servlet.jsp.PageContext cannot be resolved
    javax.servlet.jsp.JspException cannot be resolved to a type

  3. Clécius J. Martinkoski 16 Abr 2014 17:20

    Primeiramente parabéns pelo POST, além de ser um tema muito interessante sua didática é muito boa, foco em detalhes que muitas veses quem escreve deixa passar.

    Porém tenho que discordar do ultimo ponto, sim existem maneiras mais simples de tratar controle de permissões, se chama segurança declarativa, o java por padrão tem isso sobre a chancela da especificação do JAAS, que torna muito simples o processo de login, além de ser muito maleável, permitindo login relacionais simples como o demonstrado acima até sistemas de autenticação complexos com LDAP e grandes níveis de permissão, tudo de uma forma desacoplada e facilmente mantível.

  4. Tiago 27 Mai 2013 16:24

    Cara, que belo post, é antigo mas continua nos auxiliando e muito.

    Tenho uma pergunta, se um dia vier a usar Load Balancer, não teriamos problema usando um controle de login implementando dessa maneira?

    Abraço

  5. Rodrigo 30 Mar 2013 01:01

    Cara!

    O post é antigo mas preciso dizer que é um excelente tutorial. Muito simples e prático para trabalhos que não exigem muitas regras. Melhor do que ficar configurando Spring Security e baixando trocentos megabytes de bibliotecas para o projeto.

    Parabéns!

  6. Daniel Bevi 17 Jan 2013 16:46

    Boa tarde Washington.. tenho uma dúvida relacionada a escalabilidade desse sistema de login, sendo bem resumido na minha pergunta, se eu usar um load balance no server de entrada vou perder a sessão em alguma situação? Que conselhos você daria para evitar problemas?

    Abraço e muito obrigado pela ajuda!!! seus posts são sempre fantásticos!!! Acompanho a bastante tempo

  7. Cicero Ednilson 14 Dez 2012 23:37

    Parabéns bom post,

    poderia me tirar uma duvida ? no vraptor onde defino qual vai ser o controller e action inicial do sistema, digo o primeiro que vai ser chamado quando o programar for iniciado, ou sempre o inicial de default é o IndexController

    obrigado

  8. Daniel Lima 30 Nov 2012 15:52

    Oi Washington, achei sua solução bem interessante, e gostaria de saber como fazer para implementar uma lógica de redirect after login, por exemplo, o usuário digita a url listagem de produtos (lógica restrita) e o sistema vai para página de login, e depois já redireciona para a página de listagem de produtos, ao inveś de ir para o IndexController.

  9. Benhur 13 Ago 2012 05:07

    Ótimo post, mas como sou novo com vraptor não entendi como eu faria para buscar da minha classe Usuario, o email e senha.
    Estou implementando no meu tcc, e tenho uma classe Usuario, como posso fazer para buscar os dados da minha classe Usuario?

  10. Carlos Viana 9 Abr 2012 05:05

    Bom dia, eu implementei o post de controle de login e agora o de permissão. Está beleza, ótimos blog por sinal.

    Mas, como juntei o controle de login e permissão em um projeto somente acredito que os dois interceptors estejam conflitando e atrapalhando o TOMCAT.

    Ao ir para o jsp inicial o navegador aparece o seguinte erro "Erro 310 (net::ERR_TOO_MANY_REDIRECTS)"
    Já aconteceu isso com alguém?

    1. Washington Botelho autor 31 Mai 2012 15:58

      Oi Carlos,

      Você precisa verificar se um interceptor não esta interceptando o outro, senão ficará em loop infinito mesmo.

  11. Renato Gama 4 Abr 2012 13:10

    Cara, assim funciona bacana, porem e se eu quiser que as permissoes sejam dinamicas, por exemplo, que em tempo de execuca eu possa decidir que o usuario visitante pode passar a executar uma acao e eu queira gerencia isso por uma tela administrativa? Sua solucao e estatica, tem ideia de algo dinamica? Abraco!

    1. Washington Botelho autor 4 Abr 2012 15:14

      Oi Renato,

      De alguma forma você terá que dar uma identificação ao método que você esta chamando, pois só assim poderá vincular essa "key" com algo cadastrado no seu banco.
      Talvez usar o nome do próprio método e pegá-lo no interceptor, ou usar códigos, que é um dos casos em um projeto que trabalho.
      Algo como:

      @Role("save_user")
      public void save(User user) { }
      
  12. Carlos Viana 28 Mar 2012 14:41

    Washington, coloquei os dois posts de controle de login e permissão. Fiquei com uma dúvida referente a utilização do interceptor. Preciso dos dois "Login e Permission" ou somente o Permission resolve? Fiz os teste com os dois e tem acontecido o ERRO 310 TO MANY REDIRECT, tem alguma dica?

    1. Washington Botelho autor 30 Mar 2012 08:45

      Oi Carlos,

      Você precisa só de um interceptor e neste você pode colocar a lógica dos dois.
      Normalmente utilizo apenas o PermissionInterceptor e a primeira verificação é a do login, que não passa de um user != null.
      "MANY REDIRECT" seria porque no seu fluxo de dados há um redirect para uma URI que novamente entra no interceptor e faz novamente o redirect.
      Se foi feito um redirect, então este deve ir para um lugar que o usuário tenha permissão, senão ele ficara em loop, pois nunca terá permissão.

  13. Charles Almeida 31 Jan 2012 21:39

    Olá Washington,

    Estive usando este modelo de login para verificar na minha aplicação, mas observei que você fez um outro modelo nos posts recentes na publicação devmedia.

    Qual seria melhor a anotação public ou leitura de classes para liberação.

    public boolean accepts(ResourceMethod method) {
        return !Arrays.asList(IndexController.class,LoginController.class,PaginaController.class).contains(method.getMethod().getDeclaringClass());
    }
    
    1. Washington Botelho autor 23 Mar 2012 12:03

      Oi Charles,

      Hoje em dia uso a anotação Public, pois assim você pode espalhá-la por diversos controllers sem se preocupar em qual exatamente ela esta. (:

  14. Donizete 2 Dez 2011 11:53

    Também esqueci mencionar que teremos perfis pai e perfis filhos...

    1. Washington Botelho autor 4 Dez 2011 12:00

      Oi Donizete,

      Sem saber exatamente o seu MER, creio que será necessário um ManyToMany com atributos devido a complexidade dos relacionamentos.
      Assim dentro de cada tabela ManyToMany você poderá ter outros relacionamentos.
      A segunda parte deste artigo mostrará como fazê-lo, terça-feira estará no ar.

  15. Donizete 2 Dez 2011 11:51

    Excelente Post! Parabéns! Preciso desenvolver o seguinte. Devo criar um perfil, depois atribuir permissões a esse perfil(Acesso a tela de Cliente, ocultando ou mostrando os botões de editar cliente, excluir cliente...) depois ligar os usuários a perfis. Tantos os perfis como as permissões devem ser criadas dinamicamente, guardando no banco. Você teria algum exemplo assim para apresentar? Obrigado pela atenção.

    1. Washington Botelho autor 4 Dez 2011 11:56

      Oi Donizete,

      Antes da solução você precisa saber:
      Perfil tem vários acesso?
      Acesso tem vários perfis?
      Usuário tem vários perfis?
      Perfils tem vários usuário?

      Faz o MER e depois pense na solução Hibernate.

    2. Washington Botelho autor 4 Dez 2011 11:54

      Oi Donizete,

      Você precisa fazer uma análise primeiro do que você quer e fazer os relacionamentos, pra depois ver como resolver no Hibernate.
      Ver se um perfil tem vários acessos e esse mesmo acessos podem estar ligados a vários perfis.
      Se o usuário poderá ter vários perfis e da mesma forma se esses perfis podem estar ligados a vários usuários etc.
      Sem essa análise não tem como saber a sua necessidade.

  16. Deckard Cain 30 Dez 2010 23:23

    Ótimo post. O uso de anotaçoes facilitou e deixou o codigo limpo demais

    1. Washington Botelho autor 1 Dez 2011 10:59

      Muito bom Rodrigo!

      Obrigado pela contribuição. (:

  17. juniorsatanas 1 Dez 2010 13:36

    wbotelhos, Acho que o perfil tem que vim do banco junto com o usuário e senha, pois não conseguir implementar os 2 DEMOS ! Se conseguir integrar os 2 poste por favor para nos !
    Grande abraço

    junior.

    1. Washington Botelho autor 1 Dez 2010 14:06

      Oi Júnior,

      O perfil tem que ser buscado no banco mesmo, dentro do objeto Usuario.
      Para exemplo foi criado o usuário no IndexController, mas na vida real você pegaria ele do banco.

      Juntar os dois posts seria apenas juntar os códigos, tirando isso é lógica particular de cada aplicação.

  18. juniorsatanas 26 Nov 2010 12:27

    Cara acho que JQuery faz issso Thicicbox !

    1. clayton 26 Nov 2010 15:54

      BLZ vou tentar , mas vou fazer sem a consulta a banco , quero deixar somente um usuario padrao para a area administrativa , pois estou sem tempo e a parte de login principal do sistema já está pronta tenho que entrega este projeto na segunda ... obrigado pelos exclarecimentos e pelas ideias , não coloquei em pratica ainda mas irão ser muito uteis .

      E junior eu bem que queria te ajudar mais estou sem tempo e ainda não sei muita coisa sobre programação para web , estou terminando meu projeto na raça mesmo ... espero que da proxima vez eu possa te ajudar, ate mais ...

      1. juniorsatanas 29 Nov 2010 06:18

        clayton
        É sobre o que teu projeto ? poderia disponibilizar teu projeto para estudos ?

        Grande abraço e boa sorte !

  19. clayton 26 Nov 2010 12:22

    brigado ai cara , se não for pedir de mais vc pode me mostrar um jeito de criar um login com esse seu projeto para quando a pagina for interceptada aparece um pop up para o usuario digitar usuario e senha do admin para entrar nas paginas do administrador senão da erro, ou seja quero que as paginas do administrador abram somente se o usuario digitar o usuario e a senha previamente cadastrados, pode ser no codigo fonte mesmo , pois é uma medida simples estou sem tempo para entregar este projeto e falta somente a autenticação e outras coisas que já estou resolvendo , se vc puder me ajudar ou indicar algum material .

    1. Washington Botelho autor 26 Nov 2010 14:15

      Oi Clayton,

      Vou colocar aqui uma idéia que me veio a cabeça para você entender o caminho das pedras:

      • Você pode criar uma página que tenha um formulário dentro de um Dialog do jQuery;
      • Ao interceptar a chamada para a área restrita você o redireciona para esta página do Dialog;
      • Nesse redirecionamento você guarda a URL requisitada em um campo hidden vinda de um request ou na sessão;
      • Quando for clicado em autenticar deve ser feito uma consulta ao banco para ver se os dados são válidos;
      • Se for válido o redireciona para a URL guardada;
      • Se não for válido da um erro na própria tela ou joga ele para outra página como o index, por exemplo.

      A idéias seria mais ou menos essa.
      Boa sorte. (:

  20. juniorsatanas 26 Nov 2010 12:11

    clayton
    Este é o meu projeto, ta faltando 1%
    por favor da uma olhada !
    http://www.4shared.com/file/LfJsAteW/cp4.html

  21. juniorsatanas 26 Nov 2010 12:01

    Concordo, por isso estou lendo todo material da Caelum ! o negocio é que tenho que por isso para rodar no sistema que temos aqui.. e estou sozinho para Strus jsf gwt e Vraptor.. a formula para isso e Ctrl + C e Ctrl + V !

    Obrigado

  22. clayton 26 Nov 2010 11:45

    sim eu executei com esta url mas está dando erro na hora de iniciar o tomcat estava aparecendo o erro na ultima tag context do arquivo server.xml segue a tag <Context docBase so que arrumei com o nome do projeto e tudo mas ainda não funciona da erro

    1. Washington Botelho autor 26 Nov 2010 11:58

      Oi Clayton,

      Então o erro não é no projeto e sim nas configurações do Tomcat.
      Não é preciso fazer nenhuma configuração adicional diretamente no Tomcat para os projetos rodarem.
      Tenta reinstalá-lo ou tenta dar uma Googada sobre o erro.

      Aqui fala um pouco sobre: http://tomcat.apache.org/tomcat-5.5-doc/config/context.html

      "Do not choose a docBase that starts with your Host's appBase string. The default appBase is "webapps" so do not choose a docBase like "webapps-foo." Doing so will lead to deployment errors: see Bugzilla for details."

  23. juniorsatanas 26 Nov 2010 11:38

    Estou confuso nisto:

    @Resource
    public class IndexController {
        ...
    
        @Path("/")
        public void index() {
            session.setAttribute("user", this.getUsuario());
        }
    
        private Usuario getUsuario() {
            Usuario entity = new Usuario();
            entity.setNome("Washington Botelho");
            entity.setPerfil(TipoPerfil.MODERADOR);
            return entity;
        }
    
    }
    

    O Lucas do Guj falou para eu anotar :

     @Enumerated(EnumType.STRING)
    private TipoPerfil perfil;
    

    na entidade !

    1. Washington Botelho autor 26 Nov 2010 11:44

      Oi Júnior,

      Como o exemplo é didático o usuário é criado quando é acessado a raiz do projeto, ou seja, "/".
      Se você não acessar essa url e ir direto para outra página, poderá dar esse NullPointer, pois não terá sido criado o usuário na sessão.
      Antes de ir para qualquer outra página, se certifique de ter acessado a URL absoluta para ser criado o usuário no sessão.

      • Você não consiguirá usar os projetos que coloco aqui no blog literalmente fazendo Ctrl + C e Ctrl + V, pois muitas coisas são contornadas ou não são feitas da melhor forma para ficar mais básico, didático e apresentável para os usuários que estão aprendendo. Tente aprender o conceito e não se prender de fato na implementação.
  24. juniorsatanas 26 Nov 2010 11:35

    tipo assim:

    @Get
    @Path("/")
    public void index() {
        session.setAttribute("user", this.getUsuario());
        session.setAttribute("user", this.getSenha());
        session.setAttribute("user", this.getPerfil());            
    }
    

    ?

  25. Washington Botelho autor 26 Nov 2010 11:36

    Oi Clayton,

    Esse erro 404 é um erro que ocorre quando a página requisitada não é encontrada.
    Podem ser dois motivos: o servidor não esta rodando a aplicação ou a URL esta incorreta.

    Baixei o projeto e o executei com essa url: http://localhost:8080/controle-permissao-vraptor-3

  26. clayton 26 Nov 2010 10:40

    bom dia cara peguei seu exemplo estou me baseando nele para terminar um projeto de faculdade mais está dando esse erro :
    HTTP Status 404 - /controle-permissao-vraptor-3/
    o que pode ser que está errado .

  27. juniorsatanas 23 Nov 2010 09:30

    gostaria de pegar o NOME / SENHA / PERFIL do banco e jogar para a determinada area..

    tipo:
    Administrador /admin/
    Usuario /Usua/
    etc..

    1. Washington Botelho autor 26 Nov 2010 11:36

      Oi Júnior,

      Você já tem todos os dados do usuário na sessão, basta usá-los:

      user.getNome();
      user.getSenha();
      user.getPerfil();
      
  28. juniorsatanas 23 Nov 2010 08:48
    private boolean isExistePermissao(Permissao permissaoList) {
        Usuario user = this.getUser();
    
        if (permissaoList != null) { // Com permissão anotada. Verificar!
            for (TipoPerfil perfil : permissaoList.value()) {
                if (perfil.equals(user.getPerfil())) {
                    return true;
                }
            }
        } else { // Sem permissão anotada. Continue!
            return true;
        }
    
        return false;
    }
    

    to pegando um erro em: if (perfil.equals(user.getPerfil())) {
    "O problema é que o seu objeto Usuario não tem um objeto Perfil."

    esse perfil deixa de ser ENUM, e vem do banco é isso ?

    1. Washington Botelho autor 23 Nov 2010 10:49

      Oi Júnior,

      O perfil dentro do for é cada anotação em cima do método que você esta tentado acessar, ou seja, os perfis que têm permissão de usar tal método.
      O user.getPerfil() é o perfil do usuário, então você pergunta se o perfil do usuário é igual algum que tenha permissão no método que ele esta tentando executar.

      Se esta dando NullPointer, é porque o usuário da sessão é nulo, ou o usuário que esta na sessão não tem um perfil, o que é nulo também.

  29. juniorsatanas 4 Nov 2010 13:21

    Gostaria de saber como se faz para pegar tudo isso do banco na hora de um login ?

    Controle de Permissão com VRaptor 3
    Controle de Login com VRaptor 3

    Grande abraço

    SHOW CARA !

  30. Jean Paulo 13 Out 2010 01:27

    Ótimo post. Uma duvida:

    Você saberia me dizer como eu poderia faser em PHP, uma condição para somente exibir determinado link se o acesslevel do usuario foi =100

    Eu ja criei um painel de login, porem gostariaque se fosse acesslevel normal exibir o link para o PAINEL NORMAL
    e
    se fosse acesslevel = 100 exibir o link para o painel de ADM.

    1. Washington Botelho autor 13 Out 2010 08:38

      Oi Jean,

      Para aparecer um menu ou outro de acordo com o valor de uma variável chamada acesslevel da sessão você pode fazer da seguinte forma:

      <?php
          if ($_SESSION['user']->accessLevel == 100) {
              <a href="/painelLogin.php">Painel Login</a>
          } else {
              <a href="/painelNormal.php">Painel Normal</a>
          }
      ?>
      
  31. Walter Frey 2 Set 2010 20:39

    Caso não seja possível, existe algum framework para auxiliar no controle de permissões no java SE

    Valeu!

    1. Washington Botelho autor 2 Set 2010 21:06

      Fala Walter,

      O controle que faço é manual. Para cada janela (jFrame, jDialog...) eu tenho um método que recebe o objeto Usuario e de acordo com seu perfil, então desabilito ou sumo com os componentes.

      Se você for utilizar esse método em seu código Java fora das janelas, então poderá mudar estes components para static e acessá-los, por exemplo, assim:

      UsuarioView.removerBtn.setVisible(usuario.perfil.isRemover());
      

      Infelizmente não conheço nenhuma framework para se trabalhar com permissão em Java SE, mas também nunca parei para pesquisar.

  32. Walter Frey 2 Set 2010 20:33

    Olá Washington,

    Parabéns achei muito interessante esse artigo, eu trabalho com JAVA SE, e gostaria de saber se e possível aplicar essa idéia a Desktop?

    Abraço, ate mais!

  33. Daniel Jurado 25 Mai 2010 13:55

    Ótimo post. Uma duvida:

    Como eu faria para exibir na view somente os links para os recursos que um determinado usuario tem acesso? Por exemplo, um membro nao poderia ver o link para o admin.

    Alguma ideia?

    1. Washington Botelho autor 25 Mai 2010 14:21

      Fala Daniel,

      Para apresentar ou não o menu na página, já foge do interceptor, sendo tratado na tela mesmo.
      Isso depende da linguagem, mas vamos dizer que esta utilizando JSP com um usuário na sessão chamado "user":

      Verifica se o perfil do usuário é igual a ADM:

      <c:if test="${user.perfil eq 'ADM'}">MENU OPTION</c:if>
      

      Verifica se dentre a lista de perfis do usuário, contém ao menos um que seja ADM:

      <c:if test="${fn:containsIgnoreCase(user.perfilList, 'ADM') == true}">MENU OPTION</c:if>
      

      Isso faz esconder o menu, porém a página pode ser acessada pela URL, nesse caso devemos interceptar o método que chama a página. Vamos dar exemplo do método listar que chama a página de listagem:

      @Get
      @Permissao(TipoPerfil.ADMINISTRADOR)
      public void listar() {
      }
      
  34. Francisco Souza 23 Abr 2010 19:59

    Graaande post, Washington (não no sentido literal =P)

    Ficou muito bacana, man! Parabéns ;)

  35. Alciara Franca 23 Abr 2010 06:54

    Olá Washington,

    Meus parabéns parabéns seu blog,tem muito post's bem aplicaveis ;)
    E esse Post caiu como luva para mim, pois ainda esses dias na empresa onde eu trabalho estavamos discutindo como seria isso com o vraptor.

    Colocarei em práticia, assim que terminar, voltarei com as dúvida! =)

    abraços

    1. Washington Botelho autor 24 Abr 2010 08:46

      É muito bom saber que estou ajudando Alciara.

      Obrigado pelos parabéns. (:

Em resposta:
(Cancelar)
Formate seu código utilizando Markdown.