Minha contribuição - Controle de acesso VRaptor 3

175 respostas
B

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:

package br.com.bronx.accesscontrol;

import br.com.caelum.vraptor.Resource;

@Resource
public class MinhaClasseController {
	
	public void meuMetodo(){
		//
	}
}

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?

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.LoggedIn;
import br.com.caelum.vraptor.Resource;

@Resource
public class MeuRecursoController {

	@LoggedIn
	public void meuMetodo(){
		//
	}
}

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:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.LoggedIn;
import br.com.caelum.vraptor.Resource;

@Resource
public class MeuRecursoController {

	@LoggedIn
	@AccessDenied(loginPage="/login")
	public void meuMetodo(){
		//
	}
}

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:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.LoggedIn;
import br.com.caelum.vraptor.Resource;

@Resource
@LoggedIn
@AccessDenied(loginPage="/login")
public class MeuRecursoController {

	public void meuMetodo(){
		//
	}
}

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):

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.LoggedIn;
import br.com.caelum.vraptor.Resource;

@Resource
@AccessDenied(loginPage="/login")
public class MeuRecursoController {

	@LoggedIn
	public void meuMetodo() {
		//
	}
	
	public void meuOutroMetodo() {
		//
	}
	
	@LoggedIn
	public void meuTerceiroMetodo() {
		//
	}
	
}

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:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.LoggedIn;
import br.com.caelum.vraptor.Resource;

@Resource
@AccessDenied(loginPage="/login")
public class MeuRecursoController {

	@LoggedIn
	public void meuMetodo() {
		//
	}
	
	public void meuOutroMetodo() {
		//
	}
	
	@LoggedIn
	@AccessDenied(loginPage="/outraPaginaDeLogin")
	public void meuTerceiroMetodo() {
		//
	}
	
}

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:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.LoggedIn;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.caelum.vraptor.Resource;

@Resource
public class MeuRecursoController {

	@LoggedIn
	@Roles(roles="gerente")
	@AccessDenied(loginPage="/login")
	public void meuMetodo() {
		//
	}
}

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:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.caelum.vraptor.Resource;

@Resource
public class MeuRecursoController {

	@Roles(roles="gerente")
	@AccessDenied(loginPage="/login")
	public void meuMetodo() {
		//
	}
}

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

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.caelum.vraptor.Resource;

@Resource
public class MeuRecursoController {

	@Roles(roles="gerente")
	@AccessDenied(loginPage="/login", accessDeniedPage="/acessoRestrito")
	public void meuMetodo() {
		//
	}
}

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ó:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.caelum.vraptor.Resource;

@Resource
public class MeuRecursoController {

	@Roles(roles="gerente;supervisor")
	@AccessDenied(loginPage="/login", accessDeniedPage="/acessoRestrito")
	public void meuMetodo() {
		//
	}
}

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):

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.caelum.vraptor.Resource;

@Resource
public class MeuRecursoController {

	@Roles(roles="gerente/supervisor", separator="/")
	@AccessDenied(loginPage="/login", accessDeniedPage="/acessoRestrito")
	public void meuMetodo() {
		//
	}
}

Combinando entre classe e método:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.caelum.vraptor.Resource;

@Resource
@Roles(roles="aluno")
@AccessDenied(loginPage="/login")
public class MeuRecursoController {

	@Roles(roles="professor")
	@AccessDenied(accessDeniedPage="/acessoRestrito")
	public void meuMetodo() {
		//
	}
	
	public void meuOutroMetodo() {
		//
	}
	
	@AccessDenied(loginPage="/outraPaginaDeLogin")
	public void meuTerceiroMetodo() {
		//
	}
	
}

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?

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.caelum.vraptor.Resource;

@Resource
@AccessDenied(loginPage="/login", accessDeniedPage="/acessoRestrito")
public class MeuRecursoController {

	@Roles(roles="aluno;professor")
	public void meuMetodo() {
		//
	}
	
	public void meuOutroMetodo() {
		//
	}
	
	@AccessDenied(loginPage="/outraPaginaDeLogin")
	public void meuTerceiroMetodo() {
		//
	}
	
}

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:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.bronx.accesscontrol.annotation.RolesPolicy;
import br.com.caelum.vraptor.Resource;

@Resource
@AccessDenied(loginPage="/login", accessDeniedPage="/acessoRestrito")
public class MeuRecursoController {

	@Roles(roles="aluno;professor", policy=RolesPolicy.CONJUNCTION)
	public void meuMetodo() {
		//
	}
	
	public void meuOutroMetodo() {
		//
	}
	
	@AccessDenied(loginPage="/outraPaginaDeLogin")
	public void meuTerceiroMetodo() {
		//
	}
	
}

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:

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.AccessLevel;
import br.com.bronx.accesscontrol.annotation.LoggedIn;
import br.com.caelum.vraptor.Resource;

@Resource
@LoggedIn
@AccessDenied(loginPage="/login", accessDeniedPage="/acessoRestrito")
public class MeuRecursoController {

	@AccessLevel(minimumAccessLevel=3)
	public void meuMetodo() {
		//
	}
	
	public void meuOutroMetodo() {
		//
	}
	
	@AccessDenied(loginPage="/outraPaginaDeLogin")
	public void meuTerceiroMetodo() {
		//
	}
	
}

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:

@Resource
@LoggedIn
@AccessDenied(loginPage="/login", accessDeniedPage="/acessoRestrito")
public class MeuRecursoController {

	@AccessLevel(minimumAccessLevel=3, maximumAccessLevel=10)
	public void meuMetodo() {
		//
	}
	
	public void meuOutroMetodo() {
		//
	}
	
	@Roles(roles="estagiario")
	@AccessDenied(loginPage="/outraPaginaDeLogin")
	public void meuTerceiroMetodo() {
		//
	}
	
}

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.

package br.com.bronx.accesscontrol;

import br.com.bronx.accesscontrol.annotation.AccessDenied;
import br.com.bronx.accesscontrol.annotation.AccessLevel;
import br.com.bronx.accesscontrol.annotation.LoggedIn;
import br.com.bronx.accesscontrol.annotation.Roles;
import br.com.bronx.accesscontrol.annotation.RolesPolicy;
import br.com.caelum.vraptor.Resource;

@Resource
@LoggedIn //desnecessário utilizar essa annotation
@Roles(roles="alunos;professores", policy=RolesPolicy.CONJUNCTION)
@AccessDenied(loginPage="/login", accessDeniedPage="/acessoRestrito")
public class MeuRecursoController {

	public void meuMetodo() {
		//
	}
	
	@Roles(roles="reitor#diretor", separator="#")
	@AccessLevel(minimumAccessLevel=4, maximumAccessLevel=15)
	@AccessDenied(accessDeniedPage="/putaQuePariu")
	public void deletar() {
		//
	}
	
}

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!

175 Respostas

B

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:

@Override
	public boolean accepts(ResourceMethod method) {
		//this.restrictionChecker = RestrictionChecker(); ***prefiram injetar o objeto...é mais elegante! ^^
		return this.restrictionChecker.hasRestriction(method.getMethod());
	}

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:

public boolean isLoggedIn();
	public void setLoggedIn(boolean loggedIn);
	public Profile getProfile();
	public void setProfile(Profile profile);

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:

public List<String> getRoles();
	public int getAccessLevel();

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:

//Na vida real, o método receberia um Usuario 
	public void logar(String login, String senha){
		//Busca o usuário com base nos dados informados, por exemplo
		login.setLoggedIn(true);//se usuário logou com sucesso
		login.setProfile(usuarioLogado);//idem
		//outras operações
	}

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!

L

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 =)

B

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

L

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

S

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!

B

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

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, até porquê na implementação da ferramenta os papéis extraídos da annotation @Roles são armazenados num List. 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. Na implementação do getRoles, poderia fazer algo do tipo:

public List<String> getRoles() {
                List<String> stringRoles = new ArrayList<String>();
                for (UserRole userRole : this.userRoles) {
                      stringRoles.add(userRole.getRoleName());
                }
                return stringRoles;
        }

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

Valeu galera. Novamente: TESTEM! rs

[]'s

L

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

@Resource
public class LoginController {
    //...
    @LoginPage
    public void login() {...}

    @AccessDeniedPage
    public void accessDenied() {...}
}

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 =)

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…

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

Y

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:

SEVERE: Servlet.service() for servlet default threw exception
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accessControllerInterceptor' defined in file [/Users/danielkist/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/loja/WEB-INF/classes/testes/AccessControllerInterceptor.class]: Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker]: : No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:698)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:328)
	at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:385)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:375)
	at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1069)
	at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:221)
	at br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:240)
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:58)
	at br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:32)
	at br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:30)
	at com.google.common.collect.Lists$TransformingRandomAccessList.get(Lists.java:431)
	at java.util.AbstractList$Itr.next(AbstractList.java:345)
	at com.google.common.collect.Iterators$7.computeNext(Iterators.java:602)
	at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:135)
	at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:130)
	at com.google.common.collect.Lists.newArrayList(Lists.java:131)
	at com.google.common.collect.Collections2$FilteredCollection.toArray(Collections2.java:219)
	at br.com.caelum.vraptor.interceptor.DefaultInterceptorRegistry.interceptorsFor(DefaultInterceptorRegistry.java:50)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:42)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
	at java.lang.Thread.run(Thread.java:637)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:896)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:765)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:680)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:771)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:691)
	... 52 more

[]'s

Daniel

L

yorgan, tenta colocar isso no seu web.xml:

<context-param>
    <param-name>br.com.caelum.vraptor.packages</param-name>
    <param-value>br.com.bronx</param-value>
</context-param>

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

Y

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

[]'s

Daniel

B

É 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

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="acoes")
public class Acao {	
	@Id
    @GeneratedValue
    @Column(name="aco_id")
    Long id;
	@Column(name="aco_titulo")
	String titulo;
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getTitulo() {
		return titulo;
	}
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}
	
}

Perfil.java

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;


@Entity
@Table(name="perfil")
public class Perfil {
	@Id
    @GeneratedValue
    @Column(name="per_id")
	Long id;
	@Column(name="per_titulo")
	String titulo;
	
	
	@ManyToMany(cascade = {javax.persistence.CascadeType.ALL})
	@JoinTable(   
            name="acesso",   
            joinColumns=@JoinColumn(name="per_id", referencedColumnName="per_id"),   
            inverseJoinColumns=@JoinColumn(name="aco_id", referencedColumnName="aco_id")   
        )  
    @Fetch(FetchMode.JOIN) 
	private  List<Acao> acoes;
	

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getTitulo() {
		return titulo;
	}

	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}

	public List<Acao> getAcoes() {
		return acoes;
	}

	public void setAcoes(List<Acao> acoes) {
		this.acoes = acoes;
	}	
	
}

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

//Primeiro voce cadastra todas as ações que seu sistema possui
Acao a1=new Acao();
a1.setTitulo("Listar clientes");
Acao a2=new Acao();
a2.setTitulo("Inserir clientes");
Acao a3=new Acao();
a3.setTitulo("Alterar clientes");
Acao a4=new Acao();
a4.setTitulo("Desativar clientes");
Acao a5=new Acao();
a5.setTitulo("Deletar clientes");
Acao a6=new Acao();
a6.setTitulo("Visualizar detalhes de cliente ");
.
.
.
.
//continuando com todas as ações possiveis

//Ai vamos cadastrar um perfil de exemplo
Perfil gerente=new Perfil();
gerente.setTitulo("Gerente");
List<Acao> acoes=new ArrayList<Acao>();
acoes.add(a1);
acoes.add(a2);
acoes.add(a3);
acoes.add(a4);
acoes.add(a6);
gerente.setAcoes(acoes);

//ai manda salvar no hibernate talz isso fazendo na mão eu uso uma interface que ja faz esse crud pra facilitar

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

primeiro as anotações
NotCheckSession.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface NotCheckSession {}

VerifyAccess.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface VerifyAccess 
{
	int action();
	
}

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

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.view.Results;
import br.com.jslsolucoes.granchef.annotations.NotCheckSession;
import br.com.jslsolucoes.granchef.controllers.UsuarioController;
import br.com.jslsolucoes.granchef.dao.UsuarioDao;
import br.com.jslsolucoes.granchef.models.Acao;
import br.com.jslsolucoes.granchef.models.Usuario;
import br.com.jslsolucoes.granchef.others.MySession;


public class AuthenticationInterceptor implements Interceptor {
	MySession sessao;
	Result result;
	UsuarioDao dao;
	public AuthenticationInterceptor(MySession sessao,Result result,UsuarioDao dao)
	{
		this.result=result;
		this.sessao=sessao;
		this.dao=dao;
	}
   
    //Verifica se a anotação @NotCheckSession está presente ..por exemplo no seu metodo login ele iria ficar num loop infinito
   //pois eu redireciono pra login so que antes ele vai ver tem usuario na sessao redireciono de novo ai fica assim eternamente
//pra evitar isso criei essa anotação que é no caso de um metodo não precisar ser checkado sessão o que dificilmente acontece
    public boolean accepts(ResourceMethod method) {
    	return  !method.getMethod().isAnnotationPresent(NotCheckSession.class);
    }

    public void intercept(InterceptorStack stack, ResourceMethod method, 
                        Object resourceInstance) throws InterceptionException {
    	//aqui eu pego se tenho um objeto usuario na sessao e vejo se ele é nulo que no caso nao esta logado
        if(this.sessao.getObjectSession("usuario")==null)	result.use(Results.logic()).redirectTo(UsuarioController.class).login();
    	else stack.next(method, resourceInstance);    
    }
}

AccessInterceptor.java

package br.com.jslsolucoes.granchef.interceptors;

import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.view.Results;
import br.com.jslsolucoes.granchef.annotations.VerifyAccess;
import br.com.jslsolucoes.granchef.controllers.GranchefController;
import br.com.jslsolucoes.granchef.models.Acao;
import br.com.jslsolucoes.granchef.models.Usuario;
import br.com.jslsolucoes.granchef.others.MySession;


public class AcessInterceptor implements Interceptor {
	MySession sessao;
	Result result;
	int action;
	public AcessInterceptor(MySession sessao,Result result)
	{
		this.result=result;
		this.sessao=sessao;
	}
	
    public boolean accepts(ResourceMethod method) {
    	if(method.getMethod().isAnnotationPresent(VerifyAccess.class))
    	{
    		action=method.getMethod().getAnnotation(VerifyAccess.class).action();
    		return true;
    	}
    	else return false;
    }

    public void intercept(InterceptorStack stack, ResourceMethod method, 
                        Object resourceInstance) throws InterceptionException {
    	
    	boolean hasAction=false;
    	for(Acao a : ((Usuario) sessao.getObjectSession("usuario")).getPerfil().getAcoes())	if(a.getId()==action) hasAction=true;
    	if(!hasAction) result.use(Results.logic()).redirectTo(GranchefController.class).noAction();
    	else stack.next(method, resourceInstance);
    }
}

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

@Resource
public class ClienteController{
         //atributos
         //construtor


        //ai começo a brincadeira
       //eu falo que pra listar precisa tem o id 1 ligado ao seu perfil seja ele qual for eu nao falo o perfil que acessa mais sim a ação que o acessa
        @VerifyAccess(action=1)
        public void listar(){

        }

 @VerifyAccess(action=2)
        public void inserir(){

        }

 @VerifyAccess(action=3)
        public void editar(){

        }
       //assim pra qualquer metodo ou seja fica mais simples pq acabo usando apenas 1 anotação
       //ai o esquem se vira com o resto...
      //caso eu queira que não precise checar sessao ou ação é so colocar a anotação em cima que ele passa batido em tudo

      @NotCheckSession
      public void teste(){
     
      }
}

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

L

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…

B

Lucas Cavalcanti:
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…

S

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

br.com.caelum.vraptor.view.ResultException: Given uri /user/accessDenied responds to method: public void br.eti.sobreira.bookstore.controller.UserController.accessDenied(). Use result.use(logic()).redirectTo(UserController.class).accessDenied() instead. br.com.caelum.vraptor.view.DefaultPageResult.checkForLogic(DefaultPageResult.java:102) br.com.caelum.vraptor.view.DefaultPageResult.redirect(DefaultPageResult.java:92) br.eti.sobreira.bookstore.interceptor.AccessControllerInterceptor.intercept(AccessControllerInterceptor.java:46) br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:45) br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46) br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80) br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67) br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62) br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91) br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55) br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)

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

@LoggedIn @Roles(roles="admin") @AccessDenied(loginPage="/user/accessDenied", accessDeniedPage="/user/accessDenied") public List<User> list() { return dao.list(); }

O Interceptor que estou usando é AccessControllerInterceptor fornecido pelo Bronx.

J

bronx ! poupou muito tempo de trabalho meu !

Muito Agradecido Irmão … precisando tamos ai !

Otima iniciatica !

J

bronx …

Eu estou com um projeto aqui que é assim !

CONTROLE DE USUARIOS

USUÁRIOS------------------------GRUPOS-------------------PERMISSÕES------------------SISTEMA-----------MENU---------------PÁGINAS
Junior ADMIN Ler/Pesquisar/Editar CAC/NOTAS L/P/E x.jsp/y.jsp/h.jsp

O que você acha ?

L

Achei bacana esse esquema de autenticação. As sugestões do pessoal também estão muito boas. Eu só vou dar umas dicas que podem ajudar:

  1. Aquele esquema do separador é meio estranho. Acho que, ao invés de:
@Roles(roles="gerente;supervisor")

Poderia mudar para:

@Roles(roles={"gerente","supervisor"})

Não é difícil a implementação (roles se tornaria um array de String), e quando só há um parâmetro, as chaves são opcionais. Ficaria assim:

@Retention(RetentionPolicy.RUNTIME)
public @interface Roles {
	String[] roles();
	RolesPolicy policy() default RolesPolicy.DISJUNCTION;
}
  1. A aplicação VRaptor com a qual trabalho, existe a necessidade de ter logout. Dei uma olhada rápida no seu código, mas ainda não sei como acrescentaria essa “feature”. Mas basicamente seria uma action anotada assim:
@Resource
public class MeuRecursoController {  
    
    @LoggedOut
    public void tchau() {
    
    }
}

E que por trás dos panos, removeria o usuário profile presente na sessão.

  1. Pra quem usa Javascript, enxertar uma tela de login quando se esperava um pequeno bloco de html é frustrante. O interessante é retornar o erro HTTP (401) para que o método Ajax saiba tratá-lo. Acredito que é só acertar isso no interceptor que verifica a autenticação.

É isso. Espero ter ajudado.

B

Perfect! Assim ficaria muito mais fácil e elegante fazer a parada.
De qualquer forma, ainda assim deixaria os métodos setDefaultLoginPage e setDefaultAccessDeniedPage, pois as vezes a página de login do cara pode nao se referenciar a uma página/recurso controlado pelo VRaptor.

A implementação do Login estará obrigatoriamente fora do jar. 8) O que quis dizer é que caso o desenvolvedor precise utilizar os métodos setDefaultLoginPage e setDefaultAccessDeniedPage ao invés de anotar os recursos da maneira que você falou, eles terão que criar sua própria implementação do Interceptor, pois a que viria dentro do jar nao conseguiria receber essas informações, a não ser que elas estivessem dentro do Login que seria injetado!! :wink:

Hahaha…Criatividade passou longe no “VAAS”…hehehehe
Pensei em RestricTRex…sei lá…
Daqui a pouco vão sugerir “Cadillac & Dinossaurs”…kkkk

yorgan,

Eu até tinha anotado o RestrictionChecker com @Component, mas como não sabia que os pacotes dentro dos jars também poderiam ser gerenciados pelo VRaptor, acabou não funcionando e eu tive que tirar a anotação e acabei criando um ComponentFactory para essa classe.
Faça o mesmo: crie seu ComponentFactory para o RestrictionChecker, ou dê “new” diretamente no Interceptor. Corrigiremos isso next time! ^^

boneazul,

Bela contribuição.
Muitos controles de acesso utilizam a idéia de roles. Por isso que dei atenção a esse esquema.
Sua abordagem é diferente, mas achei interessante.
De qualquer forma, agregou ao tópico! :smiley: :smiley: Valeu.

sobreira,

Então, o VRaptor não permite “self-redirecting” dessa maneira.
Entendo que nesses casos é interessante que o usuário utilize o redirecionamento da maneira descrita, mas lançar uma exception por ele nao ter feito assim acaba limitando um pouco a parada. :frowning:
Porém, não me lembro o que fiz para solucionar isso :frowning: . Estou na casa da minha namorada e meu note não está aqui. Shit.
Mais tarde eu posto o que fiz.
Porém, como um workaround rápido e fácil, faça o seguinte: altere o AccessControllerInterceptor para que, no lugar do Result, ele receba um HttpServletResponse. Se não me engano o VRaptor consegue injetar sem precisar criar ComponentFactory para isso.
Feito isso, na linha onde o result realizava o redirecionamento, use o método sendRedirect do HttpServletResponse.
Como disse, mais tarde eu falo o que fiz pra contornar este problema. :thumbup:

Mas é isso galera. Postem as dúvidas, e principalmente, as sugestões!!!
Abs!!!

B

Nice. Confesso que foi minha primeira experiência com annotations. Não tinha (tenho) muita experiência com isso. Aliás, com Java mesmo tenho menos de um ano… :oops:
Mas é bem simples deixar dessa maneira, sem contar que fica bem mais elegante. Boa sugestão! :wink:

Cara, posso estar enganado, mas acho que isso foge um pouco do objetivo da ferramenta. Vamos ter um feeling sobre isso conforme utilizarmos a parada. Mas a sugestão já tá registrada. ^^

Entendo. Como você disse, bastaria fazer um Interceptor personalizado. Caso o restrictionResult.isRestricted() seja verdadeiro, basta forçar um 401. Mas ai, como é muito específico, seria melhor cada um criar sua própria implementação.

