Segurança

O PowerPortalsPro oferece um modelo de segurança flexível e orientado por código, que permite controlar o acesso tanto no nível da tabela quanto no nível do registro. A segurança é implementada criando classes de manipuladores de permissões e registrando-as no container de injeção de dependências.

Visão geral

Existem duas interfaces que você pode implementar dependendo do nível de controle que precisa:

Dica

Se você só precisar de verificações em nível de tabela (por exemplo, "usuários autenticados podem ler esta tabela"), use ITablePermissionHandler. Se você precisar de lógica em nível de registro (por exemplo, "usuários só podem deletar registros que possuem"), use ITableRecordPermissionHandler.

Boa prática — filtre na fonte

Os manipuladores de permissões impõem acesso, mas não substituem o filtro. Os manipuladores em nível de registro são executados após a recuperação de uma página de registros do Dataverse, então depender deles para ocultar linhas distorce a paginação da grade (uma página com 50 pode mostrar menos) e a contagem total, além de desperdiçar consultas buscando linhas que depois são descartadas. Sempre que os dados precisarem ser direcionados ao usuário atual, filtre no nível da consulta — com uma IFetchXmlQueryFilterInterceptor (veja abaixo) ou uma visualização personalizada que leve em conta o usuário atual — para que o Dataverse retorne apenas as linhas que o usuário deve ver e gradeie a página corretamente. Mantenha os responsáveis pela permissão como garantia de fiscalização.

Dataverse-Native Security (Prévia)

O modelo de segurança recomendado para o futuro permite que a própria Dataverse aplique a segurança para os usuários do seu portal, baseado no recurso unificado de segurança do Dataverse do Power Pages. Em vez de escrever manipuladores de permissões em código, você gerencia o acesso com papéis de segurança padrão do Dataverse — os mesmos papéis, privilégios e ferramentas administrativas usadas para usuários internos. O modelo está atualmente em prévia — tanto o recurso da Microsoft quanto o suporte do Power Portals Pro — e o Power Portals Pro seguirá o cronograma de lançamentos da Microsoft até a disponibilidade geral.

Quando ativado, o PowerPortalsPro fornece automaticamente um sistema gerenciado (C2) systemuser para cada contato do portal — no registro para novos contatos e preguiçosamente no login para os existentes — junto com o powerpagesusermapping registro que liga o contato, o usuário do sistema e seu site Power Pages. Cada chamada Dataverse para a sessão então se passa por esse usuário do sistema, então os papéis de segurança que o Power Pages sincroniza a partir dos seus papéis web e permissões de tabela governam exatamente o que o usuário pode ver e fazer. A sessão carrega um PortalUserType de ContactStubUser para que sua interface possa sempre distinguir esses usuários provisionados dos usuários internos reais.

Nota

Para usar esse modelo de segurança, você deve criar um site Power Pages no seu ambiente Dataverse — é isso que instala os componentes do framework Microsoft e permite habilitar o recurso de segurança unificada. Você não precisa de um plano pago do Power Pages, e pode deletar o site imediatamente após instalar e ativar o recurso. O registro do site do Power Pages (powerpagesite) referenciado PowerPagesSiteId por deve existir no ambiente, já que os mapeamentos do usuário e a sincronização de papéis de segurança são resolvidos contra ele.

Ativando a Segurança Dataverse-Native

Ative o modelo no SecurityOptions Program.csseu servidor, fornecendo o ID do seu registro do site Power Pages:

A configuração é validada na inicialização da aplicação: quando ProvisionSystemUsers ativada, PowerPagesSiteId deve ser definida e resolvida para um registro existente powerpagesite , caso contrário a aplicação não inicia com a orientação.

Conceda acesso exatamente como o Power Pages faz: configure funções web e permissões de tabela no app Power Pages Management, e atribua funções web aos contatos (pelo app Management ou programaticamente). A plataforma sincroniza esses papéis em papéis de segurança gerados automaticamente (nomeados PowerPages_*) e os atribui automaticamente conforme mudanças de associação à função web — como a configuração está inteiramente no Power Pages, seu portal pode se mover para ou de um site real do Power Pages sem atrito. Note que mudanças de função e privilégio podem levar de alguns segundos até alguns minutos para se propagar pelos caches do Dataverse antes de entrarem em vigor.

Siga o guia passo a passo de configuração

Começando

1. Criar um Manipulador de Permissão

Crie uma classe que implemente ITablePermissionHandler ou ITableRecordPermissionHandler. Defina a Table propriedade para o nome lógico da tabela Dataverse à qual o handler se aplica e implemente cada método de permissão.

Aqui está um exemplo simples que concede acesso total a todos os usuários para uma tabela específica:

2. Registro na Injeção de Dependência

Registre seu handler no contêiner DI do Program.cs arquivo do seu projeto (ou em um método de extensão de coleção de serviços):

Como os handlers são resolvidos a partir do contêiner DI, você pode injetar quaisquer serviços necessários (como contexto de banco de dados ou serviço ao usuário) por meio da injeção de construtores.

Segurança em Nível de Registro

Para cenários em que o acesso depende do registro específico em que está sendo operado, implemente ITableRecordPermissionHandler. Essa interface se estende ITablePermissionHandler com sobrecargas que recebem o TableRecord.

O exemplo a seguir permite que todos os usuários leiam registros globalmente, mas restringe as operações de escrita aos registros pertencentes ao usuário atual:

Nota

A CanUpdateAsync sobrecarga em nível de registro fornece tanto ao registro as atualizações propostas (recordWithUpdates) quanto ao registro em seu estado persistido atualmente (currentRecord), permitindo que você compare valores ou valide mudanças específicas de campo.

Colunas Obrigatórias

A RequiredColumns propriedade especifica quais colunas devem ser recuperadas para que o manipulador avalie permissões em nível de registro. O framework adiciona automaticamente essas colunas às consultas FetchXML quando elas ainda não estão incluídas, garantindo que o manipulador sempre tenha os dados necessários — mesmo que a visualização ou consulta não inclua essas colunas.

O exemplo a seguir usa a ppp_owningportaluserid coluna de consulta para restringir o acesso a registros pertencentes ao usuário atual:

Nota

Se RequiredColumns retorna uma lista vazia e os métodos em nível de registro do handler usam record.Idapenas , nenhuma coluna adicional é adicionada à consulta. A owner propriedade é sempre fornecida pela plataforma, independentemente de RequiredColumns.

Interceptadores de Filtro de Consulta FetchXML

Além da segurança em nível de tabela e registro, o PowerPortalsPro suporta IFetchXmlQueryFilterInterceptor — uma interface que permite modificar consultas FetchXML antes de serem executadas. Isso é útil para impor filtragem em nível de linha, como garantir que um usuário só possa ver registros que pertencem a ele ou à sua equipe.

IFetchXmlQueryFilterInterceptor estende ITablePermissionHandler, então cada interceptor também define permissões em nível de tabela por meio da Table propriedade e dos métodos padrão de permissões. O método do OnQueryAsync interceptor é chamado apenas para consultas que têm como alvo sua tabela especificada.

Diferente dos manipuladores de permissões em nível de registro, que avaliam cada registro após a recuperação, interceptadores de filtro de consulta modificam a consulta antes que ela chegue ao Dataverse. Registros filtrados nunca são recuperados, o que melhora o desempenho e a segurança — e, o que é importante, mantém a paginação em grade e as contagens totais precisas, já que o filtro aplicado após a recuperação deixaria as páginas curtas e os totais de contagem incorreta.

1. Criar um interceptador de filtro de consulta

Implemente IFetchXmlQueryFilterInterceptor, defina a Table propriedade para o nome lógico da tabela, implemente os métodos de permissão e use o FetchXMLBuilder in OnQueryAsync para adicionar filtros à consulta. O FetchXmlParameters registro fornece o arquivo do usuário EntityReferenceatual FetchXMLBuilder

O exemplo a seguir restringe consultas na contact tabela para devolver apenas o registro correspondente ao usuário atual:

2. Registro na Injeção de Dependência

Registre seu interceptor tanto como um IFetchXmlQueryFilterInterceptor quanto como um ITablePermissionHandler para que tanto o filtro de consulta quanto as permissões em nível de tabela sejam aplicados. Múltiplos interceptadores podem ser registrados e cada um será executado para consultas direcionadas à sua tabela.

Dica

Como IFetchXmlQueryFilterInterceptor estende ITablePermissionHandler, uma única classe lida tanto com permissões em nível de tabela quanto com filtragem em nível de consulta. O OnQueryAsync método é invocado apenas para consultas que correspondem à propriedade do Table interceptor, então não há necessidade de verificar o nome da tabela dentro do método.

Classes Base Integradas

A estrutura fornece classes base para simplificar padrões comuns de segurança:

Referência API

ITablePermissionHandler Interface

Propriedades

Nome
Tipo
Padrão
Descrição
Tablestring
Nome lógico da tabela à qual esse manipulador de permissão se aplica.
Nome: Table
Tipo: string
Descrição: Nome lógico da tabela à qual esse manipulador de permissão se aplica.

Métodos

