Programador ajudante e aprendiz da comunidade open source.

Controle de Permissão com VRaptor 3

Atualizado em 17 de Setembro de 2011.

Em uma aplição com diferentes níveis de acesso à funcionalidades, é fundamental termos controle das ações efetuadas pelos usuários. Podemos citar, por exemplo, exclusão de dados, alteração de informações ou visualização de certas telas que apenas os usuários com privilégio mais alto poderiam executar.

Objetivo:

Criar funcionalidades de um sistema, nas quais cada uma só poderá ser executada por um determinado tipo de usuário.

O que será tratado?:

  • Controle de acesso a métodos específicos; e
  • Controle de acesso a um controller como um todo.

Recomendo a leitura do artigo Controle de Login com VRaptor 3, pois introduz o conceito de [http://vraptor.caelum.com.br/documentacao/interceptadores/Interceptor) e explica como criar uma annotation.

Quando falamos em permissões, logo pensamos em perfis, já que uma permissão estará ligada diretamente a estes. Com isso criaremos um Enum com alguns nomes de perfil para usarmos como indicadores das permissões.

Criando os perfis (Perfil.java):

public enum Perfil {

    MEMBRO, MODERADOR, ADMINISTRADOR;

}

Veja que temos 3 (três) tipos de perfis, cada um deles poderá ter um privilégio diferente.

Criando o usuário (Usuario.java):

public class Usuario {

    private Long id;
    private String nome;
    private Perfil perfil;

    // getters e setters

}

No objeto usuário, além dos atributos normais que o mesmo possa ter, também teremos o atributo que manterá o perfil do usuário.

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

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

}

Esta anotação servirá para indicar que o recurso é público e não possui restrições.

Criando o controller inicial (IndexController.java):

@Resource
public class IndexController {

    ...

    @Public
    @Get("/")
    public void index() {
       Usuario usuario = new Usuario();
       usuario.setNome("Washington Botelho");
       usuario.setPerfil(Perfil.MODERADOR);

       session.setAttribute("user", usuario);
    }

}

No controller de entrada criamos um mock do usuário com tipo de perfil (moderador) já o colocando na sessão para o utilizarmos no exemplo. Em uma aplicação real você pegaria esse usuário do banco de dados quando o mesmo fizesse o login. Repare que este método esta sendo anotado com @Public para indicar que ele não entrará no controle de permissão.

Agora precisamos de criar a camada de negócios que simulará as ações feitas no banco de dados.

Criando o Business (UsuarioBusiness.java):

@Component
@SessionScoped
public class UsuarioBusiness {

    private Collection<Usuario> manager = new ArrayList<Usuario>();

    public void save(Usuario usuario) {
       manager.add(usuario);
    }

    public void remove(Usuario usuario) {
       manager.remove(usuario);
    }

    public Collection<Usuario> all() {
       return manager;
    }

    // getters e setters

}

Esta camada de negócio simula a inserção, remoção e recuperação dos usuários em cima de uma lista que ficará na sessão por conta da classe estar anotada com @SessionScoped. Em uma aplicação real você acessaria o banco e não teria esta anotação.

O próximo passo é criar uma anotação para podermos utilizá-las nos métodos e controllers que queremos restringir o acesso. Com esta anotação podemos identificar qual usuário tem direito de acesso ao método ou controller anotado.

Criando a anotação de permissão (Permission.java):

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

    Perfil[] value();

}

Esta anotação possui um único elemento que é um array de Perfil que por ser o único atributo existente nessa anotação, é chamado de value por boas práticas. Com isso podemos utilizar anotações em classes e métodos de forma simples. Vejamos um exemplo de um método anotado com a permissão apenas para administrador:

@Permission(Perfil.ADMINISTRADOR)
public void foo() {

}

Aqui utilizamos a anotação Permission passando o valor de administrador. Quando passamos apenas um valor para a anotação podemos omitir o atributo value, que será equivalente a:

@Permission(value = Perfil.ADMINISTRADOR)

Caso queira utilizar mais de um valor na anotação deverá passá-la em formato de hash, entre chaves separando os valores por vírgula:

@Permission({ Perfil.ADMINISTRADOR, Perfil.MODERADOR })

Com o conceito já maduro de annotation, já é possível anotar métodos ou controllers que necessitarem de restrições.

Criando o controller do usuário (UsuarioController.java):

@Resource
public class UsuarioController {

    ...

    @Get("/usuario")
    public void listagem() {
       return business.all();
    }

    @Post("/usuario")
    @Permission(Perfil.MODERADOR)
    public void salvar(Usuario usuario) {
       business.save(usuario);

       result
       .include("message", "Usuário adicionado com sucesso!")
       .redirectTo(this).listar();
    }

