Erro de privilégio com Oracle + JPA

14 respostas
Luiz_Gustavo

Galera, estou com o seguinte problema:

Alguém sabe se há alguma configuração (no banco ou na aplicação) para que a JPA reconheça, a partir da conexão, quais campos ela pode alterar em cada tabela, de acordo com os privilégios de acesso dos usuários?

Contexto:

Evoluímos uma aplicação que usa um banco de dados Oracle. Nessa aplicação, cada usuário cadastrado tem um usuário equivalente no banco, e existem vários perfis. Ao se logar, o usuário passa a acessar as tabelas de acordo com os privilégios que tem no banco (não é feito controle na aplicação). Acontece que no domínio em que esta aplicação estava antes, isso é automático.
Já no novo domínio, uma aplicação web em Java, com JPA, estou com problemas de privilégio. Para conseguir diferenciar os perfis no acesso ao banco, pegamos os dados do usuário no momento do login, e criamos um EntityManagerFactory específico para ele, que criará conexões para o perfil dele. Até aqui tudo bem.
O problema é que em algumas telas, determinado usuário só pode alterar alguns campos da tabela, mas o merge não está reconhecendo que apenas alguns campos (os permitidos) foram atualizados. Como consequência o update é dados em outros campos que o usuário não tem privilégio.

Agradeço a quem puder ajudar.

Abraço!

14 Respostas

augusto_ab

Esse problema está tirando o nosso sono…

Ninguém usa esse tipo validação de usuários no banco de dados ?!? Geralmente como vocês fazem ?!? Isso fica p/ DBA ?? É tratado na aplicação ?!

Se alguém puder dar uma força…

Luiz_Gustavo

Como informação adicional, estamos usando:

JBoss 5.0.1
Oracle 9i

Existe um datasource configurado no JBoss, que é usado pelo persistence.xml, mas a conexão obtida por ele apenas faz a validação do usuário. Como comentei acima, a partir do momento que o usuário se loga, é criado um EntiryManagerFactory para ele, com dados específicos, e esse EMF é colocado na sessão, para ser usado sempre que um EntityManager for necessário.
Precisaríamos de alguma forma informar ao JPA que analisasse o que pode ser alterado pelo perfil do usuário da conexão?

Alguma luz?

Lavieri

é complicado... o fato é q o JPA tem sim, um modo de fazer isso... mas ai vc tem q intervir no mapeamento a depender de que usuario logar o.O

por exemplo

public class Pessoa implements Serializable {
      private @Id @GeneratedValue Integer id;
      private @Column(name="nome", 
                       insertable=User.getInsertableAcess("Pessoa.nome"), 
                       updatable=User.getUpdatableAcess("Pessoa.nome")) 
                 nome;

      //etc etc etc

//o métodos User.getInsertableAcess("Pessoa.nome")
// devem retornar true / false a depender do acesso do usuario corrente
//para inserir a propriedade "nome" da entidade "Pessoa"
}

o problema esta que... os atributos, insertable, e updatable, so aceitam valores estaticos, tem q ser acessivel estaticamente, para que a Factory carregue quando estiver sendo montada....

quando insertable e updatable são falsos.... o Hibernate (ou outro framework de persistencia) não os tenta modificar, quase cereteza que nem aparece na SQL q o hibernate monta... se quiser ter certeza, ligue o show_sql, e set o insertable e updatable para false, e de um marge numa entidade q vc vê...

o seu problema vai ser colocar esse monte de insertable e updatable, para definir as propriedades do campo o.O

Luiz_Gustavo

Digamos que eu tenha uns 15 perfis diferentes… o.O

Mas deixa eu ver se entendi… a JPA já consegue identificar automaticamente qual o usuário da conexão, bastaria eu criar esses atributos? Ex:

