Minha contribuição - Controle de acesso VRaptor 3  XML
Índice dos Fóruns » Frameworks e Bibliotecas brasileiros
Autor Mensagem
bronx
JavaTeenager
[Avatar]

Membro desde: 24/08/2009 02:59:47
Mensagens: 197
Offline

Antes de continuar lendo, saiba que já há algo mais atualizado!

---------------------------------------------------------------------------------------------------------

Galera, buenas!!

Desenvolvi uma parada aqui que acredito que possa ser útil para bastante gente (ou não... =S).
Já era para eu ter postado isso aqui há algum tempo. Mas ando meio enrolado, por isso estou fazendo isso só hj...
Vou explicar o que se trata, bem como a maneira de utilizar. Mas o intuito do post é pedir opinião sobre o que acharam da idéia, se realmente ajuda, ou se é algo para se ver e soltar um belo e caloroso "FODA-SE". hehehe

Imaginem que vocês tem um controlador do VRaptor, com um método (recurso) qualquer:



Do jeito que está, supondo que nenhum Interceptor tenha sido criado para controlar o acesso a esse recurso, qualquer um que tentasse conseguiria acessar tranquilamente esse recurso, bastando acessar a URI: http://meuserver/meuContexto/minhaClasse/meuMetodo.

E se quiséssemos que somente usuários logados tivessem acesso ao referido recurso?
Teríamos que criar um Interceptor com as regras de acesso aos recursos. Nada muito complicado.

Porém, e se fosse tão simples quanto anotar um método?



Caso o método (recurso) solicitado possua tal annotation, somente usuários logados poderão acessá-lo.
Simples, não?

Essa é a idéia do que fiz: uma maneira de restringir os acessos aos recursos desenvolvidos com o VRaptor 3, sem a preocupação com a implementação dessas restrições.
Após configurar tudo, basta desenvolver sua aplicação de forma a não se preocupar com a implementação de restrições de acesso ao seu sistema.
Você simplesmente desenvolve as classes e os métodos, e se achar necessário, anota-os com as annotations de restrições. O resto é controlado pelo componente que criei, sem a menor intervenção do desenvolvedor.

Atemo-nos a utilização. rs

Aí surge a pergunta: "Tá, legal! O cara precisa estar logado. Mas o que eu faço caso ele não esteja?".
Ahááá
Simplesmente, redirecione-o para a página de login. Ou para qualquer outra página que vc quiser.
Para isso, basta fazer:



Com a annotation @LoggedIn, vc diz que somente usuários logados possuem acesso àquele recurso.
Já a annotation @AccessDenied diz o que fazer caso o acesso ao recurso seja negado. O atributo loginPage diz para onde redirecionar a navegação caso o usuário não esteja logado.

O interessante é que nao temos que fazer isso para cada método. Podemos anotar as classes também:



Com isso, TODOS os métodos dessa classe só seriam acessados caso o usuário estivesse logado no sistema.

Podemos ir além, e definir um comportamento único para todos os métodos restritos em caso de o usuário não estar logado, mesmo se não quisermos que todos os métodos estejam restritos (nossa...essa nem eu entendi):



Nesse caso, os métodos meuMetodo() e meuTerceiroMetodo() estão restritos, mas ambos adotam o mesmo comportamento caso o acesso seja negado. Isso nos poupa de ter que escrever a annotation @AccessDenied em cada um dos métodos. A seguinte situação também é válida:



O método meuTerceiroMetodo(), em caso de acesso negado, não assumiria o comportamento padrão (redirecionar para o local informado na annotation @AccessDenied da classe). Ele redirecionaria a navegação para a "/outraPaginaDeLogin". Na maioria das vezes isso não faz sentido, mas se for necessário, é fácil assim que se faz.

Dado esse overview, presumo que muitos devem estar se questionando: "Ok, mas e se o meu controle de acesso for baseado em papéis?".

Controle de acesso baseado em papéis (roles) funciona da seguinte maneira: "Quero que apenas gerentes pudessem acessar tal recurso.". As you wish:



Aumentamos a restrição ao nosso método.
Agora, além de estar logado, o usuário DEVE ser um gerente para poder ter acesso àquele recurso.

Como para saber se o usuário é ou não gerente ele obrigatoriamente deve estar logado, podemos suprimir o uso da annotation @LoggedIn:



Porém, o que fazer se o usuário está logado mas não é um gerente?
Utilize o atributo accessDeniedPage da annotation @AccessDenied:




Agora, caso o usuário logado não possua as credenciais necessárias para acessar tais recursos, ele pode ser gentilmente redirecionado para uma página informando que ele não possui acesso ao requerido recurso. Cool, isn't it? ^^

O legal é que, como mostrado anteriormente, essa restrição pode ser aplicada tanto na classe, quanto no recurso. Mas, como o nome sugere, o atributo roles pode receber mais de um papel. Saca só:



Esse recurso só seria acessado por quem fosse gerente OU supervisor.
O ponto-e-vígula é o que distingue o "gerente" do "supervisor". Mas se precisar alterar o caracter de separação, basta definir outro no atributo "separator" (momento tabajara.rs):




Combinando entre classe e método:



Podemos notar pela situação acima que a solução permite múltiplos papéis para cada usuário. No exemplo, somente alunos tem acesso aos recursos da classe MeuRecursoController. Porém para acessar o método meuMetodo(), o usuário deve ser, além de aluno, professor também.
Vejam o poder que essa ferramenta dá na hora de definir as restrições aos recursos do sistema!
Além disso, a página de login está indicada na classe, enquanto a página de acesso negado está no próprio método. Nice!

E se nem todos os métodos da classe fossem restritos, mas mesmo assim houvéssem recursos que só pudessem ser acessados por usuários que fossem alunos E professores?



A solução acima não restringiria o recurso de maneira adequada, pois alunos OU professores tem acesso ao recurso. Para alterar esse comportamento, alterem o valor do atributo policy da annotation @Roles, que indica a política a ser adotada para restringir o acesso ao recurso:



Agora sim. "RolesPolicy.CONJUNCTION" informa que somente usuários que possuem TODOS os papéis descritos no atributo roles, e não "ao menos um" dos papéis. "RolesPolicy.DISJUNCTION" é o valor padrão do atributo policy, portanto não precisa ser informado.

Eis a última abordagem de controle de acesso: por níveis de acesso.

Por vezes, é conveniente atribuirmos um nível de acesso para cada usuário.
Com isso, podemos fazer restrições do tipo: recurso x só pode ser acessado por usuários com nível de acesso maior ou igual a K.
Isso é pertinente em situações hierárquicas, onde, por exemplo, o gerente pode acessar todos os recursos, mas o desenvolvedor não (¬¬).

Pensando nisso, criei a anotação @AccessLevel, que informa o nível de acesso mínimo requerido para acessar determinado recurso:



No exemplo: para acessar os recursos dessa classe, o usuário deve estar logado. Mas para acessar o método meuMetodo(), o nível de acesso dele deve ser maior ou igual a 3. Caso nível de acesso do usuário seja menor que 3, a navegação é redirecionada para o local informado no atributo accessDeniedPage.

Tudo o que foi dito anteriormente é válido: pode-se usar indiscriminadamente a annotation @AccessLevel, tanto nos métodos quanto na classe, de forma que, para conseguir acesso ao recurso, TODAS as restrições presentes (na classe e no método) devem ser satisfeitas.

É possível definir um range de níveis de acesso. Basta preencher o atributo maximumAccessLevel:



Na maioria dos casos essas restrições resolvem a maior parte dos problemas.
Mas é possível fazer restrições complexas.

Ex.: Permitir acesso aos recursos somente para usuários logados, que sejam professores E alunos, mas que para deletarem devem ser, além de alunos e professores, diretores ou reitores com nível de acesso entre 4 e 15. Se usuário não estiver logado, use a mesma página de login para todos. Mas se ele tentar deletar e não possuir as devidas credenciais, mandem-no para a pqp.