    @Delete("/usuario/{entity.id}")
    @Permission({ Perfil.MODERADOR, Perfil.ADMINISTRADOR })
    public void remover(Usuario usuario) {
       business.remove(usuario);

       result
       .include("notice", "Usuário removido com sucesso!")
       .redirectTo(this).listar();
    }

}

Temos 4 (quatro) métodos:

  • listagm e negado: sem anotação. Podem ser acessados livrementes;
  • salvar: com permissão apenas para moderador.
  • remover: com permissão para moderador e administrador.

Lembre-se que em nível de programação os perfis não são cumulativos. Não é porque um usuário é administrador que ele poderá executar ações de um método anotado para membros. Se você quiser acesso para o administrador, deverá adicioná-lo na anotação.

Também criaremos um controller administrativo, no qual todas as funcionalidades contidas nele só poderão ser executadas pelo administrador.

Criando o controller administrativo (AdminController):

@Resource
@Permission(Perfil.ADMINISTRADOR)
public class AdminController {

}

Repare que agora a anotação esta na classe, indicando que o acesso a qualquer método desta só poderá ser feito pelo administrador.

Vamos criar as telas do sistema.

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

...
<a href="${pageContext.request.contextPath}/">Início)
<a href="${pageContext.request.contextPath}/usuario">Listar usuários)
<a href="${pageContext.request.contextPath}/admin">Administração)

Seja bem vindo: ${userSession.user.nome}
...

Acima criamos simples os links de navegação do sistema e a apresentação do nome do usuário que esta na sessão.

Criando a tela administrativa (admin.jsp):

...
${notice}
...

Na tela administrativa iremos esperar apenas uma mensagem de boas vindas.

Criando a tela de listagem (listagem.jsp):

...
${notice}

<form action="${pageContext.request.contextPath}/usuario" method="post">
    <input type="text" name="usuario.nome" />
    <input type="submit" value="Salvar" />
</form>

<c:forEach items="${usuarioList}" var="usuario">
    ${usuario.nome}

    <form action="${pageContext.request.contextPath}/usuario/${usuario.id}" method="post">
       <input type="hidden" name="_method" value="delete" />
       <input type="submit" value="Remover" />
    </form>
</c:forEach>
...

Na tela de listagem temos um formulário para salvar o usuário e logo abaixo a listagem dos usuários já cadastrados com opção de removê-los.

Com isso preparamos todo o nosso ambiente, faltando apenas o controle de permissão de fato. Esse controlador será um Interceptor.

Criando o interceptador de permissão (PermissionInteceptor.java):

Primeiramente devemos excluir as classes que não desejamos que sejam interceptadas.

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

No método accepts não iremos interceptar nem os métodos nem os controllers que estiverem anotados com @Public.

E então em nosso método intercepts vamos criar a lógica das restrições.

public void intercept(InterceptorStack stack, ResourceMethod method, Object resource) {
    Permission methodPermission = method.getMethod().getAnnotation(Permission.class);
    Permission controllerPermission = method.getResource().getType().getAnnotation(Permission.class);

    if (this.hasAccess(methodPermission) &amp;&amp; this.hasAccess(controllerPermission)) {
       stack.next(method, resource);
    } else {
       result.use(http()).sendError(403, "Você não tem permissão para tal ação!");
    }
}

Através do argumento ResourceMethod capturamos todas os atributos da anotação do tipo Permission do método acessado pegando o método usando o getMethod e em seguida a anotação passando seu tipo.

Para pegar a anotação do controller fazemos praticamente o mesmo processo alterando apenas o método getMethod para getResource e getType. - Se lembra que os nossos controllers são anotados com @Resource?

Então estas duas listas são passadas para o método hasAccess que responde se o usuário tem permissão de acesso ao recurso requisitado. Caso tenha, é chamado o método next do InterceptorStack, que da continuidade ao fluxo, caso contrário o usuário é redirecionado para a página negado.jsp.

O método que verifica se o usuário tem acesso ficará o seguinte:

private boolean hasAccess(Permission permission) {
    if (permission == null) {
       return true;
    }

    Collection<Perfil> perfilList = Arrays.asList(permission.value());

    return perfilList.contains(userSession.getUser().getPerfil());
}

Se não houver anotação na lista recebida como argumento, quer dizer que não há restrições, logo, é retornado true, liberando o acesso. Caso contrário, é verificado se o usuário possui o perfil adequado. O método hasAccess é usado para analisar tanto a permissão do método quanto ao do controller, retornando true ou false para indicar a liberação do acesso.

Contribuição

