Filtre o acesso aos seus dados com um sistema completo de permissões

Tradução automática de Deepl

O acesso com filtro aos dados é uma característica obrigatória para evitar o acesso malicioso à sua aplicação.

Até agora, poderia expor ou não expor como recurso REST um dataclass e alguns dos seus atributos. Já era um meio conveniente para restringir o acesso aos seus dados. Ainda assim, estamos entusiasmados por entregar na v19R8 um sistema poderoso e totalmente personalizável para proteger os seus dados contra utilizadores não autorizados. Um sistema para proteger os seus dados depende de quem está a aceder aos mesmos e quais os dados que são acedidos.

Como pediu durante as trocas de clientes, poderá agora lidar com muitos utilizadores que trabalham em diferentes negócios e afinar o acesso aos seus dados com vários níveis de granularidade, desde o mais geral ao mais exacto.

No seguimento das sessões web escaláveis, esta funcionalidade permite-lhe construir uma aplicação fiável e protegida.

HDI_Permissões

contexto geral

Esta nova funcionalidade é baseada em conceitos ORDA e sessões web (mais precisamente em sessões web escaláveis).

Abrange todos os processos web, tais como pedidos REST e pedidos recebidos numa datastore remota, mas também processos web como 4DACTION ou etiquetas 4D.

conceitos principais

Na sua candidatura, pode agora definir as permissões permitidas.

Uma permissão indica um recurso e privilégios associados a acções sobre este recurso.

Os recursos são um atributo dataclass, uma função modelo de dados ORDA, um dataclass, e todo o datastore.

Asacções são: criar, ler, actualizar, apagar, descrever, executar (uma função), e promover (uma função).

uma Permissão para um atributo dataclass

O atributo personalNotes do registo de dados pode ser lido pelo privilégio da medicalAction.

Resource Records.personalNotes Privilégios
Leia medicalAction

uma permissão para uma função dataclass

A função deleteOldRecords() definida no Records dataclass pode ser executada pelo privilégio de administração.

Resource Records.deleteOldRecords() Privilégios
Executar administrar

uma Permissão para um dataclass

O registo de dados pode ser lido tanto pela medicalAction como por privilégios administrativos, e as entidades podem ser criadas pelo privilégio da medicalAction.

Registos de Recursos Privilégios
Leia medicalAction, administrar
Criar medicalAction

uma permissão para toda a datastore

O privilégio de administração pode largar entidades em qualquer dataclass da datastore

Recursos ds Privilégios
Gota administrar

Para estabelecer as suas regras personalizadas de permissões, só tem de criar um ficheiro role.json na pasta Project/Sources da sua aplicação.

Alguns papéis(ou seja, um conjunto de privilégios) também podem ser definidos e associados por si próprio a cada utilizador da sua aplicação.

Lembre-se, pode associar alguns privilégios a uma sessão web escalável. Depois, quando o sistema recebe um pedido, é feito um controlo relativamente aos privilégios do utilizador armazenados na sessão web e que acções são permitidas para esses privilégios no ficheiro roles.json.

É levantado um erro de permissão se a acção sobre o recurso não for permitida.

o mecanismo em detalhes

Quando não foram estabelecidos privilégios na sessão web, é uma sessão de convidados. Por defeito, todos os dados são acessíveis para este privilégio de convidado. Além disso, se não for definida qualquer permissão no ficheiro role.json, todos os dados são acessíveis por qualquer pessoa.

Posteriormente, as permissões estabelecidas no ficheiro roles.json entram em jogo e restringem o acesso aos dados.

Podem ser estabelecidas permissões para recursos a vários níveis de granularidade. Esses recursos são listados abaixo por níveis de granularidade (desde o mais geral ao mais exacto):

– o datastore
– um dataclass
– um atributo dataclass / uma função dataclass

Os privilégios estabelecidos a um determinado nível são anulados ou completados por privilégios especificados a um nível mais preciso.

O diagrama abaixo dá uma representação mais gráfica dos privilégios associados a acções sobre algum recurso.

O privilégio do hóspede pode executar acções sobre recursos associados sem privilégios. Restringe o acesso aos seus dados assim que associa um privilégio a um par de recursos/acção.

DICA: Se quiser que os seus dados sejam inatingíveis por defeito, associe à dataastore um privilégio de ninguém para todas as acções e garanta que este privilégio nunca será colocado na sessão.

entrando em detalhes com exemplos

Vamos trabalhar com este modelo de dados simples.

blank

Nesta aplicação, queremos implementar essas regras:

  • só o privilégio de administração pode abandonar e criar entidades em toda a datastore
  • o dataclass Os doentes só podem ser lidos pelo privilégio medicalAction
  • o atributo Records.personalNotes só pode ser lido pelo privilégio medicalAction (mesmo que o dataclass seja legível por vários outros privilégios)
  • a função deleteOldRecords() definida no Records dataclass só é executável pelo privilégio de administração
  • lidar com uma função de autenticação() executável por qualquer pessoa (privilégio do hóspede)