Shit! Escrevi bagarai! Acho que poucos lerão..rs

A parada está bem legal. Como disse, depois de feitas as devidas configurações, agiliza bastante o controle de acesso em suas aplicações. O cara que desenvolve vai passar longe de se preocupar em como implementará as restrições. A única preocupação vai ser com os perfis de acesso, que ele teria de qualquer maneira.

O tendão de Aquiles disso tudo é um tal de refactor friendly. Do jeito que está, se precisássemos trocar a página de login de todos os recursos, teríamos que entrar em cadae alterar um a um.
Esse problema será sanado na próxima versão. Fazer com que, ao invés de passar o endereço direto no @AccessDenied, colocar uma chave de um map que contém todas essas configurações. Afora os detalhes, acho que resolveria e bem esse problema.

Aos que lerem até aqui, por favor, comentem! Para mim, os comentários e sugestões serão de grande valia.
Aliás, sintam-se a vontade pra fazerem o que quiser com o código. Se a galera curtir e começar a utilizar, podemos criar um projeto no source forge para irmos corrigindo e melhorando.

Enfim, espero que essa seja apenas minha primeira contribuição com a comuna open source e com o VRaptor. Digo, espero que seja de fato uma contribuição rs. De qualquer forma, o que vale é a intenção. Estou utilizando isso em minhas aplicações e está ajudando. Espero que o mesmo ocorra com outras pessoas.

A seguir (próximo post), vou explicar como configurar.

That's [almost] all, folks!

 Nome do arquivo access-control-vraptor-1.0.jar [Disk] Download
 Descrição
 Tamanho 25 Kbytes
 Baixado:  158 vez(es)

This message was edited 2 times. Last update was at 11/04/2011 15:04:48

bronx
JavaTeenager
[Avatar]

Membro desde: 24/08/2009 02:59:47
Mensagens: 197
Offline

Galera, a classe RestrictionChecker é a classe responsável por verificar se há restrições e, se houver, verificar se o usuário em questão possui permissão para acessar os recursos.
A classe encontra-se no jar que enviei, então vcs podem criar um ComponentFactory para essa classe e passá-la no construtor do Interceptor. Ou se quiserem, podem dar new quando forem usá-la tbm...quem manda é o freguês

O método que verifica se há restrições no método é o hasRestriction. O método accepts do Interceptor ficaria assim:



O hasRestriction recebe um java.lang.reflect.Method, e não um ResourceMethod do VRaptor!!!!

Feito isso, se houver restrição, então vc deve checar se o usuário logado está restrito. O responsável por isso é o método checkRestrictions da RestrictionChecker (derr rs)...
Ele recebe dois parâmetros: java.lang.reflect.Method, e a interface br.com.bronx.accesscontrol.interfaces.Login. Essa interface é implementada pelo usuário. Já explico.

O método checkRestrictions lança uma Exception, a RestrictionAnnotationException. Essa exceção é lançada quando as annotations são utilizadas indevidamente. As mensagens são explicativas e ajudam muito a resolver o problema.

O retorno do método checkRestrictions é um objeto do tipo RestrictionResult. Esse objeto possui dois atributos: um boolean informando se o usuário tem ou não permissão de acesso (private boolean restricted) e uma String contendo o destino a ser seguido, caso o acesso seja negado (private String destination). O atributo destination guarda o caminho informado na annotation @AccessDenied. Pode ser tanto o loginPage ou o accessDenied, dependendo do motivo da restrição (usuário não está logado ou não possui as credenciais para acessar o recurso).

O Interceptor que utilizo aqui é esse em anexo.

Agora, o atributo Login.

Essa interface Login é uma interface que informa se o usuário está ou não logado no sistema.

Ela descreve 4 métodos:



O método setLoggedIn(boolean loggedIn) geralmente é chamado no momento do login. Após realizar com sucesso o login do usuário, esse valor é setado como true, indicando que o usuário está logado.
Além disso, o setProfile(Profile profile) define o profile do usuário logado, que contém os papéis (roles) e nível de acesso do referido usuário.
Profile é a segunda e última interface a ser implementada pelo desenvolvedor. Possui apenas dois métodos:



Serve basicamente para a ferramenta conseguir extrair os dados do usuário.
Preferi utilizar uma lista de String ao invés de uma lista de Roles para ser o menos intrusivo possível no código do cara. Me lembraria o SelectItem do JSF!

Em anexo, implementação da interface Login e implementação da interface Profile, a título de exemplo. Tudo bem simples e comentado.

Uma possível maneira de usá-los, seria no método de login:



Resumindo: passem um Login para o método checkRestrictions da classe RestrictionChecker. A forma como vc vai implementar é irrelevante para a ferramenta.
É comum ocorrer umas NullPointerExceptions caso as interfaces não tenham sido implementadas adequadamente. Mas isso foge do controle da ferramenta.

É isso.

Testem aí. Se tiverem dificuldades, estamos aí para ajudar.
Depois de tudo configurado adequadamente, não tive problemas na utilização desse solução.
Espero que entendam o que escrevi e que façam bom proveito de tudo. hehe

Abs!


 Nome do arquivo Usuario.java [Disk] Download
 Descrição
 Tamanho 690 bytes
 Baixado:  161 vez(es)

 Nome do arquivo AccessControllerInterceptor.java [Disk] Download
 Descrição
 Tamanho 2 Kbytes
 Baixado:  155 vez(es)

 Nome do arquivo LoginControl.java [Disk] Download
 Descrição
 Tamanho 731 bytes
 Baixado:  161 vez(es)

Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6394
Offline

Muito bom, bronx =)

Isso deixa a autenticação/autorização bem fácil de usar...

No entanto, tenho dúvidas e sugestões:
- O usuário da ferramenta precisa implementar quais interfaces? É suficiente que a entidade Usuario dele implemente Profile? ou ele tem que implementar o loginControl tb?
- O interceptor da última mensagem está dentro do jar? Se adicionarmos o pacote br.com.bronx na configuração do VRaptor no web.xml, ele conseguiria ler as suas classes tranquilamente...
- Tem algum jeito de setar páginas padrão pra login e para accessDenied? a meu ver seriam (quase) sempre as mesmas... qto menos configuração melhor


Além disso, se te interessa colocar esse seu código no código principal do vraptor, adoraríamos a contribuição =) Se não, tudo bem, podemos linkar para o seu projeto da página principal do VRaptor, para todo mundo que precisar de controle de acesso...

Abraços e parabéns =)

--
Caelum
www.caelum.com.br

bronx
JavaTeenager
[Avatar]

Membro desde: 24/08/2009 02:59:47
Mensagens: 197
Offline

Hey man, valeu!!
Estava com medo de receber um "que merda", ou "isso nem ajuda tanto"...hehehe

Quanto aos teus questionamentos:

- O desenvolvedor teria que implementar as interfaces Login (para passar pro RestrictionChecker) e Profile (para passar para Login). Mas agora, posto da maneira que vc colocou, seria mais interessante ele implementar somente uma interface, não? Alteração [muito] simples. rs
- Essas classes que enviei separadamente não estão no jar. Seriam implementadas pelo usuário. Podemos discutir se deixamos ela (Interceptor) no jar ou não, pois caso ela esteja dentro, não sei como o Interceptor receberia a implementação do desenvolvedor da interface Login ou de alguma outra que possamos criar, caso alteremos o código...
- Esse recurso (páginas padrões) eu acabei não considerando, e pretendia deixar para a próxima versão. Mas é xuxú no palito, [muito mais] simples de alterar. ^^

Postar isso tudo aqui já mostra que quero deixar essa ferramenta a disposição da galera.
Colocá-la dentro do VRaptor seria style. Pouparia algum trabalho para a galera.