Leonardo3001:

É isso. Espero ter ajudado.

Não tenha dúvidas!! :smiley: :smiley:

G

Muito boa a contribuição. Porém não vamos esquecer que no Java há uma API para autenticação e autorização que é o JAAS, que te permite plugar diversos mecanismos para isso. Além de que você não precisa implementar nada na sua aplicação, apenas configurar o container para tal. Com ele é possível controlar tanto a autenticação quanto a autorização necessária para acesso aos recursos.

Só tenho duas sugestões: usar um pouco mais do convention-over-configuration evitando usar tantas anotações e configurações unificadas. Achei um pouco desnecessário usar uma anotação para dizer onde vai quando o usuário não estiver autenticado. Ele sempre deverá ir para a tela de login.

Abraços

B

O seu loginPage e accessDeniedPage estão apontando para o mesmo local. Is that right?? ^^
Além disso, não precisa utilizar a annotation @LoggedIn. Como o cara precisa ser um admin, ele tem que estar logado para que se possa saber quais roles ele possui. A ferramenta já faz essa verificação.

B

garcia-jj:
Muito boa a contribuição. Porém não vamos esquecer que no Java há uma API para autenticação e autorização que é o JAAS, que te permite plugar diversos mecanismos para isso. Além de que você não precisa implementar nada na sua aplicação, apenas configurar o container para tal. Com ele é possível controlar tanto a autenticação quanto a autorização necessária para acesso aos recursos.

Só tenho duas sugestões: usar um pouco mais do convention-over-configuration evitando usar tantas anotações e configurações unificadas. Achei um pouco desnecessário usar uma anotação para dizer onde vai quando o usuário não estiver autenticado. Ele sempre deverá ir para a tela de login.

Abraços

Opa!
Então garcia-jj, esse esquema é específico para o VRaptor. Vale lembrar que nem todos usuários do VRaptor conhecem ou sabem utilizar o JAAS (eu mesmo nem imagino como funciona…=S). Qualquer Servlet Container possui suporte a JAAS?
Agora fiquei curioso: vc utiliza JAAS com o VRaptor? É simples? Vou dar uma estudada ASAP.

Quanto ao CoC: concordo.
Tanto que estamos justamente elaborando uma solução mais simples para não termos que fazer essas configurações em todas as classes/métodos do sistema. A idéia do loginPage é dar o máximo de flexibilidade ao desenvolvedor. Pode existir uma situação onde, antes de ir para a página de login, ele queira exibir alguma informação ao usuário, por exemplo (??? sei lá rs). Mas de qualquer modo, é essa linha que pretendemos adotar: a menor quantidade de configurações possíveis.

Valeu pela contribuição. Será de grande valia!!

S

bronx:
O seu loginPage e accessDeniedPage estão apontando para o mesmo local. Is that right?? ^^
Além disso, não precisa utilizar a annotation @LoggedIn. Como o cara precisa ser um admin, ele tem que estar logado para que se possa saber quais roles ele possui. A ferramenta já faz essa verificação.

Na verdade o código que estou testando é assim:

Tentei das duas formas e a excessão lançada é a mesma. De noite vou testar a solução com o HttpServletResponse e te aviso!

B

Nice.

Acho que até a noite eu posto o que fiz para que funcionasse com o Result.

Abs, e valeu pela força!

B

sobreira:
bronx:
O seu loginPage e accessDeniedPage estão apontando para o mesmo local. Is that right?? ^^
Além disso, não precisa utilizar a annotation @LoggedIn. Como o cara precisa ser um admin, ele tem que estar logado para que se possa saber quais roles ele possui. A ferramenta já faz essa verificação.

Na verdade o código que estou testando é assim:

Tentei das duas formas e a excessão lançada é a mesma. De noite vou testar a solução com o HttpServletResponse e te aviso!

sobreira,

Use “…” antes da URI. Assim:

De qualquer forma, teste com o HttpServletResponse e poste os resultados! :wink:

Abs!

L

sobreira:
bronx:
O seu loginPage e accessDeniedPage estão apontando para o mesmo local. Is that right?? ^^
Além disso, não precisa utilizar a annotation @LoggedIn. Como o cara precisa ser um admin, ele tem que estar logado para que se possa saber quais roles ele possui. A ferramenta já faz essa verificação.

Na verdade o código que estou testando é assim:

Tentei das duas formas e a excessão lançada é a mesma. De noite vou testar a solução com o HttpServletResponse e te aviso!

vc tá usando qual versão do VRaptor?

na mais nova, a 3.1, não dá mais essa exceção forçando usar redirect via método…
http://tinyurl.com/vr3dw

S

Lucas Cavalcanti:
vc tá usando qual versão do VRaptor?

na mais nova, a 3.1, não dá mais essa exceção forçando usar redirect via método…
http://tinyurl.com/vr3dw

Estava com a 3.02. Atualizado e resolvido. Obrigado Lucas!

J

BRONX BOM DIA !

@LoggedIn  
   @Roles(roles="admin")  
   @AccessDenied(loginPage="/user/accessDenied", accessDeniedPage="/user/accessDenied")  
   public List&lt;User&gt; list() {  
       return dao.list();  
 }

ESSE admin, pode ser um valor do banco ? tipo admin/pesquisa/relatorio/edição/etc… ?

S

SIM!

Leia a segunda mensagem do Bronx que ela explica isso. Examine o exemplo da classe Usuario que ele enviou, e veja que o role é capturado pelo método: public List&lt;String&gt; getRoles(); da Interface Profile.

Persistir estes dados é simples. Na sexta mensagem deste mesmo tópico eu questiono isso e na sétima o Bronx mostra uma alternativa. É só ler e decidir como fazer.

J

sobreira Bom dia !

Otimo, tu já fez isso ?

S

Sim.

Criei uma @Entity chamda Roles. Fiz um mapeamento @OneToMany na classe Usuario para esta @Entity e segui a dica do Bronx pra mapear meu Set<Roles> para o List<Strings> retornado pelo public List<String> getRoles(); da minha classe Usuario. É realmente bem simples.

J

sobreira !

Poderia enviar as classes para eu da uma olhada ? [email removido]

Abraço !

B

E ae galera!

sobreira, como foram os testes? Funcionou? O que achou? Sugestões?
Alguém mais testou a parada? yorgan?
Dêem suas opiniões!!

Lucas,
Ontem quebrei a cabeça com o github. Na real, fiquei pouco mais de meia hora mexendo, e confesso que não entendi como a ferramenta funciona.
Mas para todos os efeitos, acho que amanhã farei algumas alterações. Criarei os métodos setDefaultLoginPage e setDefaultAccessDeniedPage, para facilitar enquanto a ferramenta ainda não estiver integrada ao VRaptor (se isso for rolar mesmo…=S), além de deixar o roles como uma lista de String e anotar o RestrictionChecker com o @Component!

E o nome? Vou alterar os pacotes para br.com.bronx.restrictrex. Alguma objeção? Ou sugestão? Rss

E por favor: TESTEM! Mais de 600 visualizações e só 2 pessoas demonstraram que realmente estão testando…=/

Abs a todos!

S

bronx:
E ae galera!

sobreira, como foram os testes? Funcionou? O que achou? Sugestões?
Alguém mais testou a parada? yorgan?
Dêem suas opiniões!!


Tava mexendo aqui, mas to caindo de sono. Como disse anteriormente gostei muito da solução e até agora está tudo ok. As funcionalidades que você apresentou estão funcionando 100%. Tive apenas um probleminha mas foi por conta da versão do vraptor que estava usando.

Estou ansioso pra pegar o projeto no Github e fazer um fork!

[]s

J

sobreira To No Aguardo !

R

show de bola !!!

eu já estava começando a fazer algo neste sentido http://www.guj.com.br/posts/preList/149082/809422.java#809422

apoio a sugestão do Lucas de fazer a configuração do loginPage e accessDeniedPage uma unica vez.

na prox semana vou retomar meus estudos em vraptor e então podemos trocar idéias

parabéns pela iniciativa.

R

a propósito,

vc já definiu o tipo de licença? Apache, GLP , LGLP, …

posso usar, complementar, alterar ?

B

ricardosoares:
show de bola !!!

eu já estava começando a fazer algo neste sentido http://www.guj.com.br/posts/preList/149082/809422.java#809422

apoio a sugestão do Lucas de fazer a configuração do loginPage e accessDeniedPage uma unica vez.

na prox semana vou retomar meus estudos em vraptor e então podemos trocar idéias

parabéns pela iniciativa.

Excelente, ricardosoares!

Quanto mais pessoas estiverem participando, melhor!

Prometo que hj a noite, mais tardar amanhã cedo, posto nova versão com a centralização das configurações de loginPage e accessDeniedPage.

A idéia do Lucas de anotar os próprios recursos com @LoginPage e @AccessDeniedPage é sensacional! Mas acredito que isso só seria possível se a ferramenta estivesse integrada ao VRaptor.

Quanto a licença: ainda não pensei a respeito.
Essa é a minha primeira contribuição em um projeto open-source, então tenho que dar uma estudada nas licenças disponíveis, suas peculiaridades etc.
Tenho inclusive que conversar com o Lucas sobre isso, pois caso a solução seja integrada a uma versão futura do VRaptor, já assumiria a licença utilizada pelo framework.

Mas velho, a minha ideia é seguir a filosofia burger king: “HAVE IT YOUR WAY”. Rs
Pode alterar o código sem problemas. Conforme a parada andar, podemos ir agregando/melhorando cada vez mais a ferramenta.

Abs.

J

bronx bOA tARDE !

Eu tenho que fazer isso tudo em um futuro sistema, logo vou contribuir… mas concordo quanto mais melhor !

E

Gostei do “VAAS”, rs
Eu tinha feito um mais amador para um sistema, vou testar a sua solução e depois retorno como foi. E vou aproveitar e testa-la numa situação bem especifica em termos de segurança q estou modelando.

Parabéns pela iniciativa
:wink:

L

Não precisa estar integrada ao VRaptor pra isso funcionar…

basta implementar uma interface interna do VRaptor…
( criar a classe:
@ApplicationScoped @Component public class PageHandler implements StereotypeHandler {…})
depois eu te explico melhor como fazer…

L

dá uma olhada nesses artigos:

http://vidageek.net/2009/06/08/como-migrar-de-svn-para-git/
http://vidageek.net/2009/07/06/git-workflow/

B

Nova versão galera!

Me desculpem o atraso de 2 dias, mas aqui está a versão alterada com algumas melhorias propostas pela galera.

O “change log”:

  • classe RestrictionChecker anotada com @Component; //eu não consegui injetá-la :frowning: .
  • criação dos métodos setDefaultLoginPage e setDefaultAccessDeniedPage na classe RestrictionChecker;
  • alteração do nome da annotation @AccessDenied para @OnAccessDenial;
  • restrição do target das annotations: agora é só TYPE e METHOD.
  • criação de exception específica em caso de o desenvolvedor não informar login page ou access denied page em nenhum lugar;
  • atributo “roles” da annotation @Roles agora é uma lista, eliminando a necessidade do antigo “separator” (thanks Leonardo3001);
  • necessidade de implementar apenas uma interface: Profile;
  • adoção temporária do nome “RestricTRex”…ainda estou aguardando as sugestões (rs).

A maneira de utilização é basicamente a mesma.

Com os métodos setDefaultLoginPage e setDefaultAccessDeniedPage não existe mais a obrigação de uso da anotação @OnAccessDenial (antiga @AccessDenied). Mas sua utilização ainda é possível, caso seja necessário um comportamento mais específico em determinadas situações.
Os métodos setDefaultLoginPage e setDefaultAccessDeniedPage devem ser chamados ANTES da chamada ao método checkRestrictions.

A interface Profile agora possui a seguinte “cara”:

public interface Profile {

	public boolean isLoggedIn();
	public List<String> getRoles();
	public int getAccessLevel();
	
}

Olha só o interceptor como pode ficar (façam como quiserem):

package br.com.bronx.interceptor;

import br.com.bronx.restrictrex.exception.DestinationException;
import br.com.bronx.restrictrex.exception.RestrictionAnnotationException;
import br.com.bronx.restrictrex.interfaces.Profile;
import br.com.bronx.restrictrex.restriction.RestrictionChecker;
import br.com.bronx.restrictrex.restriction.RestrictionResult;
import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.view.Results;

/**
 * This interceptor controls the access to the resources, based on their
 * restrictions annotations.<br>
 * The restrictions might be method restrictions or resource restrictions,
 * according to where the annotations had been placed.
 * 
 * @author Diego Maia da Silva a.k.a. Bronx
 */
@Intercepts
public class AccessControllerInterceptor implements Interceptor {

	private RestrictionChecker restrictionChecker;
	private Result result;
	private Profile profile;
	
	public AccessControllerInterceptor(Profile profile, Result result, RestrictionChecker restrictionChecker){
		this.restrictionChecker = restrictionChecker;
		this.profile = profile;
		this.result = result;
	}
	
	@Override
	public boolean accepts(ResourceMethod method) {
		return this.restrictionChecker.hasRestriction(method.getMethod());
	}

	public void intercept(InterceptorStack stack, ResourceMethod resourceMethod,
			Object resourceInstance) throws InterceptionException {
		//this.restrictionChecker.setDefaultLoginPage("minha/pagina/de/login/padrao");
		//this.restrictionChecker.setDefaultAccessDeniedPage("pagina/de/acesso/restrito/padrao");
		RestrictionResult restrictionResult;
		try {
			restrictionResult = this.restrictionChecker.checkRestrictions(resourceMethod.getMethod(), this.profile);
		} catch (RestrictionAnnotationException e) {
			throw new InterceptionException(e);
		} catch (DestinationException e) {
			throw new InterceptionException(e);
		}
		if (restrictionResult.isRestricted()){
			result.use(Results.page()).redirect(restrictionResult.getDestination());
		} else {
			stack.next(resourceMethod, resourceInstance);
		}
	}
}

Enfim…testem aí.

Planos para um futuro [extremamente] próximo: jogar isso tudo no github e implementar o esquema da @LoginPage e @AccessDeniedPage.

Lucas, me mande um tutorial de como fazer esse esquema do StereotypeHandler.

[]'s

EDIÇÃO: esqueci do anexo…damn it…!

L

só criar a classe dentro do seu projeto:

@Component
@ApplicationScoped
public class LoginPageHandler implements StereotypeHandler {

    public LoginPageHandler(RestrictionChecker checker) {
    //guarda num field
    //O RestrictionChecker tem que ser ApplicationScoped (se ele depender de algo do request 
    //não vai rolar, então vc vai ter que criar uma outra classe que tem essas configurações de loginPage)
}
    public Class<? extends Annotation> stereotype() {
         return Resource.class; //  vai funcionar pros Controllers
    }

    public void handle(Class<?> type) {
          if (//algum dos métodos de type está anotado com @LoginPage) {
              this.checker.setDefaultLoginPage(//o metodo anotado);
          }
          // mesma coisa para @AccessDeniedPage
    }
}

essa classe é carregada qdo o VRaptor está se configurando… toda vez que ele achar alguma classe anotada com @Resource, ele vai chamar o método handle(…) passando essa classe

W

Muito boa a contribuição Bronx, parabéns…

apenas uma sugestão, que tal dar mais flexibilidade para as roles, substituindo:

@Roles(roles={"gerente","supervisor"},  policy = RolesPolicy.DISJUNCTION)

por:

@Roles(roles="gerente OU supervisor E ....")
B

Lucas:

[youtube]http://www.youtube.com/watch?v=dsbrRXMdLMc[/youtube]

Muito simples man!
VRaptor surpreendendo cada dia que passa…rs
E como eu faria para redirecionar? Eu teria a classe e o método. Como faria para redirecionar para o método especificado??

wpivotto:

[youtube]http://www.youtube.com/watch?v=DeVmYfiGydo[/youtube]

Hehe! Brincadeiras a parte: cara, isso pode gerar problemas. Além de um trabalho maior para codificar um “parser” para a string, pois a mesma precisaria de agrupamentos (uso de parênteses) e o cacete a 4.
O cara poderia digitar errado, dentre outros possíveis erros…

De qualquer forma, valeu pela sugestão. E por favor, teste! rs

W

ok bronx, faz sentido…

eu consegui redirecionar para o método da seguinte maneira

@Component  
@ApplicationScoped  
public class LoginPageHandler implements StereotypeHandler {  

	private final RestrictionChecker checker;
	private final Router router;
	private static final Logger logger = LoggerFactory.getLogger(LoginPageHandler.class);

	public LoginPageHandler(RestrictionChecker checker, Router router) {  
		this.checker = checker; 
		this.router = router;
	}  

	public Class<? extends Annotation> stereotype() {  
		return Resource.class; 
	}  

