[RESOLVIDO] Acesso dinâmico de usuários

Bom dia pessoal,

Trabalho desenvolvendo um sistema que utiliza Jboss, Spring Security, Hibernate, JSF, PrimeFaces…
Controlamos o acesso de usuários com o Spring Security através de permissões de acesso (ROLE_ADMINISTRADOR, ROLE_USUARIO e etc), porém percebemos que o sistema não necessita desses perfis, mas sim de um controle dinâmico de acesso.
Por exemplo:

  • Usuario1 pode acessar a opção 1, 2 e 3 no menu do sistema;
  • Usuario2 pode acessar a opção 2 e 3;
  • Usuario3 pode acessar apenas 1.

Futuramente se houver necessidade do Usuario3 acessar outra opção, adicionar a permissão. Ou se o Usuario1 não puder mais acessar a opção 2, retirar a permissão.

Nosso sistema limita o acesso às páginas apenas com o tipo de permissão do usuário que colocamos no menu:

<sec:ifAnyGranted roles="ROLE_ADMINISTRADOR, ROLE_GESTOR"> <p:submenu label="Gestão"> <p:submenu label="Consultas"> <p:menuitem value="Exemplo" url="/restrito/exemplo/pagina.jsf" /> </p:submenu> </p:submenu> </sec:ifAnyGranted>

Às vezes um usuário com o perfil ROLE_USUARIO precisa acessar essa página (um caso específico) porém não podemos adicionar essa permissão no menu da aplicação, já que não são todos os ROLE_USUARIO que podem acessar.

Gostaria que vocês indicassem formas de fazer esse controle de uma forma elegante e que funcione corretamente para esses casos.
Já pesquisei a respeito do VRaptor e do Spring Security, mas não achei um material que dissesse se é possível esse controle.

Sugestões?
Obrigada :slight_smile:

Embora o nome comum seja “role” (‘papel’ desempenhado pelo usuário) o significado é mais de permissão.

O que vc tem hoje é um esquema de perfil onde o usuário tem o perfil A ou B. O que vc precisa é dizer que ao perfil A está associada a permissão X ou Y e poder modificar quais permissões estão associadas ao usuário.

Para isso precisa levantar as permissões do sistema. O que vc quer controlar, o que vc permitir ou bloquear. Com esta informação vc irá alterar as páginas e qq outro uso do role para usar essas permissões. No seu exemplo ficaria:

    <sec:ifAnyGranted roles="ALLOW_CONSULTA_ABC">    
                           <p:submenu label="Gestão">    
                               <p:submenu label="Consultas">    
                                   <p:menuitem value="Exemplo"  url="/restrito/exemplo/pagina.jsf" />                        
                                </p:submenu>    
                           </p:submenu>    
      </sec:ifAnyGranted>    

Agora vc cria um cadastro de Perfis. O perfil é uma forma de agrupa as permissões. Quando vc tem muitas permissões controlar uma a uma é um pesadelo. Então o perfile mais facil de gerenciar. O perfil é equivalente aos seus roles antigos.
Depois vc faz um cadastro de associação usuário -> perfis. Um usuário pode ter mais do que um perfil.

Desta forma vc pode dinamicamente cadastrar novos usuários, novos perfis, editar os perfis que já existem , etc… A unica coisa que é hardcoded são as permissões.
Depois quando vc lê os roles do usuário vc cria um join que retorna todas as permissões (destintas) que o usuário tem. Não sei onde no spring security é feita essa query, mas provavelmente vc já tem isso hoje. Portanto, basta mudar lá.

Olá julynhaprado, Conseguiu resolver este problema ? estou “empacado” no mesmo trecho que você, também queria fazer de forma dinâmica…

Alguém tem outra solução ?

Resolvi sim, talvez não da melhor maneira possível mas solucionei o problema…

No cadastro de usuário é preciso selecionar todas as páginas que ele terá acesso, ou seja, para cada página selecionada eu acrescento uma ROLE há ele.
Essas permissões de páginas foram previamente criadas, com um nome “amigável” para aparecer para o cliente.
Ou seja, criei o cadastro de permissões para acessar página.
Para cada página eu tenho uma ROLE diferente, que no menu da aplicação eu coloco (como segue abaixo) e quando o usuário acessa o sistema o próprio Spring se encarrega de verificar se o mesmo possui essa ROLE.

                    EXEMPLO1:
                        [code]<sec:ifAnyGranted
                            roles="ROLE_PG_AQUI">
                            <p:menuitem value="Nutrientes"
                                url="/diretorio/cadastro/adm_cad_pagina.jsf" />
                        </sec:ifAnyGranted>[/code]