Vamos conversar sobre a melhor maneira de fazer isso.
Aliás, vamos discutir todos esses pontos que vc levantou.
Mas antes, seria interessante que você (e todos que quiserem ^^) testasse(m) a parada. Para ter um feeling do que foi feito, como funciona, e de possíveis melhorias além dessas que você sugeriu. As sugestões da galera são muito importantes nessas horas.

Mas enfim, usem! Não fiz pra ficar empoeirando no meu HD...rs
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6394
Offline

bronx wrote:
- Essas classes que enviei separadamente não estão no jar. Seriam implementadas pelo usuário. Podemos discutir se deixamos ela (Interceptor) no jar ou não, pois caso ela esteja dentro, não sei como o Interceptor receberia a implementação do desenvolvedor da interface Login ou de alguma outra que possamos criar, caso alteremos o código...

se vc receber o Login no construtor, e a implementação dele estiver anotada com @Component, o VRaptor vai saber injetar sem problemas, mesmo que esteja tudo dentro do jar...

Por enquanto, vc poderia colocar o código que vc já tem no github? http://github.com
Pra isso vc precisa saber mexer um pouco no GIT... tutoriais em http://github.com/guides

[]'s

--
Caelum
www.caelum.com.br

sobreira
Thread.start()
[Avatar]

Membro desde: 25/11/2008 12:02:41
Mensagens: 26
Offline

Olá Bronx! Primeiramente parabéns pelo projeto. Ele vem a simplificar muito o controle de acesso da aplicação e já de início contando com recursos como roles e níveis de acesso.

Gostaria de fazer uma observação sobre a interface Profile. Ela me obriga a implementar o método:

Isto me complicou a principio, pois eu gostaria que estas roles fossem implementadas numa outra classe, o que facilitaria a persistência das mesmas no banco de dados, ou mesmo num diretorio LDAP.

Minha sugestão seria algo como:

Onde UserRole seria uma interface bem simples com apenas um método como:

Fica ai a sugestão. E mais uma vez parabéns!

This message was edited 2 times. Last update was at 16/01/2010 21:21:44


Fabiano S. Coelho
http://blog.sobreira.eti.br
[WWW]
bronx
JavaTeenager
[Avatar]

Membro desde: 24/08/2009 02:59:47
Mensagens: 197
Offline

Então Lucas, não tinha certeza quanto ao comportamento do VRaptor / Spring quanto à injeção de interfaces.

Sendo assim, fica simples deixar tudo pronto dentro do jar.
Só dificultaria caso o usuário precisasse tomar alguma ação mais específica caso o acesso fosse negado. Sei lá, gravar um log, ou algo do tipo. Mas aí ele poderia criar o próprio interceptor sem problemas.

Pensei em acrescentar os métodos setDefaultLoginPage(String defaultLoginPage) e setDefaultAccessDeniedPage(String defaultAccessDeniedPage) na classe RestrictionChecker. Assim, antes de executar o método checkRestrictions(...), o desenvolvedor informaria à ferramenta quais são as páginas de login e acesso negado padrões. Hard-coded, .properties...whatever. Ele só teria q fazer isso antes da verificação. E ainda assim as regras de utilização da annotation @AccessDenied seriam válidas. ^^
Mas isso só seria viável caso o Interceptor não esteja dentro do jar. Para que funcionasse com ele (Interceptor) dentro do jar, teríamos que passar essas informações através do Login que seria injetado...

Anyway, vou colocar a parada no github. Essa semana dou uma estudada e já lanço tudo lá.
Aliás, requisitos não funcionais: sugerem algum nome pro projeto?

Por ora, temos essas melhorias a serem feitas: páginas de login e acesso negado defaults, Interceptor padrão dentro do jar e a obrigatoriedade de implementar apenas uma interface, right?? Continuem sugerindo, e por favor, TESTEM!!


Hail sobreira!

Cara, juro que pensei nesse esquema de List<Role>, até porquê na implementação da ferramenta os papéis extraídos da annotation @Roles são armazenados num List<Role>. Porém, pensei que isso deixasse a implementação mais acoplada ainda à ferramenta. Fica mais simples devolver somente a lista com os nomes dos papéis.