O Rodrigo Ramalho contribuiu com o seguinte código para testar as anotações:

   @Test
   @SuppressWarnings("rawtypes")
   public void createPermission() throws SecurityException, NoSuchMethodException{
       UserController controller = new UserController(result, userService, validator);
       Class c = controller.getClass();

       Method m = c.getMethod("create", User.class);
       Permission p = m.getAnnotation(Permission.class);

       Assert.assertNotNull(p);
       Assert.assertEquals(2, p.value().length);
       Assert.assertEquals(Role.ADMIN, p.value()[0]);
       Assert.assertEquals(Role.MEMBER, p.value()[1]);
   }

Com isso nosso controle de permissão esta pronto e qualquer classe que necessite de monitoramente poderá ser anotada e entrará automaticamente no controle de acesso.

Se você quiser ver como fica o controle login junto com o controle de permissão visite o projeto VRaptor Starting Project: http://github.com/wbotelhos/vraptor-starting-project

Link do projeto:

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

  1. Felipe 18 Jan 2015 20:03

    Olá Washington

    Primeiramente gostaria de parabenizar pelo post, me ajudou e muito, ótimo tutorial
    Porém, só estou com uma dúvida:
    Como fazer com que o usuário já logado não acesse a página de login?

    obrigado desde já

  2. Tarcisio Ambrosio 27 Mar 2014 18:39

    Washington, muito interessante, gostaria de saber se essas informações continuam valida para o atual VRaptor v2.5.3, se ocorreu alguma alteração que atrapalhe este controle. (vou testa-lo quando chegar em casa somente)

    mas tenho outras dúvidas ainda:

    Nesse caso eu controlaria o metodo e então se o cara acessa um página de admin, vai ser inutil ele não fará nada, provavelmente será negado, mas gostaria de saber o que você acha mais produtivo, ou melhor, criar varios menus com as opções de cada perfil, por exemplo

    menuAdmin.jsp (contendo o link do admin)
    menuUsuario.jsp(contendo links do usuarios, mas não do admin)
    menuPublico.jsp(contendo links só para quem não está logado)

    seguindo essa lógica, eu teria que fazer um comando qualquer em cada tipo de menu, para verificar se aquela página pode ser acessada por ele, algo como .isAdmin, caso não redireciona para página de login (caso por algum motivo, erro ou usuário consegue o link do menuAdmin.jsp, sei que ele não fara execução de metodos, mas queria que ele nem tivesse acesso)

    ou se é melhor fazer um menu só, e em cada "Link" do menu coloco uma verificação para tornar hidden ou não a opção?

    Obs: utilizando bootstrap e vraptor

    qual tecnica você acharia mais viável, sei que existe a preferencia, mas uma que seja mais válida e segura claro.

  3. 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.

  4. 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) { }
      
  5. 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.

  6. 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. (:

  7. 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.

      1. 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.

    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.

  8. Rodrigo Ramalho 1 Fev 2011 09:17

    Massa botelhos, pra quem quiser testar as anotações do método pode fazer algo do tipo assim:

       @Test
       @SuppressWarnings("rawtypes")
       public void createPermission() throws SecurityException, NoSuchMethodException{
           UserController controller = new UserController(result, userService, validator);
           Class c = controller.getClass();
    
           Method m = c.getMethod("create", User.class);
           Permission p = m.getAnnotation(Permission.class);
    
           Assert.assertNotNull(p);
           Assert.assertEquals(2, p.value().length);
           Assert.assertEquals(Role.ADMIN, p.value()[0]);
           Assert.assertEquals(Role.MEMBER, p.value()[1]);
       }
    
    1. Washington Botelho autor 1 Fev 2011 10:59

      Muito bom Rodrigo!

      Obrigado pela contribuição. (:

  9. Deckard Cain 30 Dez 2010 23:23

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

  10. 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

  11. 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. 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

      1. 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. juniorsatanas 26 Nov 2010 12:27

          Cara acho que JQuery faz issso Thicicbox!

        2. 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. (:

          1. 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.

          2. 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 !

    2. 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."

  12. 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.
  13. 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());
    }
    
    ?
    
  14. 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 .

    1. 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/

  15. 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 10:51

      Oi Júnior,

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

      user.getNome();
      user.getSenha();
      user.getPerfil();
      
  16. 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 26 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.

  17. 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 !

    1. Washington Botelho autor 4 Nov 2010 13:48

      Oi Júnior,

      O que exatamente você precisa pegar no banco na hora do login? Não entendi direito.
      Mas você pode consultar o banco a partir do método de login mesmo ou fazer isso diretamente no interceptor, coisa que não recomendo, já que a intenção do interceptor é fazer verificações de coisa já consultadas no banco.

  18. 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)
          } else {
             <a href="/painelNormal.php">Painel Normal)
          }
      ?>
      
  19. 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.

  20. 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!

  21. 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() {
      }
      
  22. Francisco Souza 23 Abr 2010 19:59

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

    Ficou muito bacana, man! Parabéns ;)

  23. 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.