Spring Security - HTTP Status 403 - Access is denied

Ola pessoal estou acompanhando um livro de programação web, criei a parte de segurança do sistema com Spring Security, porem quando eu vou realizar o login, com o ROLE_USUARIO
consigo acessar normal, porem quando eu entro com usuario cadastrado com o ROLE_ADMINISTRADOR, recebo a seguinte mensagem.:

HTTP Status 403 - Access is denied

type Status report

message Access is denied

description Access to the specified resource (Access is denied) has been forbidden.
Apache Tomcat/7.0.22

fiz a seguinte query para ter realmente certeza, que esse usuario tinha papel de administrador

SELECT login, permissao FROM usuario, usuario_permissao WHERE codigo = usuario and login = 'lunartecnologia';

e o resultado foi :

login: lunartecnologia | permissao: ROLE_ADMINISTRADOR

porem estou recebendo aquela mensagem de acesso negado.

aqui estar meu applicationContext-Security:

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


    <form-login login-page="/publico/login.jsf"
            always-use-default-target="true" default-target-url="/restrito/principal.jsf"
            authentication-failure-url="/publico/login.jsf?login_error=1" />
    <logout/>
</http>
<authentication-manager>
    <authentication-provider>
        
        <jdbc-user-service data-source-ref="financeiroDataSource"
                authorities-by-username-query="SELECT u.login, p.permissao FROM usuario u, usuario_permissao p WHERE u.codigo = p.usuario AND u.login = ?"
                users-by-username-query="SELECT login, senha, ativo FROM usuario WHERE login = ?" />
    </authentication-provider>
</authentication-manager>

</b:beans>[/code]

alguem sabe como resolver?

tenta assim:

e o mesmo pro usuário.

kcobainnn, não chega nem a executar da erro de compilação.

qual o erro?

Log do apache

11/07/2012 14:23:56 org.apache.catalina.core.ApplicationContext log INFO: Initializing Spring root WebApplicationContext 11/07/2012 14:23:56 org.apache.catalina.core.StandardContext listenerStart SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Unsupported configuration attributes: [hasRole('ROLE_ADMINISTRADOR')] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1401) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:512) 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 org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:261) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:192) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723) at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226) at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907) at java.lang.Thread.run(Thread.java:619) Caused by: java.lang.IllegalArgumentException: Unsupported configuration attributes: [hasRole('ROLE_ADMINISTRADOR')] at org.springframework.security.access.intercept.AbstractSecurityInterceptor.afterPropertiesSet(AbstractSecurityInterceptor.java:154) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1460) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1398) ... 20 more 11/07/2012 14:23:56 org.apache.catalina.core.ApplicationContext log INFO: Closing Spring root WebApplicationContext

Já parei pra analizar o código fonte, e não vejo motivo de estar recebendo Access is denied, já que o usuario cadastrado, tem ROLE_ADMINISTRADOR!!!

o cara que tem ROLE_ADMINISTRADOR só pode acessar páginas permitidas p/ ele, assim como o ROLE_USUARIO, apenas páginas que são permitidas p/ ele.
se você quiser com que o administrador acesse todas as páginas, você teve incluir a role na lista de roles dele e não só a ROLE_ADMINISTRADOR.

Insirir o role na lista dele ?
como assim ?
Estou seguindo o livro, e ainda que o usuario tinha papel de administrador eu coloquei!!

seu Usuário provavelmente tem uma lista de Roles, então… adicione no banco a permissão ROLE_USUARIO pro seu usuário do banco, que já tem a ROLE_ADMINISTRADOR.

ah entendi, você tá falando pra usuario que já tem papel de administrador, eu insirir também o papel de usuario?

Será que desta forma resolveria ?
estou atualizando o meu usuario que possui permissão de administador

update usuario_permissao set permissao = 'ROLE_USUARIO, ROLE_ADMINISTRADOR' where usuario = 12

você tem que entender, que o seu usuário pode ter N permissões.

o relacionamento é ManyToMany, você tem que ter uma tabela usuarios, uma tabela roles, e outra usuario_roles, que vai contar um user_id e o role_id, desse modo você vai poder adicionar mais de 1 permissão por usuário.

por exemplo:

usuario :

id - 1
nome - joao

roles :

id - 1
permissão: usuario

