Spring Security - HTTP Status 403 - Access is denied

17 respostas
J

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.

17 Respostas

J

aqui estar meu applicationContext-Security:

<?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">    
    <http>     
        <intercept-url pattern="/admin/**" access="ROLE_ADMINISTRADOR" />
        <intercept-url pattern="/restrito/**" access="ROLE_USUARIO" />
  
        <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>
J

alguem sabe como resolver?

K

tenta assim:

e o mesmo pro usuário.

J

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

K

qual o erro?

J

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

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

K

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.

J

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

K

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.

J

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

J

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
K

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.

J

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


A tabela usuario_permissao será criada automaticamente a partir do mapeamento na classe Usuario

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?

K

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.

J

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.

A

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.

Criado 11 de julho de 2012
Ultima resposta 16 de jan. de 2013
Respostas 17
Participantes 3