	public void handle(Class<?> type) {  

		for(Method method : type.getMethods()){

			String route = router.urlFor(type, method, method.getGenericParameterTypes());

			if(method.isAnnotationPresent(LoginPage.class)) {
				checker.setDefaultLoginPage(route);
				logger.info("DEFAULT LOGIN PAGE -> " + route);
			}

			if(method.isAnnotationPresent(AccessDeniedPage.class)) {
				checker.setDefaultAccessDeniedPage(route);
				logger.info("DEFAULT ACCESS DENIED PAGE -> " + route);
			}
		}
	} 
	
}

O Lucas deve ter uma solução melhor…

Seria legal ter uma anotação LogoutPage também…

L

se vc quiser redirecionar para o método e classe vc faz assim:

Object instance = result.redirectTo(classe);
new Mirror().on(instance).invoke().method(metodo).withoutArgs(); //supondo que não tem argumentos

se vc quiser só a url faz como o wpivotto falou… o único erro dele é o último parâmetro do urlFor… se eu não me engano ele recebe um Object[] que são os argumentos… o ideal seria forçar que o método anotado não receba argumentos, assim é só passar new Object[0] como último argumento

B

Lucas e wpivotto,

Estamos a um passo de fecharmos isso. rs

Mas Lucas, e no caso do método possuir parâmetros?
Você acha melhor forçar que os métodos com @LoginPage e @AccessDeniedPage não possuam parâmetros?

Posso estar enganado, mas acredito que isso acaba tirando um pouco da flexibilidade proposta pela ferramenta, não acha?

Anyway, vou fazer isso tudo até o fds e mando nova versão da parada. Master ocupado para parar e fazer isso agora…=S
Abs.

L

se o método possui parâmetros, o que vc vai passar pra ele? Vc não tem essa informação… passar tudo null não é uma boa, pq o método provavelmente usa as informações

B

Nossa…eu misturei tudo… Tava pensando na injeção dos parâmetros do construtor da classe quando escrevi isso. =S
#groselhadetected
My bad. :oops:

Então fechou!

Logo mais teremos a versão mais elegante do restritor! =DDD

G

bronx:
Opa!
Então garcia-jj, esse esquema é específico para o VRaptor. Vale lembrar que nem todos usuários do VRaptor conhecem ou sabem utilizar o JAAS (eu mesmo nem imagino como funciona…=S). Qualquer Servlet Container possui suporte a JAAS?
Agora fiquei curioso: vc utiliza JAAS com o VRaptor? É simples? Vou dar uma estudada ASAP.

Quanto ao CoC: concordo.
Tanto que estamos justamente elaborando uma solução mais simples para não termos que fazer essas configurações em todas as classes/métodos do sistema. A idéia do loginPage é dar o máximo de flexibilidade ao desenvolvedor. Pode existir uma situação onde, antes de ir para a página de login, ele queira exibir alguma informação ao usuário, por exemplo (??? sei lá rs). Mas de qualquer modo, é essa linha que pretendemos adotar: a menor quantidade de configurações possíveis.

Valeu pela contribuição. Será de grande valia!!

bronx, tudo bem? Desculpe a demora em responder. Eu estava em viagem de trabalho. Mas vamos lá ao que interessa.

Qualquer servlet container suporta JAAS. A grande vantagem dele é ser um padrão, porém não é nada simples. A tua solução de longe é a mais simples. Eu sempre sugiro usar JAAS porque todos os projetos que faço usam EJB, assim ambos conversam transparente entre sí.

E achei a tua contribuição fantástica. O que você acha de disponibilizar o projeto como uma espécie de plugin para o vraptor? Assim é só colocar um jar do tipo vraptor-plugin-do-bronx.jar e ser feliz, hehe.

Abraços

B

Boa tarde garcia-jj!

Hehe…me expressei mal. Queria saber se possuem suporte “nativo”. Sem precisar de JARs extras. rs

Enfim…cara, já está assim! Já está tudo dentro do jar. É baixar, configurar e usar! o//

Mas estamos melhorando. Acho que semana que vem já teremos versão nova por aí. rs

Abs.

G

Sim, a implementação de JAAS fica no container.

S

Amigo boneazul!
Eu gostei muito do teu modelo para controlar o acesso e segurança, porém acredito que ficaria muito melhor se você utilizar o nome do método anotado ao invés de uma Ação numerada, pois assim o desenvolvedor não precisaria se preocupa em saber qual ação deverá ser associada ao método/lógica, mas ficaria bastante elegante se na anotação @VerifyAccess pudesse informar 3 parâmetros, onde:

@VerifyAccess(description=“Relatório gerencial|Esta lógica serve para imprimir o relatório gerencial.”,
pageAccessDenied="/acessoNegado.jsp",
messageAccessDenied=“acesso.negado”
)

Sendo assim:
description= Aqui seria informado uma chave do arquivo i18n (messages.properties) ou um texto contendo a informação sobre a lógica anotada, sendo este apresentado para o administrador do sistema durante a delegação de qual usuário terá ou não acesso
pageAccessDenied= Aqui seria informado uma página para direcionamento,c aso o usuário logado não tenha direitos de acesso.
messageAccessDenied= Aqui seria informado uma chave do arquivo i18n ou um texto contendo a mensagem de negação.

Seria legal também se a classe pudesse receber uma outra anotação, ex: @ResourceControl(description=“Relatórios”), onde seria informado um texto ou chave i18n para facilitar na organização do administrador do sistema, onde as lógicas anotada como segurança ficariam agrupadas dentro dos seus respectivos recurso (classes) e com isso teríamos uma arvore de controle de acesso.

Com isso teríamos o seguinte modelo HTML

Relatórios
|
±–> Relatório gerencial
+…
+…
±–> Relatório administrativo

E o administrador selecionaria os métodos “anotados” e daria o direito de acesso ao usuário, também selecionado…

Dá para ir mais a fundo nestas ideias, o importante é que o teu modelo fica mais flexível, pois o desenvolvedor não precisa saber qual a regra para cada método anotado, isto fica a cardo do administrador.

Abraços.

B

softwork:
Amigo boneazul!
Eu gostei muito do teu modelo para controlar o acesso e segurança, porém acredito que ficaria muito melhor se você utilizar o nome do método anotado ao invés de uma Ação numerada, pois assim o desenvolvedor não precisaria se preocupa em saber qual ação deverá ser associada ao método/lógica, mas ficaria bastante elegante se na anotação @VerifyAccess pudesse informar 3 parâmetros, onde:

@VerifyAccess(description=“Relatório gerencial|Esta lógica serve para imprimir o relatório gerencial.”,
pageAccessDenied="/acessoNegado.jsp",
messageAccessDenied=“acesso.negado”
)

Sendo assim:
description= Aqui seria informado uma chave do arquivo i18n (messages.properties) ou um texto contendo a informação sobre a lógica anotada, sendo este apresentado para o administrador do sistema durante a delegação de qual usuário terá ou não acesso
pageAccessDenied= Aqui seria informado uma página para direcionamento,c aso o usuário logado não tenha direitos de acesso.
messageAccessDenied= Aqui seria informado uma chave do arquivo i18n ou um texto contendo a mensagem de negação.

Seria legal também se a classe pudesse receber uma outra anotação, ex: @ResourceControl(description=“Relatórios”), onde seria informado um texto ou chave i18n para facilitar na organização do administrador do sistema, onde as lógicas anotada como segurança ficariam agrupadas dentro dos seus respectivos recurso (classes) e com isso teríamos uma arvore de controle de acesso.

Com isso teríamos o seguinte modelo HTML

Relatórios
|
±–> Relatório gerencial
+…
+…
±–> Relatório administrativo

E o administrador selecionaria os métodos “anotados” e daria o direito de acesso ao usuário, também selecionado…

Dá para ir mais a fundo nestas ideias, o importante é que o teu modelo fica mais flexível, pois o desenvolvedor não precisa saber qual a regra para cada método anotado, isto fica a cardo do administrador.

Abraços.

É o mais “legal” da ideia tirando a porquisse dos ids é essa flexibilidade mesmo, de tirar da mão do programador o que cada pessoa deve acessar , ao meu ver não tem o porque disso.

Digamos que esse modelo do bronx é role-based e o meu seria um action-based …

a diferenca entre os dois é que o dele é bem mais simples pois não é necessario geração de banco para controle apenas uma list de roles do usuario,porém como nada é perfeito peca na parte de manutenção pois se algum ou varios metodos mudam de perfil teria que ir em código mudar e isso num é legal.

o meu é mais complexo pois ha geração de banco pra controle ,mapeamento de ações do sistema porém o sistema fica totalmente desacoplado do programador pois que define o que o perfil pode fazer é o proprio gerente,administrador,supervisor …

não tive tempo ainda de pensar em algo pra melhorar akeles ids,poderia ser ligado sim a string em vez do id mas ai teria mapeamento do mesmo modo ou seja do mapeamento de ações não teria como fugir

O ideal seria realmente algo do tipo

@VerifyAcess("listaUsuario")
public void lista(){
.........
}

Eu utilizo esse eskema de “Assunto da ação” tipo,isso torna muito mais organizado para quem delega , só não postei pois aumenta 1 classe apenas

–Relatorios
—Imprimir relatorio compra
—Imprimir relatorio venda
–Cadastros
—Lista vendedor
—Editar vendedor
—Desativar vendedor
.
.
.

os outros parametros nem seriam necessarios creio eu, pois geralmente voce num tem muito o que falar apenas : “Acesso negado,voce não tem permissão para executar essa operação” tipo uma frase meio que genérico ja resolveria bem.Nada que um interceptor não resolva.

Vo pensar em algo mais programatico é que estou sem tempo pra fazer algo mais elegante.
Pois estou trabalhando em outra contribuição muito maior pra turma do Vraptor, que garanto o pessoal vai gostar bastante.

S

O trabalho que o bronx esta fazendo é genial e de fato é mais simples, basta apenas no momento de LOGIN carregar a lista de regras/perfis deste usuário, mas o problema é se uma gerente de negócio mudar o escopo de segurança, ou seja, uma lógica que foi anotada para ter acesso somente ao gerente e ao usuário, agora passe a ter também um supervisor, então eu teria que ir no código para fazer isso e em seguida fazer um “deploy” e colocar para teste e só depois se homologado, colocar em produção.
Se este “foco” mudar, o modelo ficará perfeito.

Pois é amigo, apesar do teu código ter a “complexidade” de 2 ou 3 entidades no banco e um trabalho de delegação de acesso por parte de um chefe de setor, gerente ou supervisor é esta a realidade na maioria das empresas, pois o escopo sempre muda, sempre irá existir a dinâmica para cada usuário ou um determinado perfil.
Bom, pelo menos aqui na FAESP “Federação da Agricultura e Pecuária do Estado de São Paulo” e SENAR "Serviço Nacional de Aprendizagem Rural, ambas sem fins lucrativos, sempre há mudanças.

Então boneazul, apesar da necessidade da entidade “ações”, acho que o foco seria um pouco diferente, pois a chave seria o nome do método e para não apresentar algo “estranho” para o administrador de segurança (ex: listaUsuario) seria interessante apresentar um texto “breve” explicativo, algo como: Lista de Usuários, sendo assim a anotação iria buscar no aquivo de properties a mensagem a ser apresentada ao administrador, porém acho que falta um direcionamento para uma página de “acesso negado”, pois se um usuário logado tentar acessar o método anotado e este não tiver direito de acesso, ele deverá ser direcionado para uma mensagem padrão ou uma específica, conforma a necessidade do desenvolvedor.

Mas acho que poderia seguir a linha de convenção do vRaptor, ou seja, no arquivo de properties teríamos a chave: lista.texto = Lista de Usuários (mensagem para o administrador) e para o direcionamento, caso não informado na anotação, seria algo assim: /[classe].[método].negado.jsp

Situação simples:

@VerifyAcess()
public void lista(){
.........
}

Situação específica:

@VerifyAcess(pageAccessDenied="/acessoNegado.jsp")
public void lista(){
.........
}

ou

@VerifyAcess(description="listaDeUsuarios.texto", pageAccessDenied="/acessoNegado.jsp")
public void lista(){
.........
}

Acho de dá para pensar ainda mais sobre o assunto.

Bom, parabéns para o bronx e ao boneazul pela iniciativa e principalmente pela contribuição para a comunidade.

Muito obrigado aos dois.

G

Sem dúvidas é uma excelente contribuição. Tenho acompanhado o tópico, mesmo sem opiniar muito, e posso dizer que é uma excelente contribuição. Certamente facilita muito o uso, porém o diferencial é a integração transparente ao vraptor, já que soluções como jaas e acegy tem de serem feitas na mão.

Abraços, e obrigado por compartilharem.

B

softwork:
boneazul:

a diferenca entre os dois é que o dele é bem mais simples pois não é necessario geração de banco para controle apenas uma list de roles do usuario,porém como nada é perfeito peca na parte de manutenção pois se algum ou varios metodos mudam de perfil teria que ir em código mudar e isso num é legal.

O trabalho que o bronx esta fazendo é genial e de fato é mais simples, basta apenas no momento de LOGIN carregar a lista de regras/perfis deste usuário, mas o problema é se uma gerente de negócio mudar o escopo de segurança, ou seja, uma lógica que foi anotada para ter acesso somente ao gerente e ao usuário, agora passe a ter também um supervisor, então eu teria que ir no código para fazer isso e em seguida fazer um “deploy” e colocar para teste e só depois se homologado, colocar em produção.
Se este “foco” mudar, o modelo ficará perfeito.

Pois é amigo, apesar do teu código ter a “complexidade” de 2 ou 3 entidades no banco e um trabalho de delegação de acesso por parte de um chefe de setor, gerente ou supervisor é esta a realidade na maioria das empresas, pois o escopo sempre muda, sempre irá existir a dinâmica para cada usuário ou um determinado perfil.
Bom, pelo menos aqui na FAESP “Federação da Agricultura e Pecuária do Estado de São Paulo” e SENAR "Serviço Nacional de Aprendizagem Rural, ambas sem fins lucrativos, sempre há mudanças.

Então boneazul, apesar da necessidade da entidade “ações”, acho que o foco seria um pouco diferente, pois a chave seria o nome do método e para não apresentar algo “estranho” para o administrador de segurança (ex: listaUsuario) seria interessante apresentar um texto “breve” explicativo, algo como: Lista de Usuários, sendo assim a anotação iria buscar no aquivo de properties a mensagem a ser apresentada ao administrador, porém acho que falta um direcionamento para uma página de “acesso negado”, pois se um usuário logado tentar acessar o método anotado e este não tiver direito de acesso, ele deverá ser direcionado para uma mensagem padrão ou uma específica, conforma a necessidade do desenvolvedor.

Mas acho que poderia seguir a linha de convenção do vRaptor, ou seja, no arquivo de properties teríamos a chave: lista.texto = Lista de Usuários (mensagem para o administrador) e para o direcionamento, caso não informado na anotação, seria algo assim: /[classe].[método].negado.jsp

Situação simples:

@VerifyAcess()
public void lista(){
.........
}

Situação específica:

@VerifyAcess(pageAccessDenied="/acessoNegado.jsp")
public void lista(){
.........
}

ou

@VerifyAcess(description="listaDeUsuarios.texto", pageAccessDenied="/acessoNegado.jsp")
public void lista(){
.........
}

Acho de dá para pensar ainda mais sobre o assunto.

Bom, parabéns para o bronx e ao boneazul pela iniciativa e principalmente pela contribuição para a comunidade.

Muito obrigado aos dois.

“e um trabalho de delegação de acesso por parte de um chefe de setor, gerente ou supervisor é esta a realidade na maioria das empresas, pois o escopo sempre muda, sempre irá existir a dinâmica para cada usuário ou um determinado perfil.”

É realmente ,por exemplo para a minha empresa, modelo de ROLES não rola e por isso nem é adotado.
Se voce ta falando que na sua tem 2 já somos 3 que esse tipo de implementação fica inviavel.
Pois isso postei a alternativa.

então talvez voce não tenha entendido bem o meu modelo cara,pelas sugestões que está me passando

Vo tentar ser simples na explicação do interior da parada.

No geral vai ser 4 tabelas
perfil,acesso,acoes,categoriaacoes


Tabela categoriaacoes :

Guarda as categorias de ações pra ficar mais organizado na interface do usuario ,que foi o que voce dissse uns posts atras

-Relatórios Gerencias
-Relatórios Administrativos
.
.

Tabela ações

Guarda todas as ações mapeadas no seu sistema e tem uma categoria listada acima

  • imprimir relatorio A - Relatórios Gerencias
  • imprimir relatorio B - Relatórios Gerencias
  • imprimir relatorio A - Relatórios Administrativos
  • imprimir relatorio B - Relatórios Administrativos

Nessa tabela o que poderia ser feito é passado a convenção ai ficaria legal

tipo a classe de acao seria

Id | Descrição da ação | Categoria da acao | Convenção que segue

1 | imprimir relatorio A | 1 | /vendedor/lista

dai dai pra fazer algo do tipo que voce necessita

Ai daria pra ver …

O método de acesso tem anotação??
Se tem anotação ,eu busco o usuario na sessao pego seu perfil pego as ações ligada ao perfil e procuro a convenção ,se ela não existe então negaria o acesso ao recurso caso exista deixaria acessar.
Quanto as outras configurações ficaria facil.

Algumas ate desnecessario exemplo a i18n com a key como voce sugerir sendo ja que voce so poderia passar a logica a executar
isso no final iria renderizar um jsp ai no jsp voce usaria a i18n com tag lib <c ou <fmt num lembro

quanto ao seu pageAccessDenied="/acessoNegado.jsp" nao sei se seria necessario pois ai seria generalização demais sendo que todas vez ele seguiria isso ficaria meio estranho de ver poderia deixar alguma pagina generica e caso ele passasse alguma lógica ai executaria a lógica ,não é o meu caso pois como disse eu sempre uso uma frase genérica “Voce não tem direito de acesso a esse recurso” pois seria até improdutivo fazer um jsp pra cada logica negada so pra mudar algumas palavras tipo
"Voce não tem permissao para ‘key’"

Pois há outros lados tamem , eu não mostro nada pra clicar se o cara ja nao tem acesso …

Exemplo… não se mostra uma aba que o cara num pode acessar,não se mostra um link de inserir se ele não insere o sistema TEM que se modelar ao perfil ou seja some ou aparece com as coisas isso pensando na view e se ele ta tentando acessar algo que não deve com certeza está forçando na url no meu caso. Tanto é que eu sempre guardo o usuario engraçadinho pra saber que ta tentando acessar por url direto e se precisar notificar.
Já aconteceu caso.Os caras da minha empresa são bem chato sem relação a autenticação e auditoria nesse sentido.
Pois minhas classes já são adaptadas pra auditoria também tipo desde o que o cara loga ate sair eu sei o que ele fez.Acontecia muito de usuario dizer.

“Sumiu aqui.não fui eu quem apagou” ai eu " apagou sim , apagou dia … hora minuto em segundo que ele fez" , antigamente ficava a responsabilidade pra gente.É aquele negócio cada projeto tem suas necessidades.Eu sempre preciso garantir certas coisas que são boas práticas.Essa são exemplos reais que sempre enfrentei.

vo dar uma pensada em algo simples pra ficar nesse modo com algumas customizações…

@VerifyAcess()
public void lista(){

}

Abraços a todos.

B

Alias bronx onde posso baixar seu jar?? Não achei um link pra dar uma olhada e brincar um pouco nele.

G

Eu estava passeando por aqui, e ressuscitando o tópico… o projeto do Bronx ficou muito bom. Lucas, não dá para criar lá no site do vraptor uma espécie de “área de plugins de fãs do vraptor” e disponibilizar esses pequenos projetos? Achei que se o peão procurar aqui nos tópicos fica complicado achar as informações corretas entre 5 páginas com posts bem estensos.

Pensei em uma página onde tenha uma lista dessas coisas, e talvez os docs e link para download.

Abraços

J

garcia-jj Eu fiz isso com a Loja Virtual do VRAptor 2

Acho que o Paulo deve Fazer isso !

jr

G

juniorsatanas:
garcia-jj Eu fiz isso com a Loja Virtual do VRAptor 2

Acho que o Paulo deve Fazer isso !

jr

Na verdade a tua idéia com a loja era criar um site demo do projeto.

Já a minha é de disponibilizar uma página no site do vraptor com uma lista dos projetos como esse do Bronx para que o pessoal possa ler sobre e baixar o projeto. Mas não um live demo.

Abraços

L

posso ver de colocar isso no site sim! vou marcar como TODO aqui e fazer assim que possível =)

N

Muito interessante, porém para entender como usar na thread fica meio complicado.

Bronx porque não monta um tutorial explicando detalhadamente?

parabéns

abraços

B

Srs., vortei!

Só agora tive tempo para parar e mexer novamente nisso.
Fiz quase todas as alterações sugeridas pela galera. Só falta implementar o esquema de forçar 403 qnd necessário (útil para chamadas ajax).

Enfim, o que pega é que estou desde ontem tentando testar o que fiz, e não estou conseguindo pq quando empacoto tudo num jar, o VRaptor não encontra os componentes que estão dentro dele (lança uma “org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name […]”).

Alguém aí já passou por isso?

Já tentei marcando e desmarcando o “Add directory entries”, tentei colocar tudo dentro do próprio VRaptor, e nada…¬¬

O trace completo:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accessControllerInterceptor' defined in file [C:\Users\Bronx\apache-tomcat-6.0.20\wtpwebapps\controle-acesso\WEB-INF\classes\br\com\bronx\interceptor\AccessControllerInterceptor.class]: Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.bronx.vraptor.restrictrex.restriction.RestrictionChecker]: : No matching bean of type [br.com.bronx.vraptor.restrictrex.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.vraptor.restrictrex.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:698)
	org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:328)
	org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:385)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:375)
	org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1069)
	org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:221)
	br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:240)
	br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:58)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:32)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:1)
	com.google.common.collect.Lists$TransformingRandomAccessList.get(Lists.java:431)
	java.util.AbstractList$Itr.next(Unknown Source)
	com.google.common.collect.Iterators$7.computeNext(Iterators.java:602)
	com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:135)
	com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:130)
	com.google.common.collect.Lists.newArrayList(Lists.java:131)
	com.google.common.collect.Collections2$FilteredCollection.toArray(Collections2.java:219)
	br.com.caelum.vraptor.interceptor.DefaultInterceptorRegistry.interceptorsFor(DefaultInterceptorRegistry.java:50)
	br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:42)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)

root cause

org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.vraptor.restrictrex.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:896)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:765)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:680)
	org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:771)
	org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:691)
	org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:328)
	org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:385)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:375)
	org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1069)
	org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:221)
	br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:240)
	br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:58)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:32)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:1)
	com.google.common.collect.Lists$TransformingRandomAccessList.get(Lists.java:431)
	java.util.AbstractList$Itr.next(Unknown Source)
	com.google.common.collect.Iterators$7.computeNext(Iterators.java:602)
	com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:135)
	com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:130)
	com.google.common.collect.Lists.newArrayList(Lists.java:131)
	com.google.common.collect.Collections2$FilteredCollection.toArray(Collections2.java:219)
	br.com.caelum.vraptor.interceptor.DefaultInterceptorRegistry.interceptorsFor(DefaultInterceptorRegistry.java:50)
	br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:42)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)

Enfim, se puderem ajudar, agradeço.

Já pensei umas 4 vezes em tacar o note na parede de tão puto que fiquei…kkkk

Mas é isso…

Ahhh… Para os que estavam comentando sobre as falhas do meu Roles: dá pra fazer diferente (do jeito que vocês querem - e é melhor), usando as coisas do jeito que estão! Basta abstrair as Roles que vc utiliza na annotation, e criar perfis mais “dinâmicos” que possuam tais roles.

Assim que tiver a implementação toda fechada farei um tutorial sobre tudo isso.

Fechando: por favor, me ajudem! hehehe

Abs a todos!

L

vc lembrou de colocar

&lt;context-param&gt; &lt;param-name&gt;br.com.caelum.vraptor.packages&lt;/param-name&gt; &lt;param-value&gt;br.com.bronx.vraptor.restrictrex&lt;/param-value&gt; &lt;/context-param&gt;

no seu web.xml ???

pra arquivos dentro de jars isso é necessário

B

Então Lavieri,

Eu fiz isso sim, porém só utilizei o prefixo br.com.bronx.

Vou tentar com o caminho mais específico.

Mas como disse, não consegui injetar nem classes que criei dentro do próprio VRaptor…=/

De qualquer forma, vou testar aqui e já digo se rolou ou não.

B

Lavieri, era isso mesmo.

Acho que das outras vezes que usei o param “packages”, eu não tinha adicionado as entradas dos diretórios ao JAR!

Mas enfim, tá aí! Em mãos!

Novamente, o “changelog”:

  • Agora basta usar as annotations @LoginPage e @AccessDeniedPage para informar os caminhos de redirecionamento, em caso de acesso negado.
    Os métodos antigos continuam válidos (RestrictionChecker.setDefaultLogin/AccessDeniedPage e a annotation @OnAccessDenial), para situações mais específicas;
  • Em caso de acesso negado por motivo de o usuário não possuir as credenciais necessárias (Roles ou Access Level suficientes), e nenhuma AccessDeniedPage for informada, nenhuma exception é lançada e o retorno é o HTTP 403 que a galera pediu (ótima sugestão);
  • Para forçar o “forbidden” (HTTP 403), faça o seguinte:
@OnAccessDenial(forceHttp403 = true)
public void meuMetodo(...){}

Com isso, mesmo tendo sido especificado um caminho para redirecionamento em caso de acesso negado, o servidor manda um 403 para o cliente.

Vale ressaltar que só pode haver um método anotado com @LoginPage ou @AccessDeniedPage (pode ser o mesmo método), e que o método não deve receber nenhum parâmetro.

Bom, acho que essa versão contempla 97% das sugestões que foram surgindo.
No mais, não fiz o @LogoutPage pois acho que isso deve ficar a cargo da lógica do cara (método de logout da aplicação), bastanto um simples redirecionamento via result.

Deixei o interceptor fora do pacote para que possam alterar da maneira que desejarem.
Na minha aplicação teste, criei um componente de sessão que guarda informações do usuário (UsuarioCorrente). Não precisam deixar assim, a única obrigatoriedade é passar um método e um Profile para o método checkRestrictions da classe RestrictionsChecker.

Por favor, peço novamente que testem. Confesso que foi a versão que menos testei, então ainda pode estar longe de ser “defect free”…rs

Assim que possível farei um manual detalhado, pois muita gente tem caído de paraquedas aqui, e seria uma boa para “consolidar” a documentação de tudo que foi feito.

Seguem os arquivos.

TESTEM! rs

Abs.

L
bronx:
Vale ressaltar que só pode haver um método anotado com @LoginPage ou @AccessDeniedPage (pode ser o mesmo método), e que o método não deve receber nenhum parâmetro.