o privilégio de administração pode cair e criar entidades em toda a datastore

No ficheiro role.json abaixo, definimos um privilégio administrativo. Este privilégio está autorizado:

  • largar
  • criar

entidades em todo o datastore (todos os dataclasses).

Apenas este privilégio administrativo está autorizado a realizar essas acções. Porque por defeito, todas as acções são permitidas em todos os dados, e não associamos nenhum privilégio à acção lida para a datastore, qualquer pessoa pode ler todos os dataclasses da datastore.

{"privilégios": {"privilégio":"administrar"}],
 "papéis": [{}],
 "permissões": {
  "permitido": {\i1}"AplicarPara": "ds", "tipo": "datastore", "drop": ["administrar"], "criar": ["administrar"]}]
 }
}

os doentes do dataclass só podem ser lidos pelo privilégio da acção médica

No ficheiro role.json abaixo, acrescentámos um privilégio medicalAction.

Apenas este privilégio da medicalAction está autorizado a ler o ficheiro Patients dataclass. Uma vez que esta permissão é estabelecida ao nível dataclass, ela anula as permissões estabelecidas ao nível datastore + as permissões dos convidados. Assim, apenas o privilégio medicalAction pode ler o Patients dataclass. Os outros dataclasses são legíveis por qualquer pessoa.

{"privilégios": {"privilégio": "administrar"},{"privilégio":"medicalAction"}],
 "papéis": [  {} ],
 "permissões": 
  {"permitidas": [
      {"aplicarPara": "ds", "tipo": "datastore", "drop": ["administrar"], "criar": ["administrar"] },
      {"aplicarPara": "Pacientes", "tipo": "dataclass", "read": ["medicalAction": {"medicalAction"] }
  ]
 }
}

o atributo records.personalnotes é apenas legível pelo privilégio de medicalAction

Neste exemplo, acrescentámos um privilégio de readRecords. Porque o privilégio readRecords está incluído no privilégio medicalAction, o privilégio medicalAction pode executar todas as acções permitidas para o privilégio readRecords.

Tanto readRecords como medicalAction pode ler o Records dataclass, mas o atributo personalNotes só pode ser lido pelo privilégio medicalAction.