Mas brother, a grande sacada do uso de interfaces é que ela fica totalmente independente da implementação. O que quero dizer, é que você pode implementar esse esquema que vc disse sem o menor problema. Faça da forma que vc propôs, criando sua própria classe UserRole e criando seu List<UserRole>. Na implementação do getRoles, poderia fazer algo do tipo:



Enfim, só uma sugestão. Mas você pode fazer da maneira que quiser!!!
Por favor, teste a parada e dê um feedback. É minha primeira contribuição em algum projeto open-source, então as opiniões são extremamente importantes para mim.

Valeu galera. Novamente: TESTEM! rs

[]'s
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6394
Offline

bronx wrote:
Pensei em acrescentar os métodos setDefaultLoginPage(String defaultLoginPage) e setDefaultAccessDeniedPage(String defaultAccessDeniedPage) na classe RestrictionChecker. Assim, antes de executar o método checkRestrictions(...), o desenvolvedor informaria à ferramenta quais são as páginas de login e acesso negado padrões. Hard-coded, .properties...whatever. Ele só teria q fazer isso antes da verificação. E ainda assim as regras de utilização da annotation @AccessDenied seriam válidas. ^^

Tem um jeito mais legal: anotar as lógicas de loginPage e accessDeniedPage:


Tem como ler isso no startUp da aplicação e configurar sua ferramenta =)
Só mexer um pouquinho com a api interna do VRaptor, posso te ajudar com isso =)

bronx wrote:
Mas isso só seria viável caso o Interceptor não esteja dentro do jar. Para que funcionasse com ele (Interceptor) dentro do jar, teríamos que passar essas informações através do Login que seria injetado...

Mesmo que a implementação do Login esteja fora do jar, o VRaptor consegue injetar sem problemas... A única coisa importante é que o Interceptor seja lido e gerenciado pelo vraptor, não importam nem onde ele está, nem onde as dependências dele estão...

bronx wrote:
Anyway, vou colocar a parada no github. Essa semana dou uma estudada e já lanço tudo lá.
Aliás, requisitos não funcionais: sugerem algum nome pro projeto?

bom... VAuth (VRaptor Authentication & Authorization), VAAS (VRaptor Authentication & Authorization System)...
mas acho que um nome mais aleatório seria legal tb...

--
Caelum
www.caelum.com.br

yorgan
GUJ Ranger
[Avatar]

Membro desde: 14/08/2006 19:41:31
Mensagens: 888
Localização: Floripa/SC
Offline

Parabéns pela iniciativa Bronx.
Só uma dúvida, ele precisa de alguma lib fora as que vem com o VRaptor?
Estou testando aqui mas ao quando anoto a classe AccessControllerInterceptor com @Intercepts o sistema retorna o seguinte erro:



[]'s

Daniel
[Email] [WWW]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6394
Offline

yorgan, tenta colocar isso no seu web.xml:



se já tiver um param com esse nome, coloque o valor acima, separado por ; sem espaços

--
Caelum
www.caelum.com.br

yorgan
GUJ Ranger
[Avatar]

Membro desde: 14/08/2006 19:41:31
Mensagens: 888
Localização: Floripa/SC
Offline

Não deu certo.
Mas a classe RestrictionChecker não deveria estar anotada como @Component?

[]'s

Daniel
[Email] [WWW]
boneazul
Java Ninja
[Avatar]

Membro desde: 29/10/2007 17:13:59
Mensagens: 284
Offline

É sempre que precisamos de algo relacionado a perfil de acesso sempre acaba vindo o cliente e suas loucuras

"que tal perfil pode fazer isso mais não pode fazer aquilo e ele também é gerente mais esse perfil era o perfil de administrador aquilo ,mas ainda tem que quem era administrador nao pode fazer aquilo mais a nao ser que pelo menos blablabla"

o cliente te passa a regra de negocio mais cabeluda do mundo ligado ao perfil de acesso que nem sempre o pensamento "hierarquia" resolve...

Parabens pela iniciativa ....para quem ta começando pensar num metodo de implementação de perfil é sempre complicado....

Vo postar um modelo bem simples que eu uso a mais de 5 anos pra agregar mais ao topico e que sempre me atendeu em TODOS os caso tanto pra criação,quanto pra mudança e o legal é que ele desacopla seu sistema totalmente das hierarquias de acesso ele nao usa o velho roles que pra mim sempre foi algo que mais atrapalhou do que ajudou

ele consiste em 2 classes(pensando que no meu caso sempre utilizo banco de dados para esse acesso,pra outros casos como ldap por exemplo seria pouca mudança a ser feita) vamo lá

então vão ser 2 classes entidades (3 tabelas de banco) , 2 interceptor , 2 anotações
lembrando que estou postando exemplo com o hibernate


Acao.java


Perfil.java



Beleza.... explicando as classe eu sempre falo que um determinado perfil pode realizar x acoes ...
a ideia é exatamente igual ao pensamento
a pessoa pode fazer isso e isso mais num pode fazer aquilo , se amanha muda fica facil pq apenas retiro aquela ação daquele determinado perfil
que resolve o problema para o PERFIL todo diferente se amanha acontece de mudar apenas uma regra para esse perfil que va entrar em conflito apenas crio outro perfil com as mesmas ações diferenciando o que pode o nao fazer a mais ou a menos.....


vamo pensar em exemplo prático vamo lá cadastro de cliente...

vamos supor que o seu sistema contenha 6 tipo de ações diferentes a serem feitas com um cliente

Poder listar
Poder inserir
Poder alterar
Poder desativar
Poder deletar
Poder ver detalhes sobre o cliente

são ações isoladas...ou seja ele pode ou não pentencer a um perfil de acesso ou a mais de 1 correto??

agora chega o cliente e te fala entao
o admin pode fazer tudo ok ??

ai a gente
Perfil : admin
*Poder listar
*Poder inserir
*Poder alterar
*Poder desativar
*Poder deletar
*Poder ver detalhes sobre o cliente

ai ele fala o gerente pode fazer quase tudo so num pode deletar do banco mas pode desativar

ai a gente
Perfil : gerente
*Poder listar
*Poder inserir
*Poder alterar
*Poder desativar
*Poder ver detalhes sobre o cliente

se amanha aparece uma regra nova com funcionalidade nova ou alguma funcionalidade ja implementada se divida em pontos distindos em duas
imagine que voce monte uma listagem que exiba dados em valores ai o cliente te pede olha esse valor ai tem que ser colocado no perfil ltamem se ele pode ver e gerente não pode ver mais diretor pode blz?

ai a gente cria a ação de poder ver valores e atribui esse poder só a quem deve..assim falando parece ser algo complicado...mas vamos continuar

pra exemplificar vamos fazer uns inserts no banco



//Beleza perfil criado agora vamos aos interceptors e anotações

primeiro as anotações
NotCheckSession.java


VerifyAccess.java


e finalmente os dois interceptor um primeiro que intercepta todos os recursos pensando que para fazer algo seu usuario TEM que estar logado

AuthenticationInterceptor.java


AccessInterceptor.java


Prontinho com esses 2 interceptor estou pronto pra utilizar qualquer recurso
agora vamos colocar meus exemplos praticos



Bom pessoal esse é so mais um exemplo de como implementar um perfil de acesso eu particularmente gosto ....
alguma duvida da um toque ai mas sempre atendeu e muito bem o que precisei fazer ligado a essa area











This message was edited 1 time. Last update was at 17/01/2010 22:28:26

[Email]
Lucas Cavalcanti
GUJ Hacker
[Avatar]

Membro desde: 08/07/2007 00:08:14
Mensagens: 6394
Offline

bom, boneazul... esse seu modelo é bem genérico, mas é bastante mais complexo também, e mais difícil de se trabalhar...