Ou seja, só visualizará esse menu se o usuário possuir a permissão ROLE_PG_AQUI, que foi selecionada no cadastro dele.

Porém, meus clientes tem a necessidade de ter acessos diferenciados como ADMINISTRADOR, GESTOR DO SETOR X, GESTOR DO SETOR Y etc etc etc…
Essas permissões eu chamei de: Permissões de conteúdo de página, que no cadastro também seleciono para cadastrá-los.
E uso essas permissões assim:

EXEMPLO2:
<h:outputLabel value="Exemplo" /> <sec:ifAnyGranted roles="ROLE_ADMINISTRADOR, ROLE_DESENVOLVEDOR, ROLE_GESTOR_Y"> <p:selectOneMenu style="width:335px;" value="#{bean.os.exemplo}" converter="entityConversor" required="true" requiredMessage="CAMPO É OBRIGATORIO"> <f:selectItem itemLabel="SELECIONE" itemValue="" /> <f:selectItems value="#{bean.exemplos}" var="exemplos" itemLabel="#{exemplos.p.nome}" itemValue="#{exemplos}" /> </p:selectOneMenu> </sec:ifAnyGranted> <sec:ifNotGranted roles="ROLE_ADMINISTRADOR, ROLE_DESENVOLVEDOR, ROLE_GESTOR_Y"> <p:inputText style="width:335px; text-transform:uppercase;" disabled="true" value="#{bean.p.nome}" /> </sec:ifNotGranted>

ifAnyGranted : ou seja, se o usuário que acessou essa página tiver perfil ROLE_ADMINISTRADOR, ROLE_DESENVOLVEDOR, ROLE_GESTOR_Y, mostre para ele o <p:selectOneMenu>

se não

ifNotGranted : mostre para ele o <p:inputText> já preenchido e desativado.

Qualquer dúvida estou a disposição.

Dividi o sistema em 2 linhas para controlar:

PERMISSÕES DE ACESSO HÁ PÁGINA - Tenho permissões que controlam o acesso há página, ou seja, ROLE_NOME_DA_PAGINA. Essa permissão eu uso para colocar no menu, e exibo ela numa lista de páginas cadastradas no meu sistema para serem selecionas no cadastro de usuário. Todas as páginas ali selecionadas, aquele usuário terá acesso.

PERMISSÕES DE CONTEÚDO DE PÁGINA - Essas permissões eu uso para selecionar, caso o usuário possua uma permissão específica.
Por exemplo, ROLE_GESTOR_MANUTENCAO, só esse perfil poderá clicar no botão de excluir objetos cadastrados na pagína XYZ.
Daí na página XYZ eu coloco assim:

[code]<sec:ifAnyGranted roles=“ROLE_GESTOR_MANUTENCAO”>
<p:commandButton action="#{bean.usuarioLogado.nome}" value=“Excluir” ajax=“false” />
</sec:ifAnyGranted>

<sec:ifNotGranted roles=“ROLE_GESTOR_MANUTENCAO”>
<p:commandButton action="#{bean.usuarioLogado.nome}" value=“Excluir” ajax=“false” disabled=“true” />
</sec:ifNotGranted>[/code]

ou seja,

Se o usuário não possuir a permissão de ROLE_GESTOR_MANUTENCAO exiba o botão Excluir desabilitado.
E assim por diante…

Todas as ROLES que poderão acessar os diretórios devem estar nela. Caso a ROLE do usuário não for compatível com a URL que ele digitou, aparecerá uma tela de acesso negado.
Para uma didática melhor, coloquei um exemplo de ApplicationContext-security abaixo, com algumas explicações.


[code]<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns=“http://www.springframework.org/schema/security
xmlns:b=“http://www.springframework.org/schema/beans” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=“http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd”>