public class Pessoa implements Serializable {  
      private @Id @GeneratedValue Integer id;  
      private @Column(name="nome",   
                       insertable=User.getInsertableAcess("Pessoa.nome"),   
                       updatable=User.getUpdatableAcess("Pessoa.nome"))   
                 nome;

private @Column(name="telefone",   
                       insertable=User.getInsertableAcess("Pessoa.telefone"),   
                       updatable=User.getUpdatableAcess("Pessoa.telefone"))   
                 telefone;

private @Column(name="peso",   
                       insertable=User.getInsertableAcess("Pessoa.peso"),   
                       updatable=User.getUpdatableAcess("Pessoa.peso"))   
                 peso;

private @Column(name="altura",   
                       insertable=User.getInsertableAcess("Pessoa.altura"),   
                       updatable=User.getUpdatableAcess("Pessoa.altura"))   
                 altura;

Ou esse User.get*Access é algo que EU teria que criar? Se for assim, eu poderia criar (ainda que dê trabalho) um arquivo properties de mapeamento desses privilégios para cada perfil:

CONSULTA_UPDATE_.properties

Pessoa.nome = false
Pessoa.telefone = false
Pessoa.altura = true
Pessoa.peso = true

CONSULTA_INSERT_.properties

Pessoa.nome = false
Pessoa.telefone = false
Pessoa.altura = false
Pessoa.peso = false

ADMINISTRACAO_INSERT_.properties

GERENCIA_INSERT_.properties

ADMINISTRACAO_UPDATE_.properties

GERENCIA_UPDATE_.properties

Criaria esse objeto User, que tem o nome do Role do usuário logado: GERENCIA, ADMINISTRACAO, CONSULTA, e cada método get*access usaria um resourceBundle diferente, que acessa os properties em seus padrões ROLE_PRIVILEGIO_.properties.

Como eu crio o EntityManagerFactory logo após o login, já com alguns dados do usuário, eu poderia carregar essas informações dinamicamente e passar para o EMF, mas como eu poderia fazer isso? Alguma idéia?

Tô viajando? Ainda tô perdido!

Abraço, e obrigado pela resposta!

Lavieri

eu fui olhar… novamente, pq não tava na IDE… a ideia era essa… vi la, mas obrigatorimente tem q ser uma constante ali no campo insertable e updatable…

não pode ser um método =/

teria q fazer com constantes… ia ser um saco… ter zilhoes de constantes no seu projeto…

tenso =/

fazer algo como

public static final boolean I_PESSOA_NOME = User.getInsertableAcess("Pessoa.altura"); public static final boolean U_PESSOA_NOME = User.getUpdatableAcess("Pessoa.altura");

pra so ai

triste assim…

talvez exista outro modo =/ … sei q a proxima versão do hibernate via ter versionamento… e parece q nela so vai rolar update nos campos q forem modificados… não sei bem

Luiz_Gustavo

Acho que agora caiu a ficha!

Que triste isso =/

hehehe…

Já pensou:

ADMINISTRACAO_INSERT_PESSOA_NOME
ADMINISTRACAO_INSERT_PESSOA_TELEFONE

no padrão:

PERFIL_OPERACAO_TABELA_CAMPO

com uns 15 perfis, umas 70 tabelas… com uns 30 campos cada, em média

dá uma gastura…

o pior nisso tudo é que eu acho q nem assim daria, pois eu só poderia pegar dinamicamente o perfil do usuário ¬¬

vou ver o que consigo fazer por aqui.

Abraço e obrigado!

Lavieri

o unico modo que eu sei, de avisar para o mapeamento, que um campo não deve ser alterado ou inserido, é com essas tags, de insertable ou updatable, mais elas fazem parte da anotação, e portanto são fixas…

seguindo esse mesmo reciocinio, vc poderia ter varias entidades “Pessoa” por exemplo, uma para cada nivel de acesso, modifcando apenas o atributo insertable, ou updatable… mas isso daria um trabalho FDP… pensando q vc pode ter centenas de classes, e q isso multiplicaria pela quantidade de tipos de usuarios… alem de que, modificações no acesso, implicariam em modificações em varias classe o.O

Luiz_Gustavo

Se não me engano, configurações via xml sobrepõem as configurações por anotação.
Poderia criar um persistence.xml com os mapeamentos para cada perfil, seria mais simples que manter as classes, mas ainda assim… ô trabalho!
Teria que carregar o persistence.xml específico no momento do login do caboclo.

Grant em um campo = verificação em xml :shock:

Vamos ver o que se pode fazer.

Abraço!

Lavieri

Luiz_Gustavo:
Acho que agora caiu a ficha!

Que triste isso =/

hehehe…

Já pensou:

ADMINISTRACAO_INSERT_PESSOA_NOME
ADMINISTRACAO_INSERT_PESSOA_TELEFONE

no padrão:

PERFIL_OPERACAO_TABELA_CAMPO

com uns 15 perfis, umas 70 tabelas… com uns 30 campos cada, em média

dá uma gastura…

o pior nisso tudo é que eu acho q nem assim daria, pois eu só poderia pegar dinamicamente o perfil do usuário ¬¬

vou ver o que consigo fazer por aqui.

Abraço e obrigado!

o problema disso é q o seu Banco de dados, contem parte do dominio, ou seja, regras de dominio estão la no seu banco…
e o JPA, pelomenos não ate onde eu saiba, da suporte a inserir somente campos modificados… se isso ocorrece, bastaria não liberar alteração em campos não acessiveis a cada usuario, que nunca ia dar problema de privilegios no banco…

como seu usuario ta refletido no banoc, fica complicado mesmo

Luiz_Gustavo

pior ainda… alguns perfis não podem nem consultar determinados campos… e outros podem… :cry:

Lavieri

tem uma outra coisa q pode ser feito… vai ser um xute no ovo dos DBA… mas antes no deles q no seu… ^^

vc pode quebrar as tabelas em areas acessiveis… a cada perfil, e assim ficaria izi de mapear

Luiz_Gustavo

Lavieri:
tem uma outra coisa q pode ser feito… vai ser um xute no ovo dos DBA… mas antes no deles q no seu… ^^

vc pode quebrar as tabelas em areas acessiveis… a cada perfil, e assim ficaria izi de mapear

Acho pouco provável que possamos fazer isso… mas vou sugerir… hehehehe

Abraço!

Lavieri

Luiz_Gustavo:
Lavieri:
tem uma outra coisa q pode ser feito… vai ser um xute no ovo dos DBA… mas antes no deles q no seu… ^^

vc pode quebrar as tabelas em areas acessiveis… a cada perfil, e assim ficaria izi de mapear

Acho pouco provável que possamos fazer isso… mas vou sugerir… hehehehe

Abraço!

e vc no seu proprio mapeamento… pode vc mesmo, quebrar uma tabela, em varias entidades distinstas, menores… e interligar elas por meio de um único ID… da pra fazer isso… e assim so carrega na factory de acordo com o necessario ao perfil … mesmo a tabela continuando inalterável

T

Caras desculpem por entrar no forum e não colocar nenhuma informação, e que eu tenho que fazer um trabalho igual a esse de autenticação e autorização de usuário, e estou com problema para fazer o mapeamento de ralacionamento entre duas classes. Coloquei os codigos no link abaixo:

http://www.guj.com.br/posts/listByUser/107724.java

Por favor se puderem dar uma olhada e acoselhar algum…!!!

Gustavo…!!!

Criado 28 de abril de 2009
Ultima resposta 1 de mar. de 2010
Respostas 14
Participantes 4