uma dica:
@VerifyAccess(action=1) não é nem um pouco bom... assim vc é obrigado a saber que a ação de id=1 é XXX, e se o cara que adicionou isso no banco não souber, ferrou, e se o desenvolvedor não souber ferrou... o desenvolvedor vai ter que ter um "catálogo de ações" enquanto estiver desenvolvendo...

Tem um boa prática chamada YAGNI (You ain't going to need It ou Vc não vai precisar disso)... ou seja, nunca faça uma solução complicada, se uma simples for o suficiente por um simples "pode ser que o cliente fique louco e mude de idéia no meio do caminho" ou "acho que vou precisar disso mais pra frente"...

Sua solução é legal (fora a referência por ID) para qdo vc precisa dessa generalização...

Senão, a solução do bronx parece suficiente, simples e fácil de usar, e é isso que importa na maioria dos casos...


--
Caelum
www.caelum.com.br

boneazul
Java Ninja
[Avatar]

Membro desde: 29/10/2007 17:13:59
Mensagens: 284
Offline

Lucas Cavalcanti wrote:bom, boneazul... esse seu modelo é bem genérico, mas é bastante mais complexo também, e mais difícil de se trabalhar...

uma dica:
@VerifyAccess(action=1) não é nem um pouco bom... assim vc é obrigado a saber que a ação de id=1 é XXX, e se o cara que adicionou isso no banco não souber, ferrou, e se o desenvolvedor não souber ferrou... o desenvolvedor vai ter que ter um "catálogo de ações" enquanto estiver desenvolvendo...

Tem um boa prática chamada YAGNI (You ain't going to need It ou Vc não vai precisar disso)... ou seja, nunca faça uma solução complicada, se uma simples for o suficiente por um simples "pode ser que o cliente fique louco e mude de idéia no meio do caminho" ou "acho que vou precisar disso mais pra frente"...

Sua solução é legal (fora a referência por ID) para qdo vc precisa dessa generalização...

Senão, a solução do bronx parece suficiente, simples e fácil de usar, e é isso que importa na maioria dos casos...



é Lucas realmente concordo quanto ao id preciso sempre saber a referencia...ponto negativo ainda não pensei numa solução dessa referencia como poderia ser......pq o desenvolvedor realmente tem que saber o id ligado a ação mas como tudo tem um porem ele não tem a necessidade de saber qual o perfil precisa ter essa ação perde-se de um lado ganha-se de outro...


o modelo de hierarquia eu nao precisaria saber o que faz ,mas se muda eu preciso buscar todos os que fazem e mudar..a ideía é que é bem mais flexivel...pq fica a cargo do proprio cliente definir seus perfis e tirar essa responsabilidade de código entende???eu nunca mais mudo uma linha de codigo pq a permissao é vista em tempo de execução se amanha muda um perfil todo nenhuma linha é modificada....quanto ao id realmente é algo a se pensar em algo mais programatico do que ids.....

quanto a do bronx ele realmente é mais simples só que necessita sempre repetição de anotações na maioria dos casos e sempre fica na mão do programador saber o que cada pessoa tem que fazer o que na pratica pelo menos na minha empresa nunca rolou não sei outras ...a minha ideia é justamente inversão de papeis o cliente ajusta como quer e o sistema se vira com o resto...longe de mim estar criticando algo .. apenas coloquei outra solução só pra quem interessar ou ate ter alguma ideia relativa a esse id ..postei apenas para enriquecer o tópico....


obrigado pelas dicas...
[Email]
sobreira
Thread.start()
[Avatar]

Membro desde: 25/11/2008 12:02:41
Mensagens: 26
Offline

Estou tendo a seguinte excessão no redirecionamento ao acessar diretamente uma uri anotada com as restrições:


Meu método list() anotado está assim:


O Interceptor que estou usando é AccessControllerInterceptor fornecido pelo Bronx.


Fabiano S. Coelho
http://blog.sobreira.eti.br
[WWW]
 
Índice dos Fóruns » Frameworks e Bibliotecas brasileiros
Ir para:   
Powered by JForum 2.1.8 © JForum Team