Bronx, acho que vc poderia retirar essa restrição, de os métodos não terem parametros, da pra redirecionar com parametros sem problemas, eu tenho um projeto muito parecido com o seu, que também disponibilizei o código, vou linkar aqui o SRC de como redireciono paras lógicas, e mesmo elas tendo parametros....

isso é especialmente útil para uma página de login
@LoginPage
public void login(String login, String senha) {

}

claro que esse lógica deve esperar login e senha nulos, no caso de quando é o seu sistema que fizer redirect....

com este objeto abaixo vc consegue criar rotas mesmo com parametros, e para redirecionar, para usar é simples.

http://code.google.com/p/access4vraptor/source/browse/trunk/src/main/java/br/com/simtecnologia/acesso/controle/DefaultLogicRoute.java

new DefaultLogicRoute(resourceMethod).redirectTo(result);

este classe aceita também no construtor MethodInfo, e diretamente a classe e metodo da lógica

B

Lavieri,

Eu tinha visto o que vc fez! Parabés pelo trabalho.
Aliás, pelos trabalhos. Vi que não foi a única contribuição que fez. Achei legal que algumas que você fez eu tbm fiz aqui. Acho que estamos trabalhando num sistema semelhante, pois estamos tendo os mesmos problemas. Hehehe

Quanto a página de login:

É que estamos tendo abordagens diferentes quanto aos métodos do controller.

Você utiliza o mesmo método para carregar a página de login e para de fato efetuar o login.

Eu separo essas funções em métodos distintos. Acho que isso deixa as coisas mais organizadas, além daquela questão de dividir as responsabilidades dos métodos. Saca só:

@LoginPage
public void login() {

}

É um método que não faz nada, pois foi criado única e exclusivamente para mostrar a página de login.

Para não dizer que não faz nada, dá pra colocar uma lógica para não deixar um usuário já logado ir novamente para a página de login:

@LoginPage
public void login() {
    if (isAlreadyLoggedIn())
        this.result.redirectTo(MeuController.class).metodoQualquer();
}

Na minha login.jsp, eu faria algo do tipo:

(...)
<form name="loginForm" method="post" action="<c:url value='/efetuar/login'/>">

    Usuário:
    <input type="text" name="usuario.nome" /><br/>
    Usuário:
    <input type="password" name="usuario.senha" /><br/>
    <input type="submit" />

</form>
(...)

Como pode ver, a action do form aponta para outro método, que é o que vai realizar de fato o login:

@Path("/efetuar/login")
public void efetuarLogin(Usuario usuario) {
    //lógica de login
}

Enfim…

Eu estava considerando deixar utilizar parâmetros, mas acabei não enxergando a real necessidade disso…

Mas por favor, teste aí e me diga o que acha.

E obrigado pela sugestão! :thumbup:

L

Entendo o que quer dizer, e quanto a separação de responsabilidades ^^ …

eu não custumo a colocar @Get e @Post na mesma lógica, porem minha intenção é de não restringir e dar a possibilidade de usar… o metodo de login no meu projeto e o que mostrei aqui, são apenas exemplos simplorios de como pode ser efetuado um login… eu faço alguma presuposições, inclusive a de que quem acessar a pagina de login, quer se logar, e se alguem logado a acessa, então é melhor que abra a pagina de login, e que deiche ele tentar logar.

outra coisa é que login é uma lógica vazia, que só exibe o form, e efetualogin é uma lógica que tenta logar, e se não consegue também exibe o form, então da pra ter uma lógica login, que posta pra ela mesma sem muitos problemas.

além de quer, presuposições são sempre ruim, quando se faz algo generico, como não é possivel checar em tempo de compilação o que o cara anota com @LoginPage, é melhor não lançar uma exceção na cara dele em tempo de execução…

A

Parabéns pelo projeto Bronx.
Estou tentando utilizá-lo no meu projeto, poderiam me ajudar?

Tenho as seguintes classes

//modifiquei o nome da classe Usuario que tu passou, para UsuarioProfile, para fins de estudo
public class UsuarioProfile implements Profile{
	
	private int accessLevel;
	private List<String> roles;
	
	public int getAccessLevel() {
		/*Poderia buscar o nível de acesso no 
		 * banco de dados, por exemplo.
		 */
		this.accessLevel = 1;//para fins de teste, no futuro pegarei do banco
		return this.accessLevel;
	}
	
	public List<String> getRoles() {
		/*Poderia buscar os papéis deste usuário  
		 * no banco de dados, por exemplo.
		 */
		this.roles.add("jogador");//para fins de teste, no futuro pegarei do banco
		return this.roles;
	}

	public boolean isLoggedIn() {
		// TODO Auto-generated method stub
		return false;
	}

Meu Usuario(Bean), criado pelo Hibernate, está assim

@Entity
@Table(name = "usuario", catalog = "bolao")
public class Usuario implements java.io.Serializable {

	private Profile profile;
	private int id;
	private String nome;
	private String login;
	private String senha;
	private String email;
	private String telefone;
	private String ip;
	private Set<Jogador> jogadors = new HashSet<Jogador>(0);

//....

//isso aqui está certo? É assim que devo fazer?
public void setPerfil(Profile profile){
		this.profile = profile;
	}
	
	public Profile getPerfil(){
		return this.profile;
	}

Adaptei seu interceptor, da seguinte forma

//esse Usuario que estou passando aqui, é meu Usuario(Bean), que referencia o BD de acordo com as regras do Hibernate
public AccessControllerInterceptor(Usuario usuarioCorrente, RestrictionChecker restrictionChecker,
							Result result){
                //aqui, seu usuario corrente é um Bean, correto? Logo tenho que passar meu Bean certo?

		this.result = result;
		this.restrictionChecker = restrictionChecker;
		this.usuarioCorrente = usuarioCorrente;
	}

DEntro do Interceptor acima, devo fazer assim?

restrictionResult = this.restrictionChecker.checkRestrictions(resourceMethod.getMethod(), this.usuarioCorrente.getPerfil());

A Interface Login está assim

public interface Login {
	public boolean isLoggedIn();
	public void setLoggedIn(boolean loggedIn);
	public Profile getProfile();
	public void setProfile(Profile profile);
}

E meu LoginController está assim

import br.com.bolao.accessControl.LoginControl;
import br.com.bolao.bean.Usuario;
import br.com.bolao.dao.UsuarioDao;
import br.com.bronx.vraptor.restrictrex.annotation.AccessDeniedPage;
import br.com.bronx.vraptor.restrictrex.annotation.LoginPage;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;

@Resource
public class LoginController {
	
	private LoginControl loginControl;
	private Result result;
	private UsuarioDao daoUsuario;

	public LoginController(LoginControl loginControl, Result result,
			UsuarioDao daoUsuario) {
		this.loginControl = loginControl;
		this.result = result;
		this.daoUsuario = daoUsuario;
	}

	@LoginPage
    public void login() {}

    @AccessDeniedPage
    public void accessDenied() {}
    
    public void logar(String login, String senha){
        //busco no banco login e senha, caso encontre, é montado o objeto Usuario, que possui atributos ID, NOME, TELEFONE, EMAIL eeee PERFIL, estou fazendo certo?
    	Usuario user = daoUsuario.login(login, senha);
    	if (user != null){
    		loginControl.setLoggedIn(true);
    		loginControl.setProfile(user.getPerfil());
    	}
    }
}

Galera, como podem ver, ainda sou newbie em VRaptor, e estou tentando adaptar sua contribuição ao meu projeto. Ainda não está claro algumas coisas para mim, como por exemplo o método que está dentro do Usuario(aquele que implementa Profile)

public boolean isLoggedIn() {
		// TODO Auto-generated method stub
		return false;//quando vou retornar true, e como fazer isso?
	}

Garanto que minhas perguntas podem parecer bobas, mas preciso de um auxílio de como andar com esse projeto.
Como fazer o checkRestriction? Onde? Quando?

Obrigado desde já aos que me ajudarem, boa noite, e Feliz Páscoa

L

Não vou conseguir te ajudar muito nesse projeto aki, mas vamos la…

a classe UsuarioProfile, vc deve implementar ela mais ou meno assim:

//modifiquei o nome da classe Usuario que tu passou, para UsuarioProfile, para fins de estudo
public class UsuarioProfile implements Profile{
	
	private int accessLevel;
	private List<String> roles;

	private Usuario usuario;

	public void login(Usuario usuario) {
		this.usuario = usuario;
	}
	
	public int getAccessLevel() {
		this.accessLevel = 1;//para fins de teste, no futuro pegarei do banco

		//o ideal é fazer this.accessLevel = (usuario == null) ? -1 :  usuario.getAccessLevel();
		//ou seja... se usuario não existir seta o nivel = -1

		return this.accessLevel;
	}
	
	public List<String> getRoles() {
		this.roles.add("jogador");//para fins de teste, no futuro pegarei do banco

		//o ideal é fazer return (usuario == null) ? Collections.emptyList() : usuario.getRoles();
		//se não tem usuario, retorna uma lista vazia, caso contrario retorna a lista de roles do usuario.

		return this.roles;
	}

	public boolean isLoggedIn() {
		return usuario != null;
	}

 	public void logout() {usuario = null;}

isso resolve algum de seus problemas, espero ter ajudado

G

Olá pessoal!
Estou testando o controlador de login do Diego, mas surgiu um probleminha aqui nesta linha:

restrictionResult = this.restrictionChecker.checkRestrictions(resourceMethod.getMethod(), this.usuarioLogado.getUsuario());

É nessa linha que ele verifica se o usuário está logado ou não?

Estas são as opções que ele me dá:

Estou usando a classe UsuarioLogado e LoginController que estão na apostila da Caelum.

<Editado: Agora que reparei que lá na primeira página do tópico o Diego postou as classes para usar com a interface Profile que já está no pacote =/ >

Vou ter q adaptar as classes pra usar daquela forma.

Abraço!

obs: poderiam criar uma seção desses plugins pro VRaptor no site do VRaptor, pq tô que nem barata tonta caçando as dicas pelas páginas. =)

L

Guevara:

obs: poderiam criar uma seção desses plugins pro VRaptor no site do VRaptor, pq tô que nem barata tonta caçando as dicas pelas páginas. =)

já tem uma issue lá no github pra fazer isso:

provavelmente da próxima vez que a gente atualizar esse site vai ter uma seção disso =)

G

Legal Lucas!! Isso vai ser muito bom! =)
Seria ótimo se tivesse tutoriais no estilo das apostilas da Caelum, mostrando os códigos e dando exemplos de implementação.

Ainda estou ralando aqui nas classes, tô tentando adaptar o que eu tinha mas não estou conseguindo.

Eu tinha usuarioLogado e LoginController funcionando normalmente, agora pra usar esse método de controle tive q deletar os dois e criar uma Interface Login, o Interceptor AccessControllerInterceptor e a classe LoginControl implementando a classe Login, até ai beleza.
De quem o restrictionChecker obtém se o usuário está logado ou não? É do LoginControl? E como o LoginControl obtém o role do usuário?

Minha classe usuário está assim:

@Entity
public class Usuario {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name="id_usuario")
	private Long idUsuario;	
	private String login;
	private String senha;
	private String nome;
	private String role;
        //getters e setters

Criei o atributo role pra gravar no banco se é admin, vendedor ou qualquer outra coisa.

Agora não sei onde implemento de fato o login, logout, busca pelo login e senha como era nas classes usuarioLogado e LoginController. Me perdi. =/

Abraço!

B

Fala brother. Jóia?

Cara, a última versão do controle de acesso que fiz só possui a interface Profile. Tá bem mais fácil implementar as coisas. Acho que na 5ª página do tópico eu expliquei como utilizar a nova versão.

Estou meio sem tempo para escrever um tutorial da nova versão, mas vamos lá:

O método checkRestrictions recebe um método e um Profile. Ele verifica se o Profile passado como parâmetro possui permissão para acessar aquele método.

Como funciona: o cara faz o login normalmente (vc nao precisava ter mudado isso no seu código). De alguma forma (via cookie ou sessão do browser), vc sabe qual é o usuário logado. A ideia é gerar um Profile baseado nesse usuário.

Aí vc segue seu coração.

Você pode fazer de N maneiras. Uma possibilidade seria:

Primeiro, vc cria um componente que fica na sessão. Esse componente armazenará o usuário logado enquanto a sessão estiver ativa, ou até que o usuário saia do sistema (logout):

/*
 * Componente que fica na sessão do servidor, 
 * armazenando o usuário logado.
 */

@Component
@SessionScoped
public class UsuarioCorrente {
	
	private Usuario usuarioCorrente;

	public void setUsuarioCorrente(Usuario usuarioCorrente) {
		this.usuarioCorrente = usuarioCorrente;
	}

	public Usuario getUsuarioCorrente() {
		return this.usuarioCorrente;
	}
	
	public Perfil getPerfil() {
		Perfil perfil = new Perfil();
		if (this.usuarioCorrente != null) {
			perfil.setLoggedIn(true);//como o usuário corrente não é nulo, significa que ele está logado
			//o nível de acesso vc obtém de onde quiser (banco de dados, arquivo properties etc)
			//caso não utilize níveis de acesso no seu controle de acessos, não precisa informar o accessLevel
			//perfil.setAccessLevel(0);
			//Especificamente no seu caso, cada usuário possui apenas um role. Então, faça simplesmente isso:
			List<String> roles = new ArrayList<String>();
			roles.add(this.usuarioCorrente.getRole());
			perfil.setRoles(roles);
		}
		return perfil;
	}

}

Na hora de logar (no método de login do seu LoginController) vc pode fazer o seguinte:

@Resource
public class LoginController {
	
	private Result result;
	private UsuarioCorrente usuarioCorrente;
	private Validator validator;

	public LoginController(Result result, UsuarioCorrente usuarioCorrente,
						Validator validator) {
		this.result = result;
		this.usuarioCorrente = usuarioCorrente;
		this.validator = validator;
	}
	
	@LoginPage//essa anotação indica que essa é a página de login
	public void login() {
		if (this.usuarioCorrente.getPerfil().isLoggedIn())//caso o usuário já esteja logado, redirecione-o para a página principal
			this.result.redirectTo(MeuController.class).principal();
	}

	public void logar(Usuario usuario) {
		/*
		 * Busca o usuario no banco de dados.
		 */
		if (/*usuário não encontrado - senha ou nome de usuário inválidos errada  */) {
			/*volta para a página de login com a mensagem de erro.*/
			this.validator.add(new ValidationMessage("Usuário/Senha inválidos", "login.fail"));
			this.validator.onErrorUse(Results.logic()).redirectTo(LoginController.class).login();
		} else /*usuário encontrado*/{
			this.usuarioCorrente.setUsuarioCorrente(usuario);//guardo o usuário na sessão
			this.result.redirectTo(MeuController.class).principal();//redireciono para a página principal
		}
	}

	public void logout() {
		/*na hora de sair, ele "apaga" o usuário logado (atribui "null" a ele)*/
		this.usuarioCorrente.setUsuarioCorrente(null);
		this.result.redirectTo(LoginController.class).login();//redireciona para a página de login
	}

}

Na classe UsuarioCorrente, eu criei um método getPerfil(). Perfil é uma classe que implementa a interface Profile. Saca só:

public class Perfil implements Profile {

	private int accessLevel;
	private List<String> roles = new ArrayList<String>();
	private boolean loggedIn;
	
	@Override
	public int getAccessLevel() {
		return this.accessLevel;
	}
	
	public void setAccessLevel(int accessLevel) {
		this.accessLevel = accessLevel;
	}

	@Override
	public List<String> getRoles() {
		return this.roles;
	}

	public void setRoles(List<String> roles) {
		this.roles = roles;
	}

	@Override
	public boolean isLoggedIn() {
		return this.loggedIn;
	}

	public void setLoggedIn(boolean loggedIn) {
		this.loggedIn = loggedIn;
	}


}

Os métodos anotados com @Override são as implementações da interface Profile. Os demais eu criei para facilitar.

No interceptor, faça:

/**
 * This interceptor controls the access to the resources, based on their
 * restrictions annotations.<br>
 * The restrictions might be method restrictions or resource restrictions,
 * according to where the annotations had been placed.
 * 
 * @author Diego Maia da Silva a.k.a. Bronx
 */
@Intercepts
public class AccessControllerInterceptor implements Interceptor {

	private RestrictionChecker restrictionChecker;
	private Result result;
	private UsuarioCorrente usuarioCorrente;
	
	public AccessControllerInterceptor(UsuarioCorrente usuarioCorrente, RestrictionChecker restrictionChecker,
							Result result){
		this.result = result;
		this.restrictionChecker = restrictionChecker;
		this.usuarioCorrente = usuarioCorrente;
	}
	
	@Override
	public boolean accepts(ResourceMethod method) {
		return this.restrictionChecker.hasRestriction(method.getMethod());
	}

	
	public void intercept(InterceptorStack stack, ResourceMethod resourceMethod,
			Object resourceInstance) throws InterceptionException {
		RestrictionResult restrictionResult;
		/*
		this.restrictionChecker.setDefaultAccessDeniedPage("/access/denied/page");
		Não precisa mais utilizar esses métodos, mas se quiser, vc pode continuar utilizando-os. 
		Ao invés disso, utilize as annotations @LoginPage e @AccessDeniedPage.
		this.restrictionChecker.setDefaultLoginPage("/login/page");
		*/
		try {
			restrictionResult = this.restrictionChecker.checkRestrictions(resourceMethod.getMethod(), this.usuarioCorrente.getPerfil());
		} catch (RestrictionAnnotationException exception) {
			throw new InterceptionException(exception);
		} catch (DestinationException exception) {
			throw new InterceptionException(exception);
		}
		if (restrictionResult.isRestricted()){
			if (restrictionResult.isHttp403()) {
				this.result.use(Results.http()).sendError(403);
			} else {
				this.result.use(Results.page()).redirect(restrictionResult.getDestination());
			}
		} else {
			stack.next(resourceMethod, resourceInstance);
		}
	}
}

Detalhe para essa linha:

restrictionResult = this.restrictionChecker.checkRestrictions(resourceMethod.getMethod(), this.usuarioCorrente.getPerfil());

Nela o método checkRestrictions recebe o método e o Profile que usará na validação. No caso, o profile que ele recebe é uma instância da classe Perfil, gerada com os dados do usuário logado.

Teste ae…escrevi bem rápido, mas acho que dá pra entender.
Se possível, leia os posts da página 5.

Mas cara, não se esqueça que vc pode implementar sua solução da maneira que quiser. Essa que eu postei é uma bem trivial, então fica a cargo do desenvolvedor julgar a melhor maneira de implementar a parada.

Enfim, qualquer coisa, continue gritando.

Abs.

G

Fala Bronx!
Obrigado pela ajuda! Acho que está td certo, parece que ficou faltando apenas liberar o IndexController lá no Accepts, dá uma olhada:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.vraptor.restrictrex.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:896)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:765)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:680)
	org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:771)
	org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:691)
	org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:328)
	org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:385)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:375)
	org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1069)
	org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:221)
	br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:240)
	br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:58)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:32)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:30)
	com.google.common.collect.Lists$TransformingRandomAccessList.get(Lists.java:431)
	java.util.AbstractList$Itr.next(AbstractList.java:345)
	com.google.common.collect.Iterators$7.computeNext(Iterators.java:602)
	com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:135)
	com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:130)
	com.google.common.collect.Lists.newArrayList(Lists.java:131)
	com.google.common.collect.Collections2$FilteredCollection.toArray(Collections2.java:219)
	br.com.caelum.vraptor.interceptor.DefaultInterceptorRegistry.interceptorsFor(DefaultInterceptorRegistry.java:50)
	br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:42)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)

Na apostila da Caelum o Accepts ficaria assim:

public boolean accepts(ResourceMethod method) {
	    ResourceClass resource = method.getResource();
	    return !IndexController.class.isAssignableFrom(resource.getType());	
	}

No seu Accepts está assim:

public boolean accepts(ResourceMethod method) {
		return this.restrictionChecker.hasRestriction(method.getMethod());
	}

A saida de erro seria referente a isso ou é outra coisa?
Outra coisa, a classe Perfil, fica sem anotação?

Abraço!

B

Os métodos da @LoginPage e da @AccessDeniedPage não podem (obviamente), ter restrições.

Você baixou a última versão? Tá lá na 5ª página…

O accepts é utilizado para decidir se o interceptor vai ou não interceptar a chamada de um determinado método. Acho que não seja a causa do problema.

Não se esqueça de colocar o context parameter no seu web.xml, para que os componentes do jar possam ser injetados na tua aplicação:

<context-param>
		<param-name>br.com.caelum.vraptor.packages</param-name>
		<param-value>br.com.bronx.vraptor.restrictrex</param-value>
	</context-param>

Teste aí e me diga o que rola.

G

Opa! Agora a aplicação respondeu, tava faltando a parte do web.xml.
Estou usando a versão 1.0.2 do restrictrex;
Tá dando erro 404 e mais esta saida do console:

SEVERE: Exception starting filter vraptor
br.com.bronx.vraptor.restrictrex.exception.PageException: Access denied page method cannot have parameters.
	at br.com.bronx.vraptor.restrictrex.startup.PageChecker.findPages(PageChecker.java:46)
	at br.com.bronx.vraptor.restrictrex.startup.PageHandler.handle(PageHandler.java:46)
	at br.com.caelum.vraptor.ioc.spring.StereotypedBeansRegistrar.handleRefresh(StereotypedBeansRegistrar.java:59)
	at br.com.caelum.vraptor.ioc.spring.StereotypedBeansRegistrar.onApplicationEvent(StereotypedBeansRegistrar.java:47)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:97)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:294)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:858)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:419)
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.start(SpringBasedContainer.java:63)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.start(SpringProvider.java:75)
	at br.com.caelum.vraptor.VRaptor.init(VRaptor.java:107)
	at br.com.caelum.vraptor.VRaptor.init(VRaptor.java:100)
	at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:295)
	at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:422)
	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:115)
	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3838)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4488)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:546)
	at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:637)
	at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:563)
	at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:498)
	at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1277)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:321)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:519)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:581)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