id - 2
permissão: administrador

user_roles

usuario_id : 1
role_id : 1

usuario_id : 1
role_id : 2

dessa forma, você está falando que o usuário joao tem 2 permissões.

não sei se eu fui muito claro, mas acho que do modo que você está fazendo, você está colocando uma permissão por usuário.

kcobainnn, entendi perfeitamente o que você estar querendo dizer. E é ezatamente isso que estar acontecendo na minha aplicação.
Quando eu cadastro um usuário, ele ganha permissões de ROLE_USUARIO.
o problema é que eu não possa adicionar mais de uma permissão aquele usuario.
O livro diz o seguinte

[quote]
A tabela usuario_permissao será criada automaticamente a partir do mapeamento na classe Usuario[/quote]

aqui é o trecho do mapeamento na classe Usuario

@ElementCollection(targetClass = String.class) @JoinTable( name="usuario_permissao", uniqueConstraints = {@UniqueConstraint(columnNames = {"usuario","permissao"})}, joinColumns = @JoinColumn(name = "usuario")) @Column(name = "permissao", length=50)

Porem eu não conseguir criar essa tabela com esse mapeamento.
Aí eu decidi criar a tabela manualmente, conforme a seguir:

create table usuario_permissao (usuario int(11) not null auto_increment, permissao varchar(255) not null);

Como o meu campo usuario é chave primária, eu não consigo atribuir mais de uma permissão ao usuário.
Tentei criar a tabela sem nenhuma chave primaria porem é impossivel!

Sabe como resolver?

vou dar um exemplo de como eu costumo fazer.

package com.entities;

import java.util.Collection;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
@Table(name="users")
public class User extends AbstractEntity implements UserDetails {
	private static final long serialVersionUID = 4366647536005304065L;

	private String login;
	private String password;
	
	private List<Role> roles;
	
	@Column(unique=true)
	public String getLogin() {
		return login;
	}
	
	public void setLogin(String login) {
		this.login = login;
	}
	
	public String getPassword() {
		return password;
	}
	
	public void setPassword(String password) {
		this.password = password;
	}
	
	@ManyToMany(fetch=FetchType.EAGER)
	@JoinTable(name = "user_roles", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_id") })
	public List<Role> getRoles() {
		return roles;
	}
	
	public void setRoles(List<Role> roles) {
		this.roles = roles;
	}

	@Transient
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return roles;
	}

	@Transient
	@Override
	public String getUsername() {
		return login;
	}

	@Transient
	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Transient
	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Transient
	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Transient
	@Override
	public boolean isEnabled() {
		return true;
	}
}


package com.entities;

import java.beans.Transient;

import javax.persistence.Entity;
import javax.persistence.Table;

import org.springframework.security.core.GrantedAuthority;

@Entity
@Table(name="roles")
public class Role extends AbstractEntity implements GrantedAuthority{
	private static final long serialVersionUID = -4554663931743562798L;

	private String description;
	private String role;
	
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	
	@Override
	@Transient
	public String getAuthority() {
		return role;
	}
	
	@Transient
	public void setAuthority(String authority) {
		this.role = authority;
	}
}

o que você deve fazer é inserir o seu usuário, suas roles e fazer o ligamento na tabela user_roles.

Entendi o que você quiz dizer, o problema é que se eu tentar fazer assim, possa ser que nos próximo capitulos, eu venha a ter problema
com a minha classe usuario.
Eu queria criar daquela maneira, que o livro ensina!
Porem não estou conseguindo.

Vamos descomplicar.

Apenas vai na tabela “usuario_permissao” que foi criada no banco de dados “financeiro” e você irá verificar que o código do usuário que foi previamente cadastrado está como ROLE_USUARIO, então blz, agora utilizando o seu SGBD (Sistema Gerenciador de Banco de Dados) adicione para o mesmo código cadastrado a permissão ROLE_ADMINISTRADOR. Ficando da seguinte forma:

USUARIO----------PERMISSAO
1 ROLE_USUARIO
1 ROLE_ADMINISTRADOR

Dessa forma ele terá acesso tanto aos locais disponibilizados apenas para USUARIOS quanto para os de ADMINISTRADOR. Obrigatoriamente para esse sistema todo ADMINISTRADOR tem que ser um USUARIO.