Nome
Parâmetros
Tipo
Descrição
CanAppendAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de anexar um registro.
CanAppendToAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de anexar a um registro.
CanCreateAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de criar um registro.
CanDeleteAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de excluir um registro.
CanReadAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de ler um registro.
CanUpdateAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de atualizar um registro.
Nome: CanAppendAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de anexar um registro.
Nome: CanAppendToAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de anexar a um registro.
Nome: CanCreateAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de criar um registro.
Nome: CanDeleteAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de excluir um registro.
Nome: CanReadAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de ler um registro.
Nome: CanUpdateAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de atualizar um registro.

ITableRecordPermissionHandler Interface

Propriedades

Nome
Tipo
Padrão
Descrição
RequiredColumnsList<string>
Lista de nomes lógicos de colunas que devem ser recuperados para que este manipulador possa avaliar permissões em nível de registro.
Tablestring
Nome lógico da tabela à qual esse manipulador de permissão se aplica.
Nome: RequiredColumns
Tipo: List<string>
Descrição: Lista de nomes lógicos de colunas que devem ser recuperados para que este manipulador possa avaliar permissões em nível de registro.
Nome: Table
Tipo: string
Descrição: Nome lógico da tabela à qual esse manipulador de permissão se aplica.

Métodos

Nome
Parâmetros
Tipo
Descrição
CanAppendAsyncGuid? userId
TableRecord record
Task<bool>
Método para determinar se um usuário deve ser capaz de anexar o registro fornecido.
CanAppendToAsyncGuid? userId
TableRecord record
Task<bool>
Método para determinar se um usuário deve ser capaz de adicionar ao registro fornecido.
CanCreateAsyncGuid? userId
TableRecord record
Task<bool>
Método para determinar se um usuário deve ser capaz de criar o registro fornecido.
CanDeleteAsyncGuid? userId
TableRecord record
Task<bool>
Método para determinar se um usuário deve ser capaz de excluir o registro fornecido.
CanReadAsyncGuid? userId
TableRecord record
Task<bool>
Método para determinar se um usuário deve ser capaz de ler o registro fornecido.
CanUpdateAsyncGuid? userId
TableRecord recordWithUpdates
TableRecord currentRecord
Task<bool>
Método para determinar se um usuário deve ser capaz de atualizar o registro fornecido.
Nome: CanAppendAsync
Parâmetros: Guid? userId
TableRecord record
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de anexar o registro fornecido.
Nome: CanAppendToAsync
Parâmetros: Guid? userId
TableRecord record
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de adicionar ao registro fornecido.
Nome: CanCreateAsync
Parâmetros: Guid? userId
TableRecord record
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de criar o registro fornecido.
Nome: CanDeleteAsync
Parâmetros: Guid? userId
TableRecord record
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de excluir o registro fornecido.
Nome: CanReadAsync
Parâmetros: Guid? userId
TableRecord record
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de ler o registro fornecido.
Nome: CanUpdateAsync
Parâmetros: Guid? userId
TableRecord recordWithUpdates
TableRecord currentRecord
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de atualizar o registro fornecido.

IFetchXmlQueryFilterInterceptor Interface

Propriedades

Nome
Tipo
Padrão
Descrição
Tablestring
Nome lógico da tabela à qual esse manipulador de permissão se aplica.
Nome: Table
Tipo: string
Descrição: Nome lógico da tabela à qual esse manipulador de permissão se aplica.

Métodos

Nome
Parâmetros
Tipo
Descrição
CanAppendAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de anexar um registro.
CanAppendToAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de anexar a um registro.
CanCreateAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de criar um registro.
CanDeleteAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de excluir um registro.
CanReadAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de ler um registro.
CanUpdateAsyncGuid? userId
Task<bool>
Método para determinar se um usuário deve ser capaz de atualizar um registro.
OnQueryAsyncFetchXMLBuilder fetchXmlBuilder
FetchXmlParameters parameters
Task<FetchXMLBuilder>
Chamado para permitir a modificação de uma consulta FetchXML antes de sua execução.
Nome: CanAppendAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de anexar um registro.
Nome: CanAppendToAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de anexar a um registro.
Nome: CanCreateAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de criar um registro.
Nome: CanDeleteAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de excluir um registro.
Nome: CanReadAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de ler um registro.
Nome: CanUpdateAsync
Parâmetros: Guid? userId
Tipo: Task<bool>
Descrição: Método para determinar se um usuário deve ser capaz de atualizar um registro.
Nome: OnQueryAsync
Parâmetros: FetchXMLBuilder fetchXmlBuilder
FetchXmlParameters parameters
Tipo: Task<FetchXMLBuilder>
Descrição: Chamado para permitir a modificação de uma consulta FetchXML antes de sua execução.