Olá a todos amigos do forum. Estou definindo padrões para o desenvolvimento de um software que será migrado de Delphi para Java. No sistema em Delphi as permissões dos usuários são definidas no campos de um formulário, por exemplo, num sistema de consulta de clientes, eu posso definir quais campos um vendedor pode ver, quais um gerente pode ver, etc. No sistema em Java deverá possuir a mesma funcionalidade, ai é que está o problema, se eu, no momento de criar a interface gráfica, verificar componente por componente se o usuário ter permissão de vê-lo ou não acho que o sistema não terá boa performance.
Vocês tem alguma sugestão do que pode ser feito para fazer estas verificações de permissão mantendo a boa performance do sistema?
Pode dar mais um detalhe , é separado por componentes ou por campos ?
Por exemplo você pode fazer um JPanel com dados pra exibir no caso
de ser o gerente , senao apenas mostra os campos em comum…
Você vai ter que construir um “mini-framework” pra fazer isso e o pessoal
utilizar , nao é tao complicado tendo um bom conhecimento e sabendo
o que realmente deve ser feito…
Agora se o sistema for controlado “campo a campo” acho que optar
por uma solucao web é um caso a ser analisado , há muitos frameworks
que oferecem isso pra você prontinho , ( aka , mentawai , jsf , etc…)
Bom nada que um bom papo nao resolva qualquer duvida posta ae…
Boa sorte! :thumbup:
rapaz, perto do que eu estou para usar, seu problema pode ser na realidade uma solução, uma vez q eu vou ter que ver a mesma coisa.
por exemplo, se vc quiser fazer o componente literalmente desaparecer da tela se o usuário não puder mexer naquilo, é recomendável pensar na reestruturação de leiaute, etc. Mas se deixar disabled for opção, uma classe abstrata que 1- tenha uma implementação genérica de campos ou 2- obrigue cada janela a possuir uma certa implementação pode ser útil.
No meu caso, cada usuário tem uma “chave de acesso” (eh um número) e dependendo deste valor certas telas podem ou não serem vistas. mas aí se vc quiser alterações dinâmicas nos forms, bom, a coisa muda um pouco. nesse caso não somente as janelas, mas sim cada campinho, ao ser criado tem que ter uma “contra-chave” pra vc verificar se pode ou não isso ou aquilo.
no meu decidi pela simplicidade e estou usando números primos para definir os níveis de acesso. se, por exemplo, um usuário puder ter aceso a dois níveis distintos de segurança a chave deste cidadão é a multiplicação dos dois primos que representam tal funcionalidade.
se servir pra mim certamente postarei as dificuldades e alegrias de uso, blza?
Eu optei pelo desenvolvimento de um pequeno Framework, visto que ele poderá ser facilmente utilizado, posteriormente, em outros projetos, sem contar que posso disponibilizá-lo como software livre.
Estou seguindo a seguinte idéia: tenho uma classe que herda JFrame e esta possui um método que verifica os componentes anotados para efetuar a validação. O problema que estou enfrentando parece ser simples, mas num pensei em nenhuma solução eficiente, somente em uma básica.
Ao buscar o Field, via reflection, eu preciso convertê-lo para sua classe padrão para definir suas propriedades, como posso fazer isto de maneira performática?
Com isto poderia tornar o código mais eficiente? Me desculpe, mas não conseguir ver aonde você deseja chegar.
Poderia me dar mais alguns detalhes?
Para verificar as permissões do usuário, estarei fazendo, na minha classe que herda JFrame, um método abstrato que passa o nome do componente, ai nos meus formulários estará a implementação, visto que os objetos que armazenam as permissões somente estarão disponíveis lá. O que acha da solução? Alguma forma de melhorá-la?
[quote=RicardoLuis]Com isto poderia tornar o código mais eficiente? Me desculpe, mas não conseguir ver aonde você deseja chegar.
Poderia me dar mais alguns detalhes?
[/quote]
Uhmn , estou apenas dando a ideia de você criar seus proprios componentes
assim você pode agregar novas funcionalidades a eles nao tendo que usar
JTextField aqui e GujTextField ali… sacou ?
Boa solução! Pode ser que exista alguma melhor , pode ser que não.
Bom tambem aceite a sugestao do Bernardo Rafael e de uma olhada
nos padrões de projeto que ele indicou quem sabe nao esta em algum
deles uma solucao talvez mais simples pro seu problema ?
Bernardo Rafael poderia dar uma breve explicada como poderia ser
utilizado estes padrões sugeridos para solucionar o problema?
Que tal em vez de usar classes abstratas para "obrigar"
a implementacao de um metodo porque nao utiliza uma
interface ? É uma saida muito mais elegante.
uma classe abstrata que serviria de base para as outras classes, no caso de uma janela, teriamos uma classe com o nome de ‘JanelaBase.java’
public abstract class JanelaBase {
...
}
após isso, vc pode gerar quantas classes filhas de ‘JabelaBase’ quiser, por exemplo:
1º - JanelaVendedor
public class JanelaVendedor extends JanelaBase {
...
public JanelaVendedor(){
...
}
}
2º - JanelaGerente
public class JanelaGerente extends JanelaBase {
...
public JanelaGerente(){
...
}
}
a partir deste momento, vc já pode começar a fabricar as suas janelas:
JanelaFactory
public class JanelaFactory{
public static final int JANELA_TIPO_VENDEDOR = 1;
public static final int JANELA_TIPO_GERENTE = 2;
public static JanelaBase getJanela(int tipo_janela){
switch(tipo_janela){
case JANELA_TIPO_VENDEDOR: return new JanelaVendedor();
case JANELA_TIPO_GERENTE: return new JanelaGerente();
default: return null;
}
}
}
aqui, é necessário tomar cuidado de mandar um tipo que possa ser fabricado, ou criar um tipo default para quando o tipo de Janela não for especificado corretamente.
Uhmn , no *“comeco da Thread” eu perguntei ao RicardoLuis se ele teria
que fazer o controle “campo-a-campo” ou poderia ser feito atraves de JPanel’s ele me respondeu que gostaria de controlar “campo-a-campo”…
Pois o sistema é altamente personalizavel em Delphi e ele gostaria de
fazer isso em Java tambem , acredito que “desenhar” uma janela pra cada tipo de usuario não é a melhor solução…
É , se fosse facil nao tinha graça.
Valeu! :thumbup:
É exatamente este o X da questão, o sistema deve ser altamente personalizável, não podendo ser desenhada uma tela para cada permissão, visto que estas serão dinâmicas.
Eu devo fazer uma classe que implemente alguns métodos que determinarão os componentes da janela, porém esta classe será herdada pela minha janela, que já implementa JFrame. Realmente acho esta uma solução não muito elegante, mas ainda não pensei em uma maneira melhor de fazer. Seria possível fazer por composição? Alguma idéia?
Como dito acima, não pode ser feita uma tela para cada nível, é inviável. Em relação construir templates para as janelas o sistema será feito desta maneira, porém antes de tudo, o sistema de segurança já deve estar pronto.
No momento estou vendo uma forma de eliminar a depedência entre a classe base da segurança e JFrame, de forma a criar algo bem genérico, para ser utilizado como um framework.
Caso alguém tenha novas sugestões, eu agradeço.
Eu retirei a dependência de Jframe e adicionei a seguinte construtor:
public SwingSecurity(Window window) {
super();
this.window = window;
} /* Finaliza o construtor de objetos da classe SwingSecurity. */
Desta forma, é possível passar como parâmetro qualquer classe que herde de Window (JDialog, JFrame, etc). E em minha interface gráfica eu faço a chamada da seguinte forma:
new SwingSecurity(this).validateSecurity();
Porém, agora devo passar como parâmetro as permissões do usuário, mas não posso passar como parâmetro meu objeto usuário, pois isso geraria depêndencia. Pensei em passar um Map, onde a chave é o nome do campo e o valor é sua permissão.
/*
* SwingSecurity.java
*
* Criado em 03 de Janeiro de 2006, 13h25
*/
package br.com.datamanager.security;
import java.awt.Window;
import java.lang.reflect.Field;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import br.com.datamanager.security.annotation.VerifyObject;
/**
* Classe que configura o nível de acesso de um usuário aos componentes visuais
* de uma interface gráfica.
*
* Os componentes visuais são analisados, através de reflection, verificando se
* os mesmos devem ser validados pelo sistema de segurança interno da aplicação
* e, caso necessário, será realizada uma nova análise, para determinar o nível
* de visualização do componente que o usuário tem acesso.
*
* Para a construção da classe o construtor recebe a interface gráfica que será
* analisada e uma Hash Table com as permissões do usuário, sendo a chave desta
* o nome do componente e o nível de permissão do usuário o seu valor.
*
* Para utilizar esta classe a aplicação cliente deve "anotar" seus componentes
* visuais a serem validados com a anotação VerifyObject e executar uma chamada
* ao método validateSecurity(java.awt.Window, java.util.Map<String, integer>),
* como mostrado no exemplo:
*
* new SwingSecurity(new JFrame(),
* new HashMap<String, Integer>()).validateSecurity();
*
* @author Ricardo Luís Fernandes Pinheiro
* @version 1.0
* @since 1.0
*
* @see br.com.datamanager.security.annotation.VerifyObject
*/
public class SwingSecurity implements Security {
/** Interface gráfica que será validada pelo sistema de segurança. */
private Window window;
/**
* Objeto que armazena as permissões do usuário. A chave deste Map é o nome
* do componente visual e o valor é seu nível de acesso.
*/
private Map<String, Integer> permission;
public SwingSecurity(Window window, Map<String, Integer> permission) {
super();
this.window = window;
this.permission = permission;
}
public void validateSecurity() {
for (Field field : window.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(VerifyObject.class)) {
field.setAccessible(true);
if (permission.containsKey(field.getName())) {
this.configureComponent(field, permission.get(field.getName()));
} else {
this.configureComponent(field, Security.ENABLE);
}
}
}
} /* Finaliza o método validateSecurity. */
private void configureComponent(Field field, Integer status) {
try {
Object object = field.get(window);
if (status.intValue() == Security.DISABLE.intValue()) {
if (object instanceof JTextField) {
JTextField jTextField = (JTextField) object;
jTextField.setEditable(false);
} else if (object instanceof JTextArea) {
JTextArea jTextArea = (JTextArea) object;
jTextArea.setEditable(false);
} else {
JComponent component = (JComponent) object;
component.setEnabled(false);
} /* Finaliza a estrutura condicional if/else. */
} else if (status.intValue() == Security.HIDE.intValue()) {
if (object instanceof JTextField) {
JTextField jTextField = (JTextField) object;
jTextField.setEditable(false);
jTextField.setText("");
} else if (object instanceof JTextArea) {
JTextArea jTextArea = (JTextArea) object;
jTextArea.setEditable(false);
jTextArea.setText("");
} else {
JComponent component = (JComponent) object;
component.setEnabled(false);
} /* Finaliza a estrutura condicional if/else. */
} else {
if (object instanceof JTextField) {
JTextField jTextField = (JTextField) object;
jTextField.setEditable(true);
} else if (object instanceof JTextArea) {
JTextArea jTextArea = (JTextArea) object;
jTextArea.setEditable(true);
} else {
JComponent component = (JComponent) object;
component.setEnabled(true);
}
} /* Finaliza a estrutura condicional if/else. */
} catch (IllegalArgumentException exception) {
exception.printStackTrace();
} catch (IllegalAccessException exception) {
exception.printStackTrace();
} /* Finaliza a estrutura de exceção try/catch. */
}
} /* Finaliza a classe SwingSecurity. */
No momento estou trabalhando no método configureComponent, de modo a torná-lo mais eficiente, ele está muito poluído. Alguma idéia de como melhorá-lo?