<intercept-url pattern="/nome_diretorio1/"
access=“ROLE_PAGINA_DENTRO_DO_DIRETORIO1_1, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO1_2, ------------------- DEVEM SER COLOCADOS TODAS AS ROLES QUE PODERÃO ACESSAR ESSE DIRETÓRIO
ROLE_PAGINA_DENTRO_DO_DIRETORIO1_3, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO1_4” -------------------
/>
<intercept-url pattern="/nome_diretorio2/
"
access=“ROLE_PAGINA_DENTRO_DO_DIRETORIO2_1, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO2_2, ------------------- DEVEM SER COLOCADOS TODAS AS ROLES QUE PODERÃO ACESSAR ESSE DIRETÓRIO
ROLE_PAGINA_DENTRO_DO_DIRETORIO2_3” -------------------
/>
<intercept-url pattern="/nome_diretorio3/**"
access=“ROLE_PAGINA_DENTRO_DO_DIRETORIO3_1, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO3_2, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO3_3, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO3_4, ------------------- DEVEM SER COLOCADOS TODAS AS ROLES QUE PODERÃO ACESSAR ESSE DIRETÓRIO
ROLE_PAGINA_DENTRO_DO_DIRETORIO3_5, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO3_6, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO3_7, -------------------
ROLE_PAGINA_DENTRO_DO_DIRETORIO3_8” -------------------
/>

    <form-login login-page="/nome_diretorio3/pag_login.jsf"            -------------------  NOME DO DIRETORIO + PÁGINA DE LOGIN   -- SE CASO RETORNAR SUCESSO
        authentication-failure-url="/nome_diretorio3/pag_erro.jsf?login_error=true"   ------------- NOME DO DIRETORIO + PÁGINA DE ERRO -- SE CASO RETORNAR FALHA (aqui pode ser configurada uma página com erro)
        authentication-success-handler-ref="successHandler" />
    <logout logout-success-url="/nome_diretorio3/pag_login.jsf" /> ------------- NOME DO DIRETORIO + PÁGINA RETORNADA AO SAIR DO SISTEMA
</http>

<authentication-manager>
    <authentication-provider>
        <jdbc-user-service data-source-ref="projetoDataSource"
            authorities-by-username-query="SEU SELECT AQUI"
            users-by-username-query="SEU SEGUNDO SELECT AQUI" />
        <password-encoder hash="md5" />
    </authentication-provider>
</authentication-manager>

</b:beans>.[/code]

to querendo fazer isso ai tbm, qual pacote eu baixo ? e seria o xmlns:sec=“http://www.springframework.org/security/tags” ?
pra funcionar ?

Boa tarde,

Os pacotes que eu precisei baixar foram:
www.springframework.org/schema/beans
www.springframework.org/schema/security

E para funcionar precisei colocar como no meu último post:

<b:beans xmlns="http://www.springframework.org/schema/security" xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">

Para lhe ajudar, segue os nomes dos jars que utilizamos no sistema:

spring-aop-3.0.3.RELEASE.jar spring-asm-3.0.3RELEASE.jar spring-beans-3.0.3RELEASE.jar spring-context-3.0.3RELEASE.jar spring-context-support-3.0.3RELEASE.jar spring-core-3.0.3RELEASE.jar spring-expression-3.0.3RELEASE.jar spring-jdbc-3.0.3RELEASE.jar spring-security-acl-3.0.5RELEASE.jar spring-security-config-3.0.5RELEASE.jar spring-security-core-3.0.5RELEASE.jar spring-security-taglibs-3.0.5RELEASE.jar spring-security-web-3.0.5RELEASE.jar spring-tx-3.0.3RELEASE.jar spring-web-3.0.3RELEASE.jar spring-webmvc-3.0.3RELEASE.jar

ta dando erro aqui

13,41 <sec:ifAnyGranted> Tag Library supports namespace: http://www.springframework.org/security/facelets/tags, but no tag was defined for name: ifAnyGranted

Primeiramente gostaria de agradecer a julynhaprado !!

Seu auxilio / códigos foram de suma importância para o entendimento do Spring !

julynhaprado, Muito OBRIGADO!


[quote=WAO]ta dando erro aqui

13,41 <sec:ifAnyGranted> Tag Library supports namespace: http://www.springframework.org/security/facelets/tags, but no tag was defined for name: ifAnyGranted

WAO, estava com este problema e consegui resolver inserindo a seguinte biblioteca:

facelets-taglib-0.3_jsf-2.0_spring-3.jar

ai é só fazer a referencia como a July citou…


<b:beans xmlns="http://www.springframework.org/schema/security"    
    xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
        http://www.springframework.org/schema/security    
        http://www.springframework.org/schema/security/spring-security-3.0.xsd">

Abraço!

Dúvidas estou a disposição.


Tenho uma dúvida:

O sistema está funcionando perfeitamente, porém fiz a “atualização” das permissões do usuário, como o spring “atualiza” as permissões ? Fiz o teste dando um F5 na pagina porem não surtiu efeito…