{"privilégios": {"privilégio": "administrar"}, {"privilégio": "readRecords"}, {"privilégio": "medicalAction", "inclui":readRecords": ["readRecords"] ],
 "papéis": [ {} ],
 "permissões": {
  "permitido": [
   {"aplicarPara": "ds", "tipo": "datastore", "drop": ["administrar"], "criar": ["administrar"] },
   {"aplicarPara": "Pacientes", "tipo": "dataclass", "ler": ["medicalAction": "medicalAction": "medicalAction",}
   {"aplicarPara": "Registos", "tipo": "dataclass", "read": ["readRecords"] },
   {"aplicarPara":"Records.personalNotes", "type": "attribute", "read": ["medicalAction": {"medicalAction"] }
  ]
 }
}

A função deleteoldrecords dos registos de dados é executável apenas pelo privilégio de administrar.

No exemplo abaixo, porque apenas o administrador do sistema deve ter permissão para apagar registos antigos, adicionámos para o privilégio de administração a permissão para executar a função deleteOldRecords() definida no ficheiro Records dataclass.

Apenas este privilégio pode executá-lo.

Acrescentámos também a permissão para o privilégio de administração para ler a folha de dados dos Registos, porque a leitura das entidades é necessária para os eliminar.

{"privilégios": {{"privilégio": "administrar"}, {"privilégio": "readRecords"}, {"privilégio"}: "medicalAction", "inclui": readRecords": "readRecords": "readRecords": ["readRecords"] ],
 "papéis": [  {} ],
 "permissões": {
  "permitido": [
   {"aplicarPara": "ds", "tipo": "datastore", "drop": ["administrar"], "criar": ["administrar"] },
   {"aplicarPara": "Pacientes", "tipo": "dataclass", "ler": ["medicalAction": "medicalAction": "medicalAction",}
   {"aplicarPara": "Registos", "tipo": "dataclass", "read": ["readRecords","administrar"] },
   {"aplicarPara": "Records.personalNotes", "type": "attribute", "read": {"medicalAction": "medicalAction"],
   {"aplicarPara":"Records.deleteOldRecords", "type": "method", "execute": [} {"administrar": {"administrar"}
  ]
 }
}

manusear uma função de autenticação executável por convidado

Para impedir um utilizador estrangeiro de executar qualquer função na nossa aplicação, restringimos a execução de funções a nível de datastore a nenhum privilégio (nunca é colocado na sessão web).

No nosso sistema, temos uma função authenticate() (definida na classe DataStore ) a ser executada pelos utilizadores para entrar na aplicação. Acrescentámos permissão para executar esta função authenticate().

Como deve ser executável por qualquer pessoa, a acção de execução foi definida para o privilégio de convidado. Também adicionámos os privilégios hr para impedir que o Users dataclass seja lido por alguém estrangeiro à aplicação.

A função authenticate() precisa de ler o dataclass Users para verificar a existência do utilizador e a sua palavra-chave. Assim, é promovida com o privilégio hr. A acção de promoção acrescenta um privilégio na sessão da web (apenas durante a execução da função).

{"privilégios": {{"privilégio": "administrar"}, {"privilégio": "readRecords"}, {"privilégio"}: "medicalAction", "inclui": ["readRecords"] }, {"privilégio": "hr"}, {"privilégio":nenhum"}, ["none"} ],
 "papéis": [  {} ],
 "permissões": {
  "permitido": [
   {"aplicarPara": "ds", "tipo": "datastore", "drop": ["administrar"], "criar": ["administrar"], "executar": ["none"] },
   {"aplicarPara": "Pacientes", "tipo": "dataclass", "ler": ["medicalAction": "medicalAction": "medicalAction",}
   {"aplicarPara": "Utilizadores", "tipo": "dataclass", "read": {"hr"] },
   {"aplicarPara": "Registos", "tipo": "dataclass", "read": ["readRecords", "administrar"] },
   {"aplicarPara": "Records.personalNotes", "type": "attribute", "read": {"medicalAction": "medicalAction"],
   {"aplicarPara": "Records.deleteOldRecords", "type": "method", "execute": [administrar": {"administrar"] },
   {"aplicarPara": "ds.authenticate", "tipo": "método", "promover": ["hr"], "executar": ["convidado"]
   }
  ]
 }
}

a fase de autentificação

No ficheiro role.json, pode definir papéis: ou seja, um conjunto de privilégios. No exemplo abaixo, adicionámos o papel do The Secretary contendo o privilégio createPatient e readRecords.

Os utilizadores associados a este papel podem executar todas as acções permitidas para privilégios createPatient e readRecords (criar um novo paciente e ler registos).

{"privilégios": { {"privilégio": "administrar": [ {"privilégio": [ {"privilégio": [ "readRecords" }, {"privilégio": "medicalAction", "inclui": ["readRecords"], {"privilégio": ["readRecords"], {"privilégio": "hr"  }, {"privilégio": " nenhum"},
  {"privilégio":"createPatient" } ],
 "papéis": [ {\i1}"papel": "O Secretário", "privilégios": ["createPatient","readRecords" ] } ],
 "permissões": {
  "permitido": [
   {"aplicarPara": "ds", "tipo": "datastore", "drop": ["administrar"], "criar": ["administrar"], "executar": ["none"] },
   {"aplicarPara": "Pacientes", "tipo": "dataclass", "read": ["medicalAction"], "criar": ["createPatient"] },
   {"aplicarPara": "Utilizadores", "tipo": "dataclass", "read": {"hr"] },
   {"aplicarPara": "Registos", "tipo": "dataclass", "read": ["readRecords", "administrar"] },
   {"aplicarPara": "Records.personalNotes", "type": "attribute", "read": {"medicalAction": "medicalAction"],
   {"aplicarPara": "Records.deleteOldRecords", "type": "method", "execute": [administrar": {"administrar"],
   {"aplicarPara": "ds.authenticate", "type": "método", "promover": ["hr"], "executar": "convidado": ["guest"] }
  ]
 }
}

Na sua aplicação, deve associar cada utilizador a uma função num dataclass (o Users dataclass, neste exemplo).

Aqui está o dataclass

blank

e os dados

blank

Durante a fase de autenticação, pode colocar os privilégios associados a este papel na sessão web.

Aqui está um exemplo de uma função authenticate().

exposed Function authenticate($identifier : Text; $password : Text) : Text
	
var $user : cs.UsersEntity
	
Session.clearPrivileges()
	
$user:=ds.Users.query("identifier = :1"; $identifier).first()
	
If ($user#Null)
	If (Verify password hash($password; $user.password))
		Session.setPrivileges(New object("roles"; $user.role))
		return "Your are authenticated as "+$user.role
	Else 
		return "Your are authenticated as Guest"
	End if 
Else 
	return "Your are authenticated as Guest"
End if 

Leia atentamente a documentação para saber mais sobre as permissões, e descarregue o HDI acima para executar um exemplo de demonstração.

Sinta-se à vontade para abrir discussões sobre o fórum.

Avatar
• Proprietário do produto - Marie-Sophie Landrieu -Yvert entrou ao time 4D Product como Proprietária do Produto em 2017. Como tal, está a cargo de escrever as histórias dos usuários e depois traduzi-las em especificações funcionais. Seu papel também é garantir que a implementação da funcionalidade entregue cumpra com as necessidades do cliente. Marie-sophie se formou na Escola de Engenharia de ESIGELEC e começou sua carreira como engenheira da IBM em 1995. Participou em vários projetos (de manutenção e criação) e trabalhou como desenvolvedora de Cobol. Depois trabalhou como designer de UML e desenvolvedora de Java. Suas principais funções foram analisar e redigir requisitos funcionais, coordenar os times de negócio e de desenvolvimento.