10/04/2010 00:03:23 org.apache.catalina.core.StandardContext start
SEVERE: Error filterStart
10/04/2010 00:03:23 org.apache.catalina.core.StandardContext start
SEVERE: Context [/JMovie] startup failed due to previous errors
10/04/2010 00:03:23 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: A web application registered the JBDC driver [org.postgresql.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
log4j:ERROR LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository.

Até erro no driver do Postgre tá dando. =/

B

Os métodos referentes às páginas de login e acesso negado (anotados com @AccessDeniedPage e @LoginPage) não podem receber parâmetros.

br.com.bronx.vraptor.restrictrex.exception.PageException: Access denied page method cannot have parameters.

Poste aí seu código caso haja dúvidas…

G

Estranho, só notei com @LoginPage o Login.

@Resource
public class LoginController {
	
	private UsuarioDAO usuarioDAO;
	private UsuarioLogado usuarioLogado;
	private Validator validator;
	private Result result; 
	
	
	public  LoginController(Result result, UsuarioLogado usuarioLogado, Validator validator) {  
			this.result = result;  
			this.usuarioLogado = usuarioLogado;  
			this.validator = validator;  
			}  
	
	
	@LoginPage
	@Path("/login")
	public void loginUsuario() {		
		if  (this.usuarioLogado.getPerfil().isLoggedIn())
			//caso o usuário já esteja logado, redirecione-o para a página principal  
		     this.result.redirectTo(IndexController.class).index();  		
	}	
	
	
	public LoginController(UsuarioDAO usuarioDAO, UsuarioLogado usuarioLogado, Result result){
	    this.usuarioDAO = usuarioDAO;
	    this.usuarioLogado = usuarioLogado;
	    this.result = result;
	}
	
	public void autentica(Usuario usuario) {	
		Usuario autenticado = usuarioDAO.buscaUsuarioPorLoginESenha(usuario);
		  if(usuarioDAO.existeUsuario(usuario)) {  			        
			this.validator.add(new ValidationMessage("Login já existe", "usuario.login"));  
			this.validator.onErrorUse(Results.logic()).redirectTo(LoginController.class).loginUsuario();  
		} else /*usuário encontrado*/{  
			usuarioLogado.efetuaLogin(autenticado);
			this.usuarioLogado.setUsuarioLogado(usuario);//guardo o usuário na sessão  
			this.result.redirectTo(HomeController.class).home();//redireciono para a página principal  
	    } 	
		  result.use(Results.logic()).redirectTo(LoginController.class).loginUsuario();   
	    
	}
	
	public void logout() {  
		this.usuarioLogado.setUsuarioLogado(null);		
		  result.redirectTo(IndexController.class).index();		 		
	} 
}
@Intercepts
public class AccesControllerInterceptor implements Interceptor {
	
	
	private RestrictionChecker restrictionChecker;
	private Result result;
	private UsuarioLogado usuarioLogado;
	
	
	public AccesControllerInterceptor(UsuarioLogado usuarioLogado, RestrictionChecker restrictionChecker, Result result) {
		this.result = result;
		this.restrictionChecker = restrictionChecker;
		this.usuarioLogado = usuarioLogado;
	}
	
	public boolean accepts(ResourceMethod method) {
		return this.restrictionChecker.hasRestriction(method.getMethod());
	}

	
	public void intercept(InterceptorStack stack, ResourceMethod resourceMethod,
	    Object resourceInstance) throws InterceptionException {
		RestrictionResult restrictionResult;
		//this.restrictionChecker.setDefaultAccessDeniedPage("/filme");
		this.restrictionChecker.setDefaultLoginPage("/login");
		
		try {
			restrictionResult = this.restrictionChecker.checkRestrictions(resourceMethod.getMethod(), this.usuarioLogado.getPerfil());
		} catch (RestrictionAnnotationException exception) {
			throw new InterceptionException(exception);
		} catch (DestinationException exception) {
			throw new InterceptionException(exception);
		}
		if (restrictionResult.isRestricted()){
			if (restrictionResult.isHttp403()) {
				this.result.use(Results.http()).sendError(403);
			} else {
				this.result.use(Results.page()).redirect(restrictionResult.getDestination());
			}
		} else {
			stack.next(resourceMethod, resourceInstance);
		}
	}
	
}

Era para abri a Index, lá do IndexController, que está assim:

@Path("/index")	
	public void index() {		
	}
B

Cara, tem certeza que não anotou nenhum método com a annotation @AccessDeniedPage??

Essa exceção só é lançada caso algum método dentro de algum recurso (classe anotada com @Resource) possua a annotation @AccessDeniedPage e possua parâmetros.

Dá uma olhada nos seus outros controllers para ver se vc deixou algum método com essa annotation.

No outro post vc setou o path “/filmes” como accessDeniedPage. Dê uma olhada no respectivo método para ver se a annotation não está lá.

Caso nenhum método esteja anotado com ela, aí corre o risco de haver um bug no meu código.

Faça essa verificação.

Te mandei uma mensagem pessoal com meu msn. Me add lá.

Abs.

G

Opa, só agora vi sua mensagem, vou te adicionar!

Acessou a index, era a anotação @AccesDeniedPage mesmo. =/

Agora o erro é no construtor do login:

10/04/2010 00:43:17 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginController' defined in file [/home/bruno/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/JMovie/WEB-INF/classes/br/com/bruno/jmovie/controller/LoginController.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.bruno.jmovie.controller.LoginController]: No default constructor found; nested exception is java.lang.NoSuchMethodException: br.com.bruno.jmovie.controller.LoginController.<init>()
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:946)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:890)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:328)
	at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:385)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:375)
	at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1069)
	at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:221)
	at br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:240)
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:58)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:41)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:619)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.bruno.jmovie.controller.LoginController]: No default constructor found; nested exception is java.lang.NoSuchMethodException: br.com.bruno.jmovie.controller.LoginController.<init>()
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:69)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:938)
	... 43 more
Caused by: java.lang.NoSuchMethodException: br.com.bruno.jmovie.controller.LoginController.<init>()
	at java.lang.Class.getConstructor0(Class.java:2706)
	at java.lang.Class.getDeclaredConstructor(Class.java:1985)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:64)
	... 44 more

Conseguiu ver algo errado lá no LoginController?

Valeu!!

B

A exception está dizendo que a classe não possui o construtor padrão (sem parâmetros):

(...)No default  constructor found; nested exception is java.lang.NoSuchMethodException: br.com.bruno.jmovie.controller.LoginController.<init>()  (...)

Mas isso não deveria ocorrer.

Crie aí um construtor padrão para ver o que acontece

Sinistro…!

L

tenta colocar a anotação @Autowired no construtor (antes de criar o construtor padrão)

se não funcionar, vc vai precisar trocar por injeção via setter…

de qqer forma, esse erro não deveria acontecer, a menos que vc esteja usando algo específico do spring (como o Spring AOP, Spring security, etc)

G

Deu certo Lucas!
Mandei a anotação no construtor:

@Autowired
	public  LoginController(Result result, UsuarioLogado usuarioLogado, Validator validator) {  
			this.result = result;  
			this.usuarioLogado = usuarioLogado;  
			this.validator = validator;  
			}

Abriu a Index, depois acessei a página de Login e ao digitar usuario e senha tenho este erro:

01:41:57,211 DEBUG [OgnlParametersProvider] Applying usuario.login with [admin]
01:41:57,272 DEBUG [OgnlParametersProvider] Applying usuario.senha with [admin]
01:41:57,280 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for public void br.com.bruno.jmovie.controller.LoginController.autentica(br.com.bruno.jmovie.model.Usuario) as [usuario]
01:41:57,280 DEBUG [ParametersInstantiatorInterceptor] Parameter values for {DefaultResourceMethod: br.com.bruno.jmovie.controller.LoginController.autentica} are [br.com.bruno.jmovie.model.Usuario@1cee792]
10/04/2010 01:41:57 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
br.com.caelum.vraptor.InterceptionException: java.lang.NullPointerException
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:77)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:77)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NullPointerException
	at br.com.bruno.jmovie.controller.LoginController.autentica(LoginController.java:49)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:50)
	... 37 more
10/04/2010 01:42:04 org.apache.coyote.http11.Http11Protocol pause
INFO: Pausing Coyote HTTP/1.1 on http-8080
10/04/2010 01:42:05 org.apache.catalina.core.StandardService stop
INFO: Stopping service Catalina
01:42:05,741  INFO [VRaptorApplicationContext] Closing Root WebApplicationContext: startup date [Sat Apr 10 01:41:42 BRT 2010]; root of context hierarchy
10/04/2010 01:42:05 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: A web application registered the JBDC driver [org.postgresql.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

Tava analisando com o Bronx este método:

public Usuario buscaUsuarioPorLoginESenha(Usuario usuario) {
	    Query query = this.session.
	    createQuery("from Usuario where login = :pLogin and senha = :pSenha");
	    query.setParameter("pLogin", usuario.getLogin());
	    query.setParameter("pSenha", usuario.getSenha());
	    return (Usuario) query.uniqueResult();
	}

São das classes da apostila da Caelum, não vislumbrei onde poderia estar dando conflito.

Abraço!!!

L

a nullpointer é na linha 49 do loginController:

Caused by: java.lang.NullPointerException  
     at br.com.bruno.jmovie.controller.LoginController.autentica(LoginController.java:49)

vê se tem algo lá q não foi inicializado

G

É, não sei mais onde pode estar o erro, conferi os métodos e estão corretos, são os mesmos que estava usando antes:

Form de login:

<form method="post" action="login/autentica" />    
    Login: <input type="text" name="usuario.login" /><br/>  
    Senha: <input type="password" name="usuario.senha" /><br/>  
            <input type="submit" value="Autenticar" />    
</form>

Removi a taglib na action pra deixar como estava antes, não deu certo.

Método LoginController:

public void autentica(Usuario usuario) {
		
Usuario autenticado = usuarioDAO.buscaUsuarioPorLoginESenha(usuario);
    if(autenticado != null) {
	  usuarioLogado.efetuaLogin(autenticado);
	  this.usuarioLogado.setUsuarioLogado(usuario);//guardo o usuário na sessão
	  result.use(Results.logic()).redirectTo(HomeController.class).home();
	  return;
      }
	  result.use(Results.logic()).redirectTo(LoginController.class).loginUsuario();
}

Acrescentei o return dentro do if(), e removi o validator para não interferir em nada, tb não resolveu.

Método buscaPorLoginESenha da classe UsuarioDAO:

public Usuario buscaUsuarioPorLoginESenha(Usuario usuario) {
	    Query query = this.session.
	    createQuery("from usuario where login = :pLogin and senha = :pSenha");
	    query.setParameter("pLogin", usuario.getLogin());
	    query.setParameter("pSenha", usuario.getSenha());
	    return (Usuario) query.uniqueResult();
	}

Nem encostei nessa classe.

Classe UsuarioLogado:

package br.com.bruno.jmovie.component;

import java.util.ArrayList;
import java.util.List;

import br.com.bruno.jmovie.model.Perfil;
import br.com.bruno.jmovie.model.Usuario;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.SessionScoped;

@Component
@SessionScoped
public class UsuarioLogado implements java.io.Serializable  {
	
	private static final long serialVersionUID = 1L;
	
		private Usuario usuarioLogado;
	     
	     public void efetuaLogin(Usuario usuario) {
	         this.usuarioLogado = usuario;
	     }
	     public Usuario getUsuario() {
	         return this.usuarioLogado;
	     }
	     
	     public void logout() {  
	         this.usuarioLogado = null;  
	    }  
	    	             
	    public boolean isLogged() {  
	    	 return usuarioLogado != null;  
	    }
	    public String getNome() {
	        return usuarioLogado.getNome();
	    }
		public void setUsuarioLogado(Usuario usuarioLogado) {
			this.usuarioLogado = usuarioLogado;
		}
		public Usuario getUsuarioLogado() {  
	    	 return this.usuarioLogado;  
	    }  
	    
	     public Perfil getPerfil() {  
	        Perfil perfil = new Perfil();  
	    	if (this.usuarioLogado != null) {  
	    	    perfil.setLoggedIn(true);
	    	    
	    	 List<String> roles = new ArrayList<String>();  
	    	     roles.add(this.usuarioLogado.getRole());  
	    	     perfil.setRoles(roles); 
	    	}
	    	 return perfil; 
	     }

	 }

Já tinha todos os métodos, apenas acrescentei o de pegar perfil e o de listar os roles.

Classe AccesControllerInterceptor:

package br.com.bruno.jmovie.interceptor;

import br.com.bronx.vraptor.restrictrex.exception.DestinationException;
import br.com.bronx.vraptor.restrictrex.exception.RestrictionAnnotationException;
import br.com.bronx.vraptor.restrictrex.restriction.RestrictionChecker;
import br.com.bronx.vraptor.restrictrex.restriction.RestrictionResult;
import br.com.bruno.jmovie.component.UsuarioLogado;
import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.view.Results;

@Intercepts
public class AccesControllerInterceptor implements Interceptor {
	
	
	private RestrictionChecker restrictionChecker;
	private Result result;
	private UsuarioLogado usuarioLogado;
	
	
	public AccesControllerInterceptor(UsuarioLogado usuarioLogado, RestrictionChecker restrictionChecker, Result result) {
		this.result = result;
		this.restrictionChecker = restrictionChecker;
		this.usuarioLogado = usuarioLogado;
	}
	
	public boolean accepts(ResourceMethod method) {
		return this.restrictionChecker.hasRestriction(method.getMethod());
	}

	
	public void intercept(InterceptorStack stack, ResourceMethod resourceMethod,
	    Object resourceInstance) throws InterceptionException {
		RestrictionResult restrictionResult;
		//this.restrictionChecker.setDefaultAccessDeniedPage("/filme");
		//this.restrictionChecker.setDefaultLoginPage("/login");
		
		try {
			restrictionResult = this.restrictionChecker.checkRestrictions(resourceMethod.getMethod(), this.usuarioLogado.getPerfil());
		} catch (RestrictionAnnotationException exception) {
			throw new InterceptionException(exception);
		} catch (DestinationException exception) {
			throw new InterceptionException(exception);
		}
		if (restrictionResult.isRestricted()){
			if (restrictionResult.isHttp403()) {
				this.result.use(Results.http()).sendError(403);
			} else {
				this.result.use(Results.page()).redirect(restrictionResult.getDestination());
			}
		} else {
			stack.next(resourceMethod, resourceInstance);
		}
	}
	
}

Deixei como postado aqui, apenas coloquei o usuarioLogado.getPerfil() na linha de checkRestrictions.

O erro é o mesmo, NullPointerException na linha 49 que é onde busca o usuário por login e senha. O usuário está cadastrado no banco e estou informando corretamente.

Alguma idéia?

Abraço pessoal!!

L

será q não tem algum motivo pro restrictionResult vir null? por exemplo o usuário não ter restrições?

se sim, é só adicionar outra condição no if… se isso for null vc faz o stack.next ou dá algum erro

G

Coloquei o código numa estrutura try/catch :

public void autentica(Usuario usuario, ResourceMethod resourceMethod, Validator validator,Object resourceInstance)
	throws InterceptionException{		
		try {
		Usuario autenticado = usuarioDAO.buscaUsuarioPorLoginESenha(usuario);
	    if(autenticado != null) {
	        usuarioLogado.efetuaLogin(autenticado);
	        this.usuarioLogado.setUsuarioLogado(usuario);//guardo o usuário na sessão
	        result.use(Results.logic()).redirectTo(HomeController.class).home();
	        return;
	    } else {
	    	 this.validator.add(new ValidationMessage("usuario.login", "login.obrigatorio"));
	    	 result.use(Results.logic()).redirectTo(LoginController.class).loginUsuario();
	    }
		} catch(Exception e) {
			//throw new InterceptionException(e.getMessage());
			
		} finally {
	    result.use(Results.logic()).redirectTo(HomeController.class).home();
	    
		}

Ficou uma coisa bizonha, redireciona para a Home, que seria a página após o login correto, porém informa que o usuário não está logado.

Este é o trecho que informa se o usuário está logado ou não:

<c:if test="${usuarioLogado.logged}">
    	Olá, ${usuarioLogado.nome }! <a href="<c:url value="/login/logout"/>">Logout</a>
		</c:if>
		<c:if test="${empty usuarioLogado or not usuarioLogado.logged}">
    	Você não está logado. <a href="<c:url value="/login"/>">Login</a>
    	<a href="<c:url value="/usuario"/>">Cadastre-se</a>
		</c:if>

Fica valendo o método isLogged() da classe UsuarioLogado ou tenho que usar outro método?

Esta é a saida:

16:40:38,088 DEBUG [DefaultResourceTranslator] trying to access /
16:40:38,101 DEBUG [DefaultResourceTranslator] found resource {DefaultResourceMethod: br.com.caelum.vraptor.blank.IndexController.index}
16:40:38,352 DEBUG [AsmBasedTypeCreator ] Trying to make class for IndexController$index$715134878$2
16:40:38,353 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for public void br.com.caelum.vraptor.blank.IndexController.index() as []
16:40:38,353 DEBUG [AsmBasedTypeCreator ] Parameter names found for creating type are: []
16:40:38,354 DEBUG [AsmBasedTypeCreator ] Methods: []
16:40:38,354 DEBUG [AsmBasedTypeCreator ] Fields: []
16:40:38,354 DEBUG [CacheBasedTypeCreator] cached generic type for method {DefaultResourceMethod: br.com.caelum.vraptor.blank.IndexController.index}
16:40:38,375 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for public void br.com.caelum.vraptor.blank.IndexController.index() as []
16:40:38,375 DEBUG [ParametersInstantiatorInterceptor] Parameter values for {DefaultResourceMethod: br.com.caelum.vraptor.blank.IndexController.index} are []
16:40:38,490 DEBUG [DefaultStaticContentHandler] deferring URI to container: /JMovie/WEB-INF/jsp/index/index.jsp
16:40:40,407 DEBUG [DefaultResourceTranslator] trying to access /login
16:40:40,408 DEBUG [DefaultResourceTranslator] found resource {DefaultResourceMethod: br.com.bruno.jmovie.controller.LoginController.loginUsuario}
16:40:40,448 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for public void br.com.bruno.jmovie.controller.LoginController.loginUsuario() as []
16:40:40,448 DEBUG [ParametersInstantiatorInterceptor] Parameter values for {DefaultResourceMethod: br.com.bruno.jmovie.controller.LoginController.loginUsuario} are []
16:40:40,485 DEBUG [DefaultStaticContentHandler] deferring URI to container: /JMovie/WEB-INF/jsp/login/loginUsuario.jsp
16:40:44,435 DEBUG [DefaultResourceTranslator] trying to access /login/autentica
16:40:44,436 DEBUG [DefaultResourceTranslator] found resource {DefaultResourceMethod: br.com.bruno.jmovie.controller.LoginController.autentica}
16:40:44,465 DEBUG [AsmBasedTypeCreator ] Trying to make class for LoginController$autentica$[telefone removido]$3
16:40:44,466 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for public void br.com.bruno.jmovie.controller.LoginController.autentica(br.com.bruno.jmovie.model.Usuario,br.com.caelum.vraptor.resource.ResourceMethod,br.com.caelum.vraptor.Validator,java.lang.Object) throws br.com.caelum.vraptor.InterceptionException as [usuario, resourceMethod, validator, resourceInstance]
16:40:44,468 DEBUG [AsmBasedTypeCreator ] Parameter names found for creating type are: [Usuario, ResourceMethod, Validator, ResourceInstance]
16:40:44,468 DEBUG [AsmBasedTypeCreator ] Method for field 'Usuario' being defined for type Lbr/com/bruno/jmovie/model/Usuario;
16:40:44,469 DEBUG [AsmBasedTypeCreator ] Method for field 'ResourceMethod' being defined for type Lbr/com/caelum/vraptor/resource/ResourceMethod;
16:40:44,470 DEBUG [AsmBasedTypeCreator ] Method for field 'Validator' being defined for type Lbr/com/caelum/vraptor/Validator;
16:40:44,470 DEBUG [AsmBasedTypeCreator ] Method for field 'ResourceInstance' being defined for type Ljava/lang/Object;
16:40:44,472 DEBUG [AsmBasedTypeCreator ] Methods: [public br.com.bruno.jmovie.model.Usuario LoginController$autentica$[telefone removido]$3.getUsuario(), public br.com.caelum.vraptor.resource.ResourceMethod LoginController$autentica$[telefone removido]$3.getResourceMethod(), public void LoginController$autentica$[telefone removido]$3.setResourceMethod(br.com.caelum.vraptor.resource.ResourceMethod), public void LoginController$autentica$[telefone removido]$3.setUsuario(br.com.bruno.jmovie.model.Usuario), public void LoginController$autentica$[telefone removido]$3.setValidator(br.com.caelum.vraptor.Validator), public br.com.caelum.vraptor.Validator LoginController$autentica$[telefone removido]$3.getValidator(), public void LoginController$autentica$[telefone removido]$3.setResourceInstance(java.lang.Object), public java.lang.Object LoginController$autentica$[telefone removido]$3.getResourceInstance()]
16:40:44,473 DEBUG [AsmBasedTypeCreator ] Fields: [private br.com.bruno.jmovie.model.Usuario LoginController$autentica$[telefone removido]$3.Usuario_, private br.com.caelum.vraptor.resource.ResourceMethod LoginController$autentica$[telefone removido]$3.ResourceMethod_, private br.com.caelum.vraptor.Validator LoginController$autentica$[telefone removido]$3.Validator_, private java.lang.Object LoginController$autentica$[telefone removido]$3.ResourceInstance_]
16:40:44,473 DEBUG [CacheBasedTypeCreator] cached generic type for method {DefaultResourceMethod: br.com.bruno.jmovie.controller.LoginController.autentica}
16:40:44,473 DEBUG [OgnlParametersProvider] Applying usuario.login with [admin]
16:40:44,528 DEBUG [OgnlParametersProvider] Applying usuario.senha with [admin]
16:40:44,529 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for public void br.com.bruno.jmovie.controller.LoginController.autentica(br.com.bruno.jmovie.model.Usuario,br.com.caelum.vraptor.resource.ResourceMethod,br.com.caelum.vraptor.Validator,java.lang.Object) throws br.com.caelum.vraptor.InterceptionException as [usuario, resourceMethod, validator, resourceInstance]
16:40:44,530 DEBUG [ParametersInstantiatorInterceptor] Parameter values for {DefaultResourceMethod: br.com.bruno.jmovie.controller.LoginController.autentica} are [br.com.bruno.jmovie.model.Usuario@1aa0a15, null, null, null]
16:40:44,751 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for public void br.com.bruno.jmovie.controller.HomeController.home() as []
16:40:44,752 DEBUG [AsmBasedTypeCreator ] Trying to make class for HomeController$home$84008057$4
16:40:44,752 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for public void br.com.bruno.jmovie.controller.HomeController.home() as []
16:40:44,752 DEBUG [AsmBasedTypeCreator ] Parameter names found for creating type are: []
16:40:44,753 DEBUG [AsmBasedTypeCreator ] Methods: []
16:40:44,753 DEBUG [AsmBasedTypeCreator ] Fields: []
16:40:44,753 DEBUG [CacheBasedTypeCreator] cached generic type for method {DefaultResourceMethod: br.com.bruno.jmovie.controller.HomeController.home}
16:40:44,795 DEBUG [DefaultResourceTranslator] trying to access /home
16:40:44,795 DEBUG [DefaultResourceTranslator] found resource {DefaultResourceMethod: br.com.bruno.jmovie.controller.HomeController.home}
16:40:44,828 DEBUG [ParametersInstantiatorInterceptor] Parameter values for {DefaultResourceMethod: br.com.bruno.jmovie.controller.HomeController.home} are []
16:40:44,866 DEBUG [DefaultStaticContentHandler] deferring URI to container: /JMovie/WEB-INF/jsp/home/home.jsp

Nesta linha parece que está vindo td null, conforme o Lucas falou.

16:40:44,530 DEBUG [ParametersInstantiatorInterceptor] Parameter values for {DefaultResourceMethod: br.com.bruno.jmovie.controller.LoginController.autentica} are [br.com.bruno.jmovie.model.Usuario@1aa0a15, null, null, null]

E o certo seria apenas dois parâmetros, login e senha, ali parecem três parâmetros que estão vindo, não sei se estou certo.

Valeu!!!

G

Consegui resolver o problema me baseando no exemplo do Bronx, faltou no construtor do LoginController os parâmetros de UsuarioDAO, conforme abaixo:

@Autowired
	public  LoginController(Result result, UsuarioLogado usuarioLogado, Validator validator, UsuarioDAO usuarioDAO) {  
			this.result = result;  
			this.usuarioLogado = usuarioLogado; 
			this.validator = validator;
			this.usuarioDAO = usuarioDAO;
			}

Agora o método autentica() funciona e está direcionando para a Home.

Ao direcionar para a Home não está mostrando o nome do usuário logado:

<c:choose>
		<c:when test="${usuarioLogado.usuarioLogado eq null}">
		Você não está logado. <a href="<c:url value="/login"/>">Fa&ccedil;a login</a>		
		</c:when>
		<c:otherwise>
		Ol&aacute;, ${usuarioLogado.nome }! <a href="<c:url value="/login/logout"/>">Logout</a>			
		</c:otherwise>
	</c:choose>

Estou pegando o nome lá no componente usuarioLogado, desta forma:

public String getNome() {
	        return usuarioLogado.getNome();
	    }

Na classe Usuario está:

public String getNome() {		
		return nome;
	}

Abraço!!

G

Para mostrar o nome do usuário logado na JSP usando o controlador de login é necessário usar EL com a estrutura Componente>Classe>Atributo, como a seguir:

Usando a taglib <c:choose>

<c:choose>
		<c:when test="${usuarioLogado.usuarioLogado eq null}">
		Você não está logado. <a href="<c:url value="/login"/>">Fa&ccedil;a login</a>		
		</c:when>
		<c:otherwise>
		Ol&aacute;, ${usuarioLogado.usuarioLogado.nome }! <a href="<c:url value="/login/logout"/>">Logout</a>			
		</c:otherwise>
</c:choose>

Ou usando a taglib <c:if test>

<c:if test="${usuarioLogado.usuarioLogado eq null}">
    	Você não está logado. <a href="<c:url value="/login"/>">Efetue Login</a>
</c:if> 	
<c:if test="${usuarioLogado.usuarioLogado != null}">
    	Olá, ${usuarioLogado.usuarioLogado.nome }! <a href="<c:url value="/login/logout"/>">Logout</a>
</c:if>

A expressão deveria mostrar o nome, mas NÃO mostra, me enganei ao editar o projeto, mas rodar outro que mostra o nome do usuário logado.

Abraço!

F

Bronx, parabéns pela iniciativa!!! :smiley:

já inclui em meu projeto e a configuração e as anotações estão bem simples de usar bacana!!!

Eu já li o tópico inteiro não sei se já perguntaram isso ou já deram essa sugestão mas ai vai!

Então eu criei o seguinte controller:

@LoggedIn
@Roles(roles = { "admin" })
@Resource
public class CategoriaController {

	public CategoriaController() {
	}
	
	public void list() {
		
	}
}

ai sem estar Logado tentei acessar a URI: “minhaapp/categoria/list” não acessou!!! Bingo funcionou, ai ele vai e me encaminha para o método que estiver anotado com @LoginPage. Porém depois que eu efetuo o meu login ele vai para o meu método de login “óbvio” ao invés de ir para URI que eu tinha tentado acessar…

ps: como eu faria para tipo salvar a URI q o usuário tentou acessar e se ele for efetuar o login leva-lo para lah após o login? tem como?

[]'s

L

é complexo, eu fiz na minha implementação… mas não foi tão simplis ^^ … infelismente não tive tempo de montar a página de documentação =/
mas farei muito em breve…

Obs.: não sei se o bronx fez a implementação…

G

Fala ai Bronx!
Estou com um probleminha aqui, saca so a saida do console:

INFO: Initializing Coyote HTTP/1.1 on http-8080
17/04/2010 16:38:01 org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 927 ms
17/04/2010 16:38:02 org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
17/04/2010 16:38:02 org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.26
16:38:02,939  INFO [VRaptorApplicationContext] Refreshing Root WebApplicationContext: startup date [Sat Apr 17 16:38:02 BRT 2010]; root of context hierarchy
16:38:03,264  INFO [VRaptorApplicationContext] Scanning WEB-INF/classes: /home/bruno/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp2/wtpwebapps/Imobiliaria/WEB-INF/classes
16:38:03,488  INFO [VRaptorApplicationContext] Scanning packages from WEB-INF/classes and jars: [br.com.bronx.vraptor.restrictrex]
16:38:03,544  INFO [DefaultListableBeanFactory] Overriding bean definition for bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor': replacing [Root bean: class [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Root bean: class [br.com.caelum.vraptor.ioc.spring.InjectionBeanPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
16:38:03,923  INFO [DefaultListableBeanFactory] Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@147358f: defining beans [defaultTypeFinder,asmBasedTypeCreator,defaultTypeNameExtractor,defaultDeserializers,defaultAcceptHeaderToFormat,defaultInterceptorRegistry,defaultResourceNotFoundHandler,emptyElementsRemoval,pathAnnotationRoutesParser,defaultRouter,defaultMethodNotAllowedHandler,defaultConverters,defaultRoutes,encodingHandlerFactory,noRoutesConfiguration,XStreamXMLDeserializer,objenesisProxifier,defaultResourceTranslator,paranamerNameProvider,defaultMultipartConfig,stereotypeHandler,converterHandler,interceptorStereotypeHandler,deserializesHandler,stereotypedBeansRegistrar,defaultSpringLocator,defaultStatus,XStreamJSONSerialization,defaultValidator,outjectResult,defaultRepresentationResult,executeMethodInterceptor,defaultHttpResult,defaultRefererResult,downloadInterceptor,defaultPathResolver,deserializingInterceptor,applicationConfiguration,defaultResult,flashInterceptor,parametersInstantiatorInterceptor,replicatorOutjector,defaultMethodInfo,resourceLookupInterceptor,XStreamXMLSerialization,ognlParametersProvider,defaultFormatResolver,forwardToDefaultViewInterceptor,interceptorListPriorToExecutionExtractor,defaultLogicResult,defaultValidationViewsFactory,instantiateInterceptor,multipartInterceptor,emptyResult,defaultPageResult,jstlLocalization,bigDecimalConverter,bigIntegerConverter,booleanConverter,byteConverter,characterConverter,doubleConverter,enumConverter,floatConverter,integerConverter,localeBasedCalendarConverter,localeBasedDateConverter,longConverter,primitiveBooleanConverter,primitiveByteConverter,primitiveCharConverter,primitiveDoubleConverter,primitiveFloatConverter,primitiveIntConverter,primitiveLongConverter,primitiveShortConverter,shortConverter,uploadedFileConverter,VRaptorRequestProvider,httpServletRequestProvider,httpServletResponseProvider,httpSessionProvider,defaultInterceptorStack,defaultRequestExecution,entityManagerCreator,entityManagerFactoryCreator,JPATransactionInterceptor,usuarioDAO,imovelDAO,loginController,indexController,imagemController,homeController,imovelController,accesControllerInterceptor,imagens,usuarioLogado,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,restrictionChecker,pageHandler,org.springframework.aop.config.internalAutoProxyCreator,cacheBasedTypeCreator]; root of factory hierarchy
16:38:04,136  INFO [DefaultConverters   ] Registering bundled converters
16:38:04,309  INFO [RouteBuilder        ] /login                                                       -> LoginController.login()
16:38:04,318  INFO [RouteBuilder        ] /login/adiciona                                              -> LoginController.adiciona(Usuario)
16:38:04,318  INFO [RouteBuilder        ] /login/autentica                                             -> LoginController.autentica(Usuario)
16:38:04,319  INFO [RouteBuilder        ] /login/logout                                                -> LoginController.logout()
log4j:WARN No appenders could be found for logger (br.com.bronx.vraptor.restrictrex.startup.PageHandler).
log4j:WARN Please initialize the log4j system properly.
16:38:04,365  INFO [RouteBuilder        ] /index/lista                                                 -> IndexController.lista()
16:38:04,366  INFO [RouteBuilder        ] /index                                                       -> IndexController.index()
16:38:04,374  INFO [RouteBuilder        ] /filme/{filme.id}/imagem                                     -> ImagemController.upload(Imovel, UploadedFile)
16:38:04,379  INFO [RouteBuilder        ] /filme/{filme.id}/imagem                                     -> ImagemController.download(Imovel)
16:38:04,380  INFO [RouteBuilder        ] /home                                                        -> HomeController.home()
16:38:04,381  INFO [RouteBuilder        ] /imovel/adiciona                                             -> ImovelController.adiciona(Imovel)
16:38:04,382  INFO [RouteBuilder        ] /imovel/lista                                                -> ImovelController.lista()
16:38:04,383  INFO [RouteBuilder        ] /imovel/edita                                                -> ImovelController.edita(Long)
16:38:04,387  INFO [RouteBuilder        ] /imovel                                                      -> ImovelController.formulario()
16:38:04,391  INFO [RouteBuilder        ] /imovel/altera                                               -> ImovelController.altera(Imovel)
16:38:04,392  INFO [RouteBuilder        ] /imovel/remove                                               -> ImovelController.remove(Long)
16:38:04,393  INFO [VRaptor             ] VRaptor 3.1.1 successfuly initialized
17/04/2010 16:38:04 org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
17/04/2010 16:38:04 org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
17/04/2010 16:38:04 org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/54  config=null
17/04/2010 16:38:04 org.apache.catalina.startup.Catalina start
INFO: Server startup in 2584 ms

No web.xml está:

<context-param>  
        <param-name>br.com.caelum.vraptor.packages</param-name>  
        <param-value>br.com.bronx.vraptor.restrictrex</param-value>  
    </context-param>

Tô tomando erro 404 ao acessar a aplicação pelo browser, sendo que ele encontra a index conforme aparece ai.
Sabe o que pode ser isso?

Já consigo acessar a aplicação, o problema era na anotação @Path da index. Mas o Warn do log4j continua acusando o appenders do PageHandler

Abraço!

G

Opa! Mais uma vitória aqui!
Consegui resolver o problema de mostrar o nome do usuário logado na JSP após ele ser incluido na sessão.
Este método é para usar com usuários cadastrados no banco.

No LoginController ficou assim:

public void autentica(Usuario usuario) {
		Usuario autenticado = usuarioDao.buscaUsuarioPorLoginESenha(usuario);
		if (autenticado != null) {
			this.usuarioLogado.setUsuarioLogado(autenticado);// guardo o usuário na sessão
			result.use(Results.logic()).redirectTo(HomeController.class).home();
		} else
			this.validator.add(new ValidationMessage("Login incorreto", "login.incorreto"));
		    this.validator.onErrorUse(Results.logic()).redirectTo(LoginController.class).login();

	}

O método de buscar por login e senha estão na apostila da Caelum, é só seguir por lá.

Eu estava fazendo errado, guardando na sessão o “usuario” ao invés de “autenticado”.

Na JSP ficou assim:

<c:choose>
		<c:when test="${usuarioLogado.usuarioLogado eq null}">
		Você não está logado.<a href="<c:url value="/login"/>">Fa&ccedil;a login</a>		
		</c:when>
		<c:otherwise>
		Ol&aacute;, ${usuarioLogado.usuarioLogado.nome }! <a href="<c:url value="/login/logout"/>">Logout</a>			
		</c:otherwise>
		</c:choose><br />

E por fim na classe UsuarioLogado tenho este método:

public String getNome() {  
	     return usuarioLogado.getNome();  
	}

O lance dos roles é que não tá funcionando aqui, anotei desta forma:

@Resource
@LoggedIn 
@Roles(roles="admin")
public class ImovelController {
//implementação aqui
}

Teóricamente só o admin poderia acessar esse controlador, mas o “guest” que eu cadastrei no banco tb está acessando. =/

Na classe Perfil está assim:

public Perfil getPerfil() {
		Perfil perfil = new Perfil();
		if (this.usuarioLogado != null) {
			perfil.setLoggedIn(true);
			perfil.setRoles(this.getRolesUsuario());
		}
		return perfil;
	}

private List<String> getRolesUsuario() {
		List<String> roles = new ArrayList<String>();
		roles.add("admin");
		roles.add("guest");
		return roles;
	}

Alguma idéia do que possa ser?
Abraço!

G

Resolvi essa tb!!
O acesso ao Controller anotado com role=“admin” agora só acessa usuário que é admin, o método para pegar o role do usuário lá no banco ficou assim:

public String getRole() {
		return usuarioLogado.getRole();
	}

public Perfil getPerfil() {
		Perfil perfil = new Perfil();
		if (this.usuarioLogado != null) {
			perfil.setLoggedIn(true);
			List<String> roles = new ArrayList<String>();
			roles.add(this.usuarioLogado.getRole());
			perfil.setRoles(roles);
		}
		return perfil;
	}

Para quem quiser mostrar além do usuário na JSP, o role do usuário é só colocar desta forma:

<c:choose>
		<c:when test="${usuarioLogado.usuarioLogado eq null}">
		Você não está logado.<a href="<c:url value="/login"/>">Fa&ccedil;a login</a>		
		</c:when>
		<c:otherwise>
		Ol&aacute;, ${usuarioLogado.usuarioLogado.nome }!, ${usuarioLogado.usuarioLogado.role } <a href="<c:url value="/login/logout"/>">Logout</a>			
		</c:otherwise>
		</c:choose>

Abraço! =)

G

Tô com um probleminha aqui ao efetuar logout, quando clico em “voltar” no browser volta para a Home, que deveria ser acessada apenas com usuário logado, embora a Home seja visualizada sem o usuário estar logado, é uma coisa bem chata.
Anotei a Home com @Roles(roles=“admin”) e não resolveu, nem com @LoggedIn. =/
Como faço pra impedir esse “voltar” no browser?
Abraço!

L

Guevara:
Tô com um probleminha aqui ao efetuar logout, quando clico em “voltar” no browser volta para a Home, que deveria ser acessada apenas com usuário logado, embora a Home seja visualizada sem o usuário estar logado, é uma coisa bem chata.
Anotei a Home com @Roles(roles=“admin”) e não resolveu, nem com @LoggedIn. =/
Como faço pra impedir esse “voltar” no browser?
Abraço!

Não faz ^^

simples assim…

O voltar do browser é feito com cache… o navegador faz cache da página… e ele só volta pra algo que ele já abriu, portanto quem abriu tinha autorização…

Existem forma de tornar uma página impedida de fazer cache… mas mesmo asism o browser pode decidir fazer cache, ou uma rede proxy, enfim… via ser dificil tirar isso…

só com páginas via método “POST” e mesmo assim… clicando em voltar é capaz de abrir…

G

Oi Lavieri!!
Achei esta dica aqui:
http://vraptor.caelum.com.br/cookbook/evitando-que-o-browser-faca-cache-das-paginas/
Será que resolve esse lance?
Abraço!

G

Fiz uma receita de bolo que está publicada no site do vraptor que mostra um componente que não deixa nem o browser nem o proxy fazer cache: http://vraptor.caelum.com.br/cookbook/evitando-que-o-browser-faca-cache-das-paginas/

G

E ai Garcia!!!
Deu certo!! Resolveu o problema!! :smiley:
Abraço!!

L

Fiz uma receita de bolo que está publicada no site do vraptor que mostra um componente que não deixa nem o browser nem o proxy fazer cache: http://vraptor.caelum.com.br/cookbook/evitando-que-o-browser-faca-cache-das-paginas/

é eu sei… eu uso isso… mas mesmo assim, o browser se quiser ou o proxy podem fazer o cache…

isso é uma recomendação do site, para que não o faça, o que não quer dizer que o browser irá segui-la

J

O post vai virar um CRUD ?

G

E ae bronx!

Achei a idéia sensacional e o feedback que o pessoal tem dado muito bom.
Esta semana estarei utilizando em um projeto que estou fazendo e qualquer contribuição posto por aqui.

mto bom cara.
abraços

J

bronx!

Eu vou incorporar o teu PROJETO no meu : http://www.guj.com.br/posts/list/204767.java
J

gabrielmassote !

Tu ja fez algum projeto no VRapotr ?
G

Tudo bem Junior?

Já fiz os exemplos das apostilas da Caelum com o VRaptor antigo e uma parte com o novo.

Agora que estou aprendendo tudo o que um projeto que estou fazendo necessita.
Esta indo tranquilo. Muito legal o framework.

Ok?
Abraços

J

Qual teu email, para eu te mandar um presente ! gmail !

J

gabrielmassote Enviado !

J

Vamos faZer o CRUD ?

D

(A.S.: perdão se eu estiver ressuscitando a thread. :-o)

fabio.cbrandao:
…Eu já li o tópico inteiro não sei se já perguntaram isso ou já deram essa sugestão mas ai vai!

Então eu criei o seguinte controller:

... ai sem estar Logado tentei acessar a URI: “minhaapp/categoria/list” não acessou!!! Bingo funcionou, ai ele vai e me encaminha para o método que estiver anotado com @LoginPage. Porém depois que eu efetuo o meu login ele vai para o meu método de login “óbvio” ao invés de ir para URI que eu tinha tentado acessar…

ps: como eu faria para tipo salvar a URI q o usuário tentou acessar e se ele for efetuar o login leva-lo para lah após o login? tem como?

[]'s

Lavieri:
é complexo, eu fiz na minha implementação… mas não foi tão simplis ^^ … infelismente não tive tempo de montar a página de documentação =/
mas farei muito em breve…

Obs.: não sei se o bronx fez a implementação…

Oi Bronx, Blz?!! :wink:
Antes de qq coisa: meus parabens p/ idéia do Pluggin de Autenticação/Privilégios!!! P/ ser sincero, é uma das raras partes q não sou muito fã de trabalhar (em desenvolvimento de sistemas). A sua implementação inicial fez 1 uso bem prático da JavaAnnotation e, com o desenrolar da thread, foi adicionada + simplicidade da CoC, né não?!! 8)
Ah, muito bacana a questão q o fabio levantou: :idea: é mesmo! P/ ex., no caso de a Sessão expirar, a pessoa é Cadastra e tem o Priviégio necessário para acessar determina pág. Blz, ele faz o LogOn e como fazemos p/ redirecionarmos p/ a pág. q ela estava tentando acessar??!
Lucas, bl?!!
Alias, existe no VRaptor alguma forma de sabermos qual foi a URL/URI q fez o request ao método, sem ser (é claro) pela CoC/Conveção do VRaptor3??! :?:

F

Bronx mais uma vez Parabéns!!!

estou aqui só para postar um feedback a respeito. Já estou utilizando o seu Controle de Acesso a aproximadamente 2 meses e está funcionando perfeitamente, neste final de semana inclusive coloquei o site que eu vinha trabalhando com Vraptor + Controle de Acesso no AR disponivel para todos os usuários!!!

para aqueles que se interessarem

http://www.loucaliza.com.br

URL Bloqueada:
http://www.loucaliza.com.br/admin

A idéia do Loucaliza foi criar uma comunidade de usuárioas que queiram contribuir cadastrando as localizações que conheçam, além de contribuirem comentandosobre estas localizações avaliando-as com notas. A idéia é ajudar as pessoas a escolherem um serviço de acordo com as experiencias de outras pessoas que já utilizaram aquele serviço!

Valeu comu GUJ!!!

L

E ai pessoal!!!

Alguém consegue fazer um pacote com a ultima atualização do sisteminha de controle de acesso?

Obrigado!!!

J

Leandro-SP tem como disponibilizar ?

F

Pessoal,

acredito que esta seja a ultima versão que o Bronx tenha disponibilizado, pelo menos é a que eu estou utilizando no Loucaliza, e está funcionando perfeitamente tentem acessar a http://www.loucaliza.com.br/admin que está com acesso restrito, e mesmo que vc se cadastre no site não vai conseguir acessar essa URL pois é apenas para Roles Admin…

J

fabio.cbrandao

É tipo o Spring Security ?

como ta a extrutura de tuas tabelas ? do acesso !?
F

juniorsatanas:
fabio.cbrandao

É tipo o Spring Security ?

como ta a extrutura de tuas tabelas ? do acesso !?</blockquote>

Junior, eu não conheço muito bem o Spring Security então não sei comparar com ele.

Não sei se entendi sua pergunta direito mas o meu controle de acesso eu estou fazendo com um campo Roles na Tabela do Usuário. Não Tenho uma tabela apenas para Roles para associa-lá com a tabela de Usuários, mas sei que muito fazem isso e acredito que seja a maneira mais correta de se fazer. Mas acredito que sua estrutura varia de acordo com a dificuldade e complexidade do Projeto.

J

Usuário.


id bigint
nome cv
senha
cpf cv
Roles cv

tendo essa tabela eu faço uma pesquisa no banco, procurando por nome e senha, e a Roles do usuário correto ? apos isso eu direciono ele para

Página 1 ----------- se administrador
pagina 2 ------------se usuario comum
pagina 3-------------se tec
etc…

é isso ?

F

juniorsatanas:
Usuário.


id bigint
nome cv
senha
cpf cv
Roles cv

tendo essa tabela eu faço uma pesquisa no banco, procurando por nome e senha, e a Roles do usuário correto ? apos isso eu direciono ele para

Página 1 ----------- se administrador
pagina 2 ------------se usuario comum
pagina 3-------------se tec
etc…

é isso ?

Exatamente isso!

Minha estrutura segue este mesmo modelo que vc passou. Dá pra vc direciona-lo para cada página de acordo com a Roles dele.

J

fabio.cbrandao tu pode postar parte do código aqui, para eu ter uma ideia de como fazer o meu ?

F

juniorsatanas:
fabio.cbrandao tu pode postar parte do código aqui, para eu ter uma ideia de como fazer o meu ?

@LoggedIn
@Resource
public class AdminLocalizacaoController {

	private final Result result;
	private final LocalizacaoDAO dao;
	
	public AdminLocalizacaoController(Result result, LocalizacaoDAO dao) {
		this.result = result;
		this.dao = dao;
	}
	
	@Roles(roles = {"admin", "moderador"})
	@Path("/admin/localizacao/list")
	public void list() {
	}
	
	@Roles(roles = {"admin"})
	@Path("/admin/localizacao/excluir/{id}")
	public void excluir(Long id) {
		dao.delete(dao.findById(id));
		result.use(Results.logic()).redirectTo(AdminLocalizacaoController.class).list();		
	}

Como vc pode ver nesse controle eu tenho dois métodos um é apenas para previlégio do admin e o outro pode ser chamado por admin e moderador…

F

Pessoal,

estou postando aqui um projeto de exemplo utilizando o Restrictrex…

Acesse o link abaixo e baixe o RestrictrexProject.zip
http://cid-3bd2ec0085abad63.office.live.com/self.aspx/.Public/RestrictrexProject.zip

obs: desenvolvi o projeto no eclipse e compactei em .zip, caso tenham alguma dificuldade em acessa-lo avise.

J

fabio.cbrandao !

Obrigado, vai poupar tempo para meu projeto, fico devendo uma ! ótima iniciativa !

Boa Semana !

Junior

J

Fabio, vou pegar teu exemplo e por ele para rodar + postgresql, e vou postar o link para baixar !

Flw

F

Ok, juniorsatanas!

Poste ai que vai nos ajudar bastante!

J

o que ta foda e isso :

package br.com.restrictrex.project.controller;

import br.com.bronx.vraptor.restrictrex.annotation.LoggedIn;
import br.com.bronx.vraptor.restrictrex.annotation.Roles;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Resource;
import br.com.restrictrex.project.model.Usuario;
import br.com.restrictrex.project.session.UsuarioLogado;

@Resource
public class UsuarioController {

	private final UsuarioLogado usuarioLogado;
	
	public UsuarioController(UsuarioLogado usuarioLogado) {
		this.usuarioLogado = usuarioLogado;
	}
	
	public void login(Usuario usuario) {
		this.usuarioLogado.efetuaLogin(usuario);
	}
	
	@LoggedIn
	@Roles(roles = {"admin"})
	@Path("/test1")
	public void test1() {
	}
	
	@LoggedIn
	@Roles(roles = {"admin", "moderador"})
	@Path("/test2")
	public void test2() {
	}
	
	@LoggedIn
	@Roles(roles = {"admin", "moderador", "usuario"})
	@Path("/test3")
	public void test3() {
	}
	
	@LoggedIn
	@Roles(roles = {"moderador"})
	@Path("/test4")
	public void test4() {
	}
	
	@LoggedIn
	@Roles(roles = {"moderador", "usuario"})
	@Path("/test5")
	public void test5() {
	}
	
	@LoggedIn
	@Roles(roles = {"usuario"})
	@Path("/test6")
	public void test6() {
	}
}
PARA ISSO :
package br.com.catequese.controller;

import br.com.catequese.security.UsuarioWeb;
import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Put;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import static br.com.caelum.vraptor.view.Results.*;

import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.Hibernate;
import br.com.caelum.vraptor.validator.ValidationMessage;
import br.com.catequese.dao.UsuarioDao;
import br.com.catequese.to.Usuario;
import java.util.List;

@Resource
public class UsuarioController {
    private final UsuarioDao dao;
    private final Result result;
    private final Validator validator;
    private final UsuarioWeb usuarioWeb;
    
    public UsuarioController(UsuarioDao dao, Result result, Validator validator, UsuarioWeb usuarioWeb) {
        this.dao = dao;
        this.result = result;
        this.validator = validator;
        this.usuarioWeb = usuarioWeb;
    }

    @Post @Path("/usuario/adiciona")
    public void adiciona(Usuario usuario) {
        if (dao.existeUsuario(usuario)) {
            validator.add(new ValidationMessage("Login já existe", "usuario.login"));
        }
        validator.onErrorUse(page()).of(UsuarioController.class).formulario();
        dao.adiciona(usuario);
        result.redirectTo(UsuarioController.class).lista();
    }

    @Delete @Path("/usuario/{idUsuario}")
    public void remove(Integer idUsuario) throws Exception {
        Usuario d = dao.carrega(idUsuario);
        dao.excluir(d);
        result.redirectTo(UsuarioController.class).lista();
    }

    @Get @Path("/usuario/{idUsuario}")
    public Usuario edita(Integer idUsuario){
        return dao.carrega(idUsuario);
    }

    @Put @Path("/usuario/{usuario.idUsuario}")
    public void altera(Usuario usuario) {
        validator.addAll(Hibernate.validate(usuario));
        validator.onErrorUse(page()).of(UsuarioController.class).edita(usuario.getIdUsuario());
        dao.atualiza(usuario);
        result.redirectTo(UsuarioController.class).lista();
    }

    @Get @Path("/usuario/novo")
    public void formulario() {
    }

    @Get @Path("/usuario/todos")
    public List&lt;Usuario&gt; lista(){
        return dao.listaTudo();
    }

    @Get @Path("/usuario/login")
    public void loginForm() {
    }

    @Post @Path("/usuario/login")
    public void login(Usuario usuario) throws Exception {
        Usuario carregado = dao.carrega(usuario);
        if (carregado == null) {
            validator.add(new ValidationMessage("Login e/ou senha inválidos", "usuario.login"));
        }
        validator.onErrorUse(page()).of(UsuarioController.class).loginForm();
        usuarioWeb.login(carregado);
        result.redirectTo(AlunoController.class).formulario();
    }

    @Path("/usuario/logout")
    public void logout() {
        usuarioWeb.logout();
        result.redirectTo(UsuarioController.class).loginForm();
    }
}
L

Obrigado bronx!!!

São 2:18h. de um sábado e eu finalmente consegui fazer funcionar o seu Restrictrex no meu projeto. Estava desde às 22h. Obrigado.

J

Leandro-SP Bom dia !

Como você fez ? tem como postar aqui ?

abraço.

L

juniorsatanas:
Leandro-SP Bom dia !

Como você fez ? tem como postar aqui ?

abraço.

Fiz exatamente com o Guevara fez… ele colocou as classes dele nos posts anteriores.
Foi um pouco complicado (quebrei a cabeça) para adaptar ao meu projeto mas no fim ocorreu tudo bem.
Dá uma olhadinha nos posts anteriores e se sentir dificuldades me fala ou coloca a sua duvida aqui pra galera.
Att,
Leandro

J

Leandro…

Exemplo que funciona e me leva para N telas diacordo com a Roles…

@LoggedIn
	@Roles(roles = {"admin"})
	@Path("/test1")
	public void test1() {
	}
	
	@LoggedIn
	@Roles(roles = {"admin", "moderador"})
	@Path("/test2")
	public void test2() {
	}

Meu sistema que logar pegando um OBJETO usuario senha e roles do banco e me direciona para uma tela FORM !

@Post @Path("/usuario/login")
    public void login(Usuario usuario) throws Exception {
        Usuario carregado = dao.carrega(usuario);
        if (carregado == null) {
            validator.add(new ValidationMessage("Login e/ou senha inválidos", "usuario.login"));
        }
        validator.onErrorUse(page()).of(UsuarioController.class).loginForm();
        usuarioWeb.login(carregado);
        result.redirectTo(AlunoController.class).formulario();
    }

Pergutna é : como pegar esse valor de roler do banco e comparar com " @Roles(roles = {“admin”})"

Obrigado !

J

Quero fazer um controle de usuário:

Usuario páginas 1 2 3 5 9 8
Administrado páginas 1 2
Pesquisador páginas 3 5
Cadastrador páginas 1

Vai no banco e pega a Roles, e direciona para páginas que tem acesso !

Abraço
.

J

ok

F

Estou vindo ressuscitar o tópico… rs

Pessoal,

Já estou trabalhando a um bom tempo com o VRaptor3 no meu projeto e hoje resolvi atualizar sua versão.

Eu estava com a versão 3.1.1 e resolvi atualizar para a mais atual 3.1.3, porém logo de cara quando fui subir o TOMCAT deu um erro! A única coisa q fiz foi trocar o .jar do vraptor e alterar a ref. no meu classpath

Alguém já viu esse erro?

14:00:15,934  INFO [DefaultSpringLocator] No application context found
14:00:16,043  INFO [VRaptorApplicationContext] Refreshing Root WebApplicationContext: startup date [Tue Aug 10 14:00:16 GMT-03:00 2010]; root of context hierarchy
14:00:16,403  INFO [Version             ] Hibernate Validator 3.1.0.GA
14:00:16,481  INFO [VRaptorApplicationContext] Scanning WEB-INF/classes: C:\Develop\Workspaces\Workspace-Loucaliza\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\Loucaliza\WEB-INF\classes
log4j:WARN No appenders could be found for logger (org.springframework.core.io.support.PathMatchingResourcePatternResolver).
log4j:WARN Please initialize the log4j system properly.
14:00:16,949  INFO [VRaptorApplicationContext] Scanning packages from WEB-INF/classes and jars: [br.com.bronx.vraptor.restrictrex]
10/08/2010 14:00:17 org.apache.catalina.core.StandardContext filterStart
SEVERE: Exception starting filter vraptor
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'pageHandler' defined in URL [jar:file:/C:/Develop/Workspaces/Workspace-Loucaliza/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Loucaliza/WEB-INF/lib/restrictrex-1.0.2.jar!/br/com/bronx/vraptor/restrictrex/startup/PageHandler.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.route.Router]: : Error creating bean with name 'defaultRouter': Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.caelum.vraptor.http.route.RoutesParser]: : Error creating bean with name 'pathAnnotationRoutesParser': Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.caelum.vraptor.http.route.TypeFinder]: : Error creating bean with name 'defaultTypeFinder': Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.ParameterNameProvider]: : Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultTypeFinder': Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.ParameterNameProvider]: : Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'pathAnnotationRoutesParser': Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.caelum.vraptor.http.route.TypeFinder]: : Error creating bean with name 'defaultTypeFinder': Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.ParameterNameProvider]: : Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultTypeFinder': Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.ParameterNameProvider]: : Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultRouter': Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.caelum.vraptor.http.route.RoutesParser]: : Error creating bean with name 'pathAnnotationRoutesParser': Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.caelum.vraptor.http.route.TypeFinder]: : Error creating bean with name 'defaultTypeFinder': Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.ParameterNameProvider]: : Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultTypeFinder': Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.ParameterNameProvider]: : Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'pathAnnotationRoutesParser': Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.caelum.vraptor.http.route.TypeFinder]: : Error creating bean with name 'defaultTypeFinder': Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.ParameterNameProvider]: : Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultTypeFinder': Unsatisfied dependency expressed through constructor argument with index 0 of type [br.com.caelum.vraptor.http.ParameterNameProvider]: : Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paranamerNameProvider': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.caelum.vraptor.http.ParanamerNameProvider]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:698)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.start(SpringBasedContainer.java:68)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.start(SpringProvider.java:82)
	at br.com.caelum.vraptor.VRaptor.init(VRaptor.java:110)
	at br.com.caelum.vraptor.VRaptor.init(VRaptor.java:103)
	at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275)
	at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:397)
	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3709)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4363)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
J
Xi, extranho pra caralho !

Xi, extranho pra caralho !

F

É realmente muito estranho.

O mais estranho foi o fato de ele ter gerado um erro como se houvesse algum conflito com o jar ou com a configuração do restrictrex.

Foi até por isso q postei essa dúvida neste tópico do restrictrex. Achei q alguém já tivesse passado por isso.

F

Descobri!

O meu projeto na versão 3.1.1 não usava o jar paranamer-2.2.jar

Porém só foi eu trocar o .jar do vraptor e add o paranamer-2.2.jar

Se algum dia alguém precisar segue a dica!

J

não “extranho” com X - risos. ainda bem que resolveu !

J

fabio.cbrandao

Teu conctrole de usuário, pega no banco a permisão e o caminho do roles ?

vlw

L
Tenta atualizar o paranamer.jar

Tenta atualizar o paranamer.jar

F

juniorsatanas:
fabio.cbrandao

Teu conctrole de usuário, pega no banco a permisão e o caminho do roles ?

vlw

Junior,

Meu controle de usuário pega a permissão do usuário assim que ele efetua o login no sistema…

não entendi a pergunta na parte do caminho de roles…?

F

Leandro-SP:
java.lang.NoClassDefFoundError: com/thoughtworks/paranamer/AnnotationParanamer

Tenta atualizar o paranamer.jar

É o problema foi solucionado troquei a versão do paranamer-1.5.jar para o paranamer-2.2.jar

G

Opa! Td certo pessoal?
Tô procurando a dica para redirecionar o usuário para a Home caso ele ainda esteja logado, o lance é que eu chamei a index e ela aparareceu, toda zicada, pq o usuário logado possui outro css, então para os recursos/métodos que não tenham restrição seria legal mandar o usuário logado para a Home, alguém têm essa resposta?
Abraço!!

F

Guevara,

Não entendi direito mas vc quer direcionar o usuário logado para a home quando ele tentar acessar algum método q não tenha permissão? Se for isso anote o seu método Home com

@AccessDeniedPage
public void home() {
}
G

Oi Fabio!
O problema não é a home, é a index, pois os métodos restritos podem ser anotados para restringir para determinados usuários o acesso. Mas os métodos sem anotação acessados por usuários não logados podem ser acessados tb pelos usuários logados, o problema é que a página é aberta toda zicada, pois o css do usuário logado é diferente dos usuários visitantes.Exemplo:

@Roles(admin)
public void lista() {
}

public void listaVenda() {
}

Repare que o listaVenda tb pode ser acessado pelo admin, mas a página virá com css referente a visitantes e não css do admin.
Como eu estou usando Sitemesh, o decorador de listaVenda() é diferente do lista(). Pra mim o redirecionamento do admin para a home ao acessar a index já tava bom.

Abraço!

F
@Roles(roles = {"admin"})
public void lista() {   
}   
  
public void listaVenda() {   
   if(usuarioLogado.getUsuario() != null)
      result.use(Results.logic()).redirectTo(MeuController.class).lista();	
}

Cara tenta fazer isso, incluir uma verificação para ver se o usuário q está acessando o método está logado caso ele esteja redirecione a lógica para o método do usuário logado!!!

S

Pessoal, a versão do primeiro post é a mais atualizada? Gostei bastante desse plugin, mas não terei tempo para ler o tópico todo. Li a primeira página, a documentação e os primeiros comentários acerca da biblioteca, mas não me ficou claro se a versão do primeiro post é a mais atual.

F

Cara,

Página 8 (oito) penultimo post coloquei a versão 1.0.2.jar é a versão q eu estou utilizando acredito q seja a ultima…

G

Oi Spidey, a versão atual postada no tópico é a 1.2, está na página 3 ou 4, o Bronx postou.

Fabio, vou pesquisar aqui como posso resolver esse lance, mas acho que o ideal seria ter algo no web.xml, se o cara estiver logado mandar pra pagina Home. Lembrei do lance de redirecionamento para 404 e 500, se colocar a tag deles lá o usuário é redirecionado para uma JSP personalizada. Poderia ser feito o mesmo com o Restrictrex, algo do tipo:

<login-page>
	<login-status>LoggedIn</login-status>
	<location>/WEB-INF/jsp/home.jsp</location>
	</login-page>

Ou se o cara não estiver logado ir para a index.jsp:

<login-page>
	<login-status>LoggedOut</login-status>
	<location>/WEB-INF/jsp/index.jsp</location>
	</login-page>

Fazer verificação em cada método do sistema fica inviável, seria melhor fazer uma verificação de sessão, se o cara não tiver na sessão manda pra index, se tiver na sessão impedir dele acessar páginas liberadas, não sei se expliquei direito mas a ideia é essa.
O Bronx é que deve saber desse lance… =)

G

Um exemplo do que eu expliquei, tenho a minha index.jsp, qualquer um pode acessar:

O menú da home, assim como páginas restritas possuem outro tipo de css, para o funcionário o css da página é outro, como na imagem abaixo:

Beleza, mas se o funcionario cair numa index, ou numa venda.jsp. ou aluguel.jsp que são páginas que não possuem restrição alguma, é isto que acontece:

CSS de páginas index com menú de usuário logado, misturou td.
Como estou usando SiteMesh o decorador de index, venda e aluguel.jsp é especifico para usuários não logados, já as páginas com restrições possuem outro decorador. É ai que está o dilema.

F

Agora entedi!!!

Nesse caso não vou saber t ajudar, não uso o sitemash nem decorador nenhum…

Estou usando o velhor de guerra include das jsps…

B

Você tem duas opções:

1 - Vc restringe esses recursos “livres” para que somente usuários não logados acessem. Nesse caso, o próprio RestrictRex vai mandar o usuário logado para a página de acesso negado. Ex:

@Roles(roles = "usuario_nao_logado") //usuários que não satisfizerem essa condição serão redirecionados para o método anotado com @AccessDeniedPage
public void foo() {
    //stuff
}

;

2 - No início de cada método, verificar se o usuário está logado. Umas três linhas a mais no começo do método, mas vc fica livre pra redirecionar o cara para onde quiser. Ex:

public void bar() {
    if (!this.sessionUser.isLoggedIn())  //sessionUser pode ser, por exemplo, o componente que armazena os dados do usuário logado
        this.result.redirectTo...//se não estiver logado, redirecione-o para algum lugar
    //stuff
}

Enfim, acho que não tem muita relação com o restritor, e mais com a regra de negócios do cara.
Mas estão aí possíveis soluções. :thumbup:

J

Bronx tu chegou a terminar o demo desse seu recurso ? tipo um CRUD pegando do banco as roles etc.. ?
Estou com dúvida nisto :

Não estou conseguindo pegar as roles do banco !
package br.com.restrictrex.project.session;

import java.util.ArrayList;
import java.util.List;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.SessionScoped;
import br.com.restrictrex.project.model.Usuario;
import br.com.restrictrex.project.roles.Perfil;

@Component
@SessionScoped
public class UsuarioLogado {
    private Usuario usuario;
    public UsuarioLogado() {
    }
    public void efetuaLogin(Usuario usuario) {
        this.usuario = usuario;
    }
    public void efetuaLogoff() {
        this.usuario = null;
    }
    public Usuario getUsuario() {
        return usuario;
    }
    public Perfil getPerfil() {  
        Perfil perfil = new Perfil();  
        if (this.getUsuario() != null) {  
            perfil.setLoggedIn(true);
            List&lt;String&gt; roles = new ArrayList&lt;String&gt;();  
            roles.add(this.getUsuario().getRoles());  
            perfil.setRoles(roles);  
        }  
        return perfil;  
    }
}
package br.com.catequese.controller;

import br.com.catequese.security.UsuarioWeb;
import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Put;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import static br.com.caelum.vraptor.view.Results.*;

import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.Hibernate;
import br.com.caelum.vraptor.validator.ValidationMessage;
import br.com.catequese.dao.UsuarioDao;
import br.com.catequese.to.Usuario;
import java.util.List;

@Resource
public class UsuarioController {
    private final UsuarioDao dao;
    private final Result result;
    private final Validator validator;
    private final UsuarioWeb usuarioWeb;
    
    public UsuarioController(UsuarioDao dao, Result result, Validator validator, UsuarioWeb usuarioWeb) {
        this.dao = dao;
        this.result = result;
        this.validator = validator;
        this.usuarioWeb = usuarioWeb;
    }

    @Post @Path("/usuario/adiciona")
    public void adiciona(Usuario usuario) {
        if (dao.existeUsuario(usuario)) {
            validator.add(new ValidationMessage("Login já existe", "usuario.login"));
        }
        validator.onErrorUse(page()).of(UsuarioController.class).formulario();
        dao.adiciona(usuario);
        result.redirectTo(UsuarioController.class).lista();
    }

    @Delete @Path("/usuario/{idUsuario}")
    public void remove(Integer idUsuario) throws Exception {
        Usuario d = dao.carrega(idUsuario);
        dao.excluir(d);
        result.redirectTo(UsuarioController.class).lista();
    }

    @Get @Path("/usuario/{idUsuario}")
    public Usuario edita(Integer idUsuario){
        return dao.carrega(idUsuario);
    }

    @Put @Path("/usuario/{usuario.idUsuario}")
    public void altera(Usuario usuario) {
        validator.addAll(Hibernate.validate(usuario));
        validator.onErrorUse(page()).of(UsuarioController.class).edita(usuario.getIdUsuario());
        dao.atualiza(usuario);
        result.redirectTo(UsuarioController.class).lista();
    }

    @Get @Path("/usuario/novo")
    public void formulario() {
    }

    @Get @Path("/usuario/todos")
    public List&lt;Usuario&gt; lista(){
        return dao.listaTudo();
    }

    @Get @Path("/usuario/login")
    public void loginForm() {
    }

    @Post @Path("/usuario/login")
    public void login(Usuario usuario) throws Exception {
        Usuario carregado = dao.carrega(usuario);
        if (carregado == null) {
            validator.add(new ValidationMessage("Login e/ou senha inválidos", "usuario.login"));
        }
        validator.onErrorUse(page()).of(UsuarioController.class).loginForm();
        usuarioWeb.login(carregado);
        result.redirectTo(AlunoController.class).formulario();
    }

    @Path("/usuario/logout")
    public void logout() {
        usuarioWeb.logout();
        result.redirectTo(UsuarioController.class).loginForm();
    }
}
no meu usuário controller:
@Get @Path("/usuario/todos")
    public List&lt;Usuario&gt; lista(){
        return dao.listaTudo();
    }
para implementar isto:
package br.com.restrictrex.project.controller;

import br.com.bronx.vraptor.restrictrex.annotation.LoggedIn;
import br.com.bronx.vraptor.restrictrex.annotation.Roles;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Resource;
import br.com.restrictrex.project.model.Usuario;
import br.com.restrictrex.project.session.UsuarioLogado;

@Resource
public class UsuarioController {

    private final UsuarioLogado usuarioLogado;
    public UsuarioController(UsuarioLogado usuarioLogado) {
        this.usuarioLogado = usuarioLogado;
    }
        public void login(Usuario usuario) {
        this.usuarioLogado.efetuaLogin(usuario);
    }
    
    @LoggedIn
    @Roles(roles = {"admin"})
    @Path("/test1")
    public void test1() {
    }
    
    @LoggedIn
    @Roles(roles = {"admin", "moderador"})
    @Path("/test2")
    public void test2() {
    }
    
    @LoggedIn
    @Roles(roles = {"admin", "moderador", "usuario"})
    @Path("/test3")
    public void test3() {
    }
    
    @LoggedIn
    @Roles(roles = {"moderador"})
    @Path("/test4")
    public void test4() {
    }
    
    @LoggedIn
    @Roles(roles = {"moderador", "usuario"})
    @Path("/test5")
    public void test5() {
    }
    
    @LoggedIn
    @Roles(roles = {"usuario"})
    @Path("/test6")
    public void test6() {
    }
}
C

Bom, gostei muito da idéia dessa contribuição, deixa de forma simples o controle de acesso, estou tentando implementar mas ao acessar minha URL: [url]http://localhost:8080/BMWEB/consultor/index[/url] está ocorrendo o erro:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accessControllerInterceptor' defined in file [D:\TCC\vraptor-blank-project-3.1.1\build\web\WEB-INF\classes\br\bmweb\intercepetor\AccessControllerInterceptor.class]: Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker]: : No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:698)
	org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:328)
	org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:385)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:375)
	org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1069)
	org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:221)
	br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:244)
	br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:59)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:32)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:30)
	com.google.common.collect.Lists$TransformingRandomAccessList.get(Lists.java:431)
	java.util.AbstractList$Itr.next(AbstractList.java:345)
	com.google.common.collect.Iterators$7.computeNext(Iterators.java:602)
	com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:135)
	com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:130)
	com.google.common.collect.Lists.newArrayList(Lists.java:131)
	com.google.common.collect.Collections2$FilteredCollection.toArray(Collections2.java:219)
	br.com.caelum.vraptor.interceptor.DefaultInterceptorRegistry.interceptorsFor(DefaultInterceptorRegistry.java:50)
	br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:42)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:70)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:56)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
root cause

org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:896)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:765)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:680)
	org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:771)
	org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:691)
	org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:328)
	org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:385)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:375)
	org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1069)
	org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:221)
	br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:244)
	br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:59)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:32)
	br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:30)
	com.google.common.collect.Lists$TransformingRandomAccessList.get(Lists.java:431)
	java.util.AbstractList$Itr.next(AbstractList.java:345)
	com.google.common.collect.Iterators$7.computeNext(Iterators.java:602)
	com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:135)
	com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:130)
	com.google.common.collect.Lists.newArrayList(Lists.java:131)
	com.google.common.collect.Collections2$FilteredCollection.toArray(Collections2.java:219)
	br.com.caelum.vraptor.interceptor.DefaultInterceptorRegistry.interceptorsFor(DefaultInterceptorRegistry.java:50)
	br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:42)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:70)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:56)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
As classes estão assim: ConsultorController:
@LoggedIn
    @AccessDenied(loginPage="../cliente/Tela_Login", accessDeniedPage="../cliente/Tela_Login")
    public void index() {
    }
LoginControl:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.bmweb.controller;

import br.com.bronx.accesscontrol.interfaces.Login;
import br.com.bronx.accesscontrol.interfaces.Profile;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.SessionScoped;

/**
 *
 * @author cristiano
 */
@Component
@SessionScoped
public class LoginControl implements Login{

	private boolean loggedIn;
	private Profile profile;

	@Override
	public boolean isLoggedIn() {
		return this.loggedIn;
	}

	@Override
	public void setLoggedIn(boolean loggedIn) {
		this.loggedIn = loggedIn;
	}

	@Override
	public Profile getProfile() {
		return this.profile;
	}

	@Override
	public void setProfile(Profile profile) {
		this.profile = profile;
	}

}
AccessControlInterceptor:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.bmweb.intercepetor;

import br.bmweb.bean.Usuario;
import br.bmweb.bean.UsuarioWeb;
import br.bmweb.controller.LoginControl;
import br.com.bronx.accesscontrol.exception.RestrictionAnnotationException;
import br.com.bronx.accesscontrol.interfaces.Login;
import br.com.bronx.accesscontrol.restriction.RestrictionChecker;
import br.com.bronx.accesscontrol.restriction.RestrictionResult;
import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.view.Results;

/**
 *
 * @author cristiano
 */
@Intercepts
public class AccessControllerInterceptor implements Interceptor {

	private RestrictionChecker restrictionChecker;
	private Result result;
	private Login login;

	public AccessControllerInterceptor(LoginControl login, RestrictionChecker restrictionChecker, Result result){
		this.login = login;
		this.restrictionChecker = restrictionChecker;
		this.result = result;
	}

	@Override
	public boolean accepts(ResourceMethod method) {
		return this.restrictionChecker.hasRestriction(method.getMethod());
	}


	public void intercept(InterceptorStack stack, ResourceMethod resourceMethod,
			Object resourceInstance) throws InterceptionException {
		RestrictionResult restrictionResult;
		try {
			restrictionResult = restrictionChecker.checkRestrictions(resourceMethod.getMethod(), login);
		} catch (RestrictionAnnotationException e) {
			throw new InterceptionException(e);
		}
		if (restrictionResult.isRestricted()){
			result.use(Results.page()).redirect(restrictionResult.getDestination());
		} else {
			stack.next(resourceMethod, resourceInstance);
		}
	}
}
Meu web.xml tá assim:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>BMWEB</display-name>
  <filter>
    <filter-name>vraptor</filter-name>
    <filter-class>br.com.caelum.vraptor.VRaptor</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>vraptor</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>
  <context-param>
    <param-name>br.com.caelum.vraptor.packages</param-name>
    <param-value>br.com.bronx</param-value>
</context-param>
</web-app>
No console mostra isto:
16:12:19,646  INFO [VRaptor             ] VRaptor 3.1.1 successfuly initialized
16:12:33,594 DEBUG [VRaptor             ] VRaptor received a new request
16:12:33,688 DEBUG [DefaultRequestExecution] executing stack  DefaultRequestExecution
16:12:33,759 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor ResourceLookupInterceptor
16:12:33,759 DEBUG [DefaultResourceTranslator] trying to access /consultor/index
16:12:33,797 DEBUG [DefaultResourceTranslator] found resource [DefaultResourceMethod: ConsultorController.indexConsultorController.index()]
16:12:33,827 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor FlashInterceptor
16:12:33,835 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor InterceptorListPriorToExecutionExtractor
Tá faltando algo?
J

aqui tem um pronto e mais simples !
http://www.wbotelhos.com/

A

Gostei da ideia do controle de acesso. mas em meio a tantas mensagens, não consegui identificar o que está valendo.

Percebi que foi prometido um tutorial (ou resumo) mas não vi link… alguem sabe informar se foi feito?

tfa

A

O Bronx me passou o arquivo atualizado. O nome agora é SACI.

Vou elaborar um passo a passo e fazer a postagem amanhã

J

posta aqui vai ajudar !

L

Alguém sabe se o tutorial já foi postado?

J

não foi nao !

A

segue arquivo SACI atualizado e classes modelo

A

Outro arquivo

A

Configuração Web.xml

&lt;context-param&gt;
    &lt;param-name&gt;br.com.caelum.vraptor.packages&lt;/param-name&gt;
    &lt;param-value&gt;
            br.com.caelum.vraptor.converter.l10n,
            br.com.caelum.vraptor.util.hibernate,
            br.com.bronx.vraptor.saci                                          &lt;!-- ESTA LINHA QUE É NECESSÁRIA --&gt;
        &lt;/param-value&gt;
  &lt;/context-param&gt;

transcrevo abaixo as orientações que o Bronx me passou:

o AccessControllerInterceptor
entao, olha o construtor dele

public AccessControllerInterceptor(UsuarioCorrente usuarioCorrente, RestrictionChecker restrictionChecker,
                                                       Result result){

ele recebe um Result que vc já conhece
recebe um RestrictionChecker. Esse RestrictionChecker está no jar que te mandei (isto é, Saci)
é essa classe que verifica se há ou não restrições então por isso precisamos dela e
por último a classe UsuarioCorrente

ela é uma implementação simples de um componente SessionScoped que guarda na sessão o usuário logado no sistema então quando vc a recebe, vc está recebendo o usuário logado
mas isso não tem nenhuma relação com o restritor, vc pode fazer diferente.

Então se vc olhar a UsuarioCorrente verá que ele simplesmente guarda o usuário na sessão nada d+

Faça do jeito que for conveniente…essas classes eu uso no projeto de teste do restritor, então estão bem simples hehe

Voltemos ao interceptor o método accepts dele o objeto restrictionChecker simplesmente verifica se o recurso (classe/método) que está sendo acessado possui ou não restrições
se não possuir, não há motivo para verificar se o usuário pode ou não acessá-la

Caso haja restrição, ele vai interceptar novamente esse interceptor é só uma implementação vc pode alterá-lo de acordo com as necessidades por exemplo, se quiser que ele verifique as restrições em todas as requisições, só retornar true no accept
e por aí vai

apenas pra revisar:

  1. configurar web.xml
  2. vc tem que ter um perfil como vc vai obter esse perfil, isso já é problema seu
    essa classe usuariocorrente que fiz foi a minha implementação para fazer os testes aqui
    confesso que nos sistemas aqui fazemos algo parecido, mas não é uma regra…vc pode buscar o perfil de onde quiser, sacou?

aí no método intercept
vc invoca o método checkRestrictions da classe restrictionChecker
vc passa como parâmetro o método em questão, e o tal do perfil do usuário
que nada mais é que uma implementação da interface Profile que está no jar
right?

as anotações de restriões foram alteradas?

As anotações
@LoginPage
essa vc usa no método da página de login o método nao pode receber parâmetros (taí uma futura melhoria) mas não confunda com o método referente ao action do form é só o método que mostra a página de login mesmo

@AccessDeniedPage
essa vc coloca sobre o método da página onde vc quer que o usuário seja redirecionado, caso tente acessar um recurso sem possuir as credenciais necessárias
bom, agora sim, acabaram-se as configurações

essas informações são checadas durante o startup da aplicação

então agora, é começar a colocar as restrições nos recursos

@LoggedIn -> somente usuários logados

@Roles(roles = {…}) -> somente usuários que possuírem todas as roles (ou apenas uma dentre as informadas - vai da configuração)

@AccessLevel ->> utilizado para restrições hierárquicas

tipo @AccessLevel(minimumAccessLevel = 4)

logo, um usuário com nível de acesso 3 não conseguiria acessar o recurso mas usuários com níveis 4, 5, 6 etc conseguiriam esse é mais chato, mas confesso que nunca precisei utilizá-lo

e onde colocar o nivel de acesso?

justamente no perfil

vc pode fazer do jeito que quiser aí o importante é a interface, não a implementação vc só tem que passar um Profile para o checkRestrictions

RESUMO:

  1. configurar web.xml
  2. ter uma lista de perfis em algum lugar
  3. definir pagina de erro e pagina de login (no controller)
  4. anotar os metodos com as "restrições"

só esse "ter uma lista de perfis" que ficou meio vago
eu trocaria por "implementar a interface Profile"

tem outras duas anotações importantes
@OnAccessDenial(forceHttp403 = true)
ela indica que, em caso de acesso negado, ao invés de redirecionar para a página que vc anotou com @AccessDenied, ele simplesmente retorna o código http 403
isso é muito útil em chamadas ajax

@CascadeRestrictions(cascade = false)
é para alterar o comportamento do restritor ele funciona assim vc pode utilizar as restrições na classe e nos métodos o comportamento padrão dele é o seguinte: tem que satisfazer TODAS as restrições - as da classe e do método por exemplo

@Resource
@Roles(roles = "professor")
class ExemploController {

public void areaProfessor(){}

}

nesse caso, somente professores conseguem acessar o método areaProfessor mas
pode ter a seguinte situação

@Resource
@Roles(roles = "professor")
class ExemploController {

public void areaProfessor(){}

public void areaSomenteProfessoresDoutores(){}
}

além da área de professor, tem uma área que só pode ser acessada por doutores aqui já dá pra ver que vai dar problema pq do jeito que está um professor consegue acessar os dois métodos pois a única restrição é essa: que seja professor (role = "professor")

logo, temos que restringir mais ainda …

então tem que anotar o metodo? isso!

@Resource
@Roles(roles = "professor")
class ExemploController {

public void areaProfessor(){}

@Roles(roles = "doutor")
public void areaSomenteProfessoresDoutores(){}
}

neste caso qual a anotação mandatoria (que prevalece)?

então esse é o ponto as duas prevalecem!o cara vai ter que ser doutor E professor

entendi. há uma combinação (E), ok …
isso caso queira mudar esse comportamento aí entra aquela anotação acima
[code
@CascadeRestrictions(cascade = false)
[/code]

se quiser que seja acessado por qualquer doutor…
isso

ficaria assim

@Resource
@Roles(roles = "professor")
class ExemploController {

public void areaProfessor(){}

@Roles(roles = "doutor")
@CascadeRestrictions(cascade = false)
public void areaSomenteProfessoresDoutores(){}
}

agora, basta ele ser doutor pq agora o que prevalece é a restrição do método
só pra concluir suponhamos que há tbm, no mesmo controller, uma área onde somente MESTRES possam acessar

@Resource
@Roles(roles = "professor")
class ExemploController {

public void areaProfessor(){}

@Roles(roles = "doutor")
@CascadeRestrictions(cascade = false)
public void areaSomenteDoutores(){}

@Roles(roles = "mestre")
@CascadeRestrictions(cascade = false)
public void areaSomenteMestres(){}
}

certo?
sim.
podemos melhorar isso olha agora

@Resource
@Roles(roles = "professor")
@CascadeRestrictions(cascade = false)
class ExemploController {

public void areaProfessor(){}

@Roles(roles = "doutor")
public void areaSomenteDoutores(){}

@Roles(roles = "mestre")
public void areaSomenteMestres(){}

//outros métodos/recursos
}

o que eu fiz foi simplesmente tirar a anotação @Cascade… de cada método e coloquei somente uma direto na classe isso significa que agora, para qualquer método que possuir restrição específica, o restritor não desconsidera a restrição que está na classe

e nos métodos que não possuírem restrições específicas, use a restrição da classe

bem, é isso

----------- FIM da conversa com o Bronks

B

Pq sempre escrevem “BronKS”?? hehehe

Piadas à parte, acho que ficou claro como fazer a parada funcionar!
Só falta eu colocar no git…

J

Bronx precida de um Demo !

Posta la !

R

Muito obrigado pela sua contribuição, será de grande ajuda para mim…

No meu caso os usuarios que não tem acesso a determinadas partes da aplicação não poderão nem ver os links das páginas… Alguém pode me ajudar?

B

Senhores, fiquem atentos às novidades: http://www.guj.com.br/java/238655-saci---simple-access-controller-vraptor-3 :wink:

A

Olá Boa tarde a Todos,
Galera estou com um pequeno problema, a alguns dias comecei a trabalhar com o VRaptor e antes de encontrar o projeto do Bronx estava criando os Interceptors e
trabalhando com o login de usuário através de Anotações simples que criei para dizer oque era publico e o que exigia login.

Achei o projeto do Bronx muito legal e comecei a implementar com ele aqui durante a tentativa de execução obtive o seguinte erro:

13:59:38,210 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/doku].[default]] (http--0.0.0.0-80-1) Servlet.service() for servlet default threw exception: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accessControllerInterceptor': Unsatisfied dependency expressed through constructor argument with index 1 of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker]: : No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:730) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:196) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1003) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:907) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:329) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43) [org.springframework.web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:263) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083) [org.springframework.context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:86) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:47) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58) [vraptor-3.4.1.jar:]
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88) [vraptor-3.4.1.jar:]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
	at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
	at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
	at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_29]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:920) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:795) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723) [org.springframework.beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
	... 46 more

Será que alguem poderia me ajudar não estou conseguindo perceber a causa da exception

L

No matching bean of type [br.com.bronx.accesscontrol.restriction.RestrictionChecker]

talvez vc precise criar uma implementação dessa interface e anotar com @Component.

A

Muito obrigado,
Resolveu!!

A

Bom aproveitando, obtive outro erro
na verdade quando eu coloco a anotação

ele simplesmente não direciona nem para a tela de login nem para 403

continua dando acesso a pagina como se não houvesse problema nenhum.

para demonstrar como esta vide o código abaixo:

//Trecho do classe Resource que possui o direcionamento da página principal
	@LoggedIn
	@Get("/")
	public void index(){
		
	}

Na minha pagina quando colocamos aplicacao/

ele direciona para este metodo

Então suspeitei da minha implementação de Profile que esta assim

@Override
	public boolean isLoggedIn() {
		if(this.usuario != null)		
			return true;
		else
			return false;
	}

Não sei porque ele não direciona para o login,
ou porque não da pelo menos um erro

B

Olá, aquila.venancio!

O RestrictionChecker já é um componente devidamente configurado.

Qual versão do jar você está utilizando? Pois desde a última versão (de maio do ano passado), você sequer precisa criar um interceptor. Já tem tudo pronto lá! :smiley:

Acho que o problema está na configuração. Nos mostre como está o seu web.xml!
Aqui tem as explicações detalhadas de como configurar tudo certinho!

A

Pois é Bronx,
eu vi a data dos post mas comecei mexer com o VRaptor agora e pesquisando sobre controle de acesso encontrei o seu projeto.
Estava utilizando a versão antes de ter nome como primeiro jar quando li as 12 páginas de discursão do forum encontrei seu link indicando a versão atual SACI
só que estava utilziando a versão mais antiga logo a sugestão do Lucas Cavalcanti veio acalhar.

Agora que li a documentação do seu pequeno framework de segurança estou conseguindo caminhar com velocidade um pouco maior,
porem volta e meia aparece uns exception meio tensos aqui.
Mas a informação esta bem legal esta dando para descobrir a causa.

de qualquer forma ai vai o xml.

<filter>
		<filter-name>vraptor</filter-name>
		<filter-class>br.com.caelum.vraptor.VRaptor</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>vraptor</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>REQUEST</dispatcher>
	</filter-mapping>

	<context-param>
		<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
		<param-value>messages</param-value>
	</context-param>

	<context-param>

		<param-name>br.com.caelum.vraptor.packages</param-name>

		<param-value> br.com.bronx.vraptor.saci</param-value>

	</context-param>
Criado 16 de janeiro de 2010
Ultima resposta 30 de jul. de 2012
Respostas 175
Participantes 26