Seguridad de la mesa

Power Portals Pro asegura los datos en tres niveles: qué tablas puede tocar un usuario, qué columnas de esas tablas puede ver y cambiar, y qué filas regresan en absoluto. Las tres se deciden en un registro por tabla. Describe ese registro con AddTableAccess — es la forma de conceder una tabla y lo que usan las plantillas del proyecto para cada tabla que registran. Cuando una regla está fuera de lugar, las mismas tres respuestas pueden escribirse como una ITablePermissionProvider clase; ambas producen lo mismo y componen de la misma manera. No se concede nada hasta que una de ellas lo dice: una tabla que no cubre el registro es inalcanzable, que es el default fallo-cerrado.

Propina

No tienes que escribir esto desde una página en blanco. Los proyectos generados incluyen una secure-a-table habilidad: pide a tu agente de codificación que asegure una tabla y este trabaja a través de qué tabla, para quién es, qué filas, qué operaciones y qué columnas, luego escribe el registro y realiza los cambios correspondientes en Dataverse a través del servidor Power Portals Pro MCP — creando el rol del portal si el acceso está limitado a un rol, y otorgando al usuario de la aplicación los privilegios que implican las respuestas. Después, check_setup informa cualquier tabla a la que tus páginas se vinculen y a la que nada conceda acceso, y cualquier registro que se retire de la seguridad de columnas. Consulta cómo empezar → servidor MCP.

Todos, o solo algunas personas

Cada registro dice para quién es, y hay dos respuestas. Regístralo en el portal y aplica a una audiencia tus nombres en clave — todos o todos los usuarios conectados. Regístralo dentro AddPortalRole y se aplica a los titulares de ese rol, que es una decisión de datos que toma un administrador en Dataverse. El acceso en sí se describe de la misma manera en ambos.

Registro Aplica a Para cambiar quién lo recibe
AddTableAccess("account", t => t.ForSignedInUsers()…) todos los que el público cubre, a petición editar el código y volver a desplegar
AddPortalRole("Credit Manager", role => role.WithTableAccess("account", …)) contactos que ostentan ese Rol de Portal, y nadie más asignar o desasignar el rol en Dataverse — sin despliegue

Se puede registrar una tabla una vez para cada audiencia de todo el portal — ForEveryone() para lo que cualquiera puede alcanzar, ForSignedInUsers() para qué añade iniciar sesión — y ambas suman. Un visitante recibe la primera; un usuario iniciado sesión recibe ambos, con cada operación confinada a las filas del registro que la concede. Con las dos inscripciones que aparecen a continuación, todo el mundo lee cada artículo, y un autor con inicio de sesión también puede escribir uno y editar el suyo propio:

Los roles se suman; nunca restan. El acceso de un usuario son los registros a nivel de portal más todos los roles que ocupa, sindicados — así que el de todo el portal es el suelo en el que todos se sienten, y un rol solo puede aumentarlo. Un rol no puede recuperar una columna o fila que concedió el registro en todo el portal; para retener algo a la mayoría de la gente, concederlo en un rol en lugar de en todo el portal. (Ajustado SecurityOptions.Roles.CompositionBehavior a Restrictive si necesitas que todos los grupos estén de acuerdo.)

Así que: si todos los usuarios de ese tipo deberían tener acceso, regístralo en el portal. Si tan solo algunos deberían hacerlo — y qué personas es una pregunta cuya respuesta cambia sin autorización — lo ponen en un rol. Un registro de rol no otorga nada hasta que alguien crea un registro de Rol del Portal con ese nombre y lo asigna, por eso uno puede sentarse en un proyecto nuevo sin hacer daño.

Descripción del acceso de una tabla

La mayoría de las tablas quieren las mismas pocas reglas: para quién es la tabla, a qué filas llegan, qué pueden hacer y qué columnas ven. AddTableAccess Dice los cuatro en un solo registro y produce un ordinario ITablePermissionProvider — nada más adelante sabe la diferencia. Lo que compra es que las tres decisiones que deben estar de acuerdo (el filtro, la creación y las columnas escribibles) se toman una vez en lugar de tres.

Una audiencia, un alcance de fila y Allow(…) todos son necesarios. Ninguno de ellos tiene un valor predeterminado, porque cada defecto plausible es una forma de publicar datos omitiendo algo — y un registro que se equivoca falla al inicio en lugar de en producción.

Oscilaciones de fila

El alcance filtra cada consulta de la tabla — cuadrículas, consultas, subrejillas, gráficos y el fetch antes de una partida guardada o eliminación. Los scopes nombrados cubren las formas que los portales siguen necesitando:

¿Qué filas Alcance En crear
Cada fila AllRows() Nada preparado
Los propios registros del usuario RowsOwnedByContact("customerid") la búsqueda está configurada para ellos
Los registros de sus colegas, en la misma cuenta RowsOfTheirAccount("customerid") La consulta está configurada en su cuenta
Registros colgando de un padre a los que puedan contactar RowsViaParent("salesorderid", "salesorder", p => …) Nada fijado — el acceso propio del padre decide
Registros que los señalan de más de una manera RowsMatchingAny(r => r.RowsOwnedByContact("customerid"), r => r.RowsOfTheirAccount("customerid")) Lo que establece el primer ámbito de propiedad
Su propia fila de contactos OwnRecordOnly() No Create

Los ámbitos de propiedad establecen la columna por sí mismos cuando se crea un registro, tras las comprobaciones de permisos: el usuario no necesita acceso de escritura ni Append To en la tabla a la que apunta, el valor proviene de la sesión en lugar de la petición, y se rechaza una partida guardada posterior que lo cambie. Eso es lo que mantiene un registro que alguien crea dentro del filtro al que está sujeto. Úsalo OwnedBy('column') cuando la columna propietaria no es la que filtra las filas, y WithoutStamping() cuando un plugin ya la configura.

Cuando leer y cambiar difieren

One scope responde a cada operación a menos que digas lo contrario. RowsForWriting Reduce las filas que un usuario puede cambiar sin reducir las filas que puede ver — "Todos leen cada contacto, cada uno edita solo el suyo" es esa distinción y nada más — y RowsForDeleting reduce la destrucción aún más, porque poder corregir un registro no es lo mismo que poder destruirlo. Cada uno vuelve a la que está por encima, por lo que un registro que no hace distinción no atrae ninguno. Los creadores no se ven afectados: aún no hay fila que filtrar.

Cuando los visores con nombre no encajan

RowsMatching toma un filtro propio sin salir del registro. Dale FetchXML — un <filter> elemento o un conjunto <fetch> cuyos filtros y unirse se copian, con {currentUserId} para el contacto con que inicia sesión— o una callback que se ejecute por solicitud y devuelva bien el FetchXML, compuesto por lo que responden tus servicios, o un filtro que haya construido. Ambos reciben lo mismo TableQueryContext que recibe un proveedor, así saben quién pregunta y si las filas van a ser leídas, actualizadas o eliminadas. No devolver nada no otorga filas: TableQueryFilter.AllRows es como se dice cada fila.

Descripción del acceso de un puesto

Dentro AddPortalRole del rol está la audiencia, así que el registro no nombra a otro. Los roles suman y nunca restan: el acceso del usuario son los registros a nivel de portal más todos los roles que ocupa, sindicatos. Los roles del portal en sí mismos — qué son, cómo se asignan y cómo componen — son la siguiente sección.

Nota

Una clase de proveedor sigue siendo la forma de expresar cualquier cosa que una descripción no puede, y se compone de forma idéntica — AddTablePermissionProvider<T> y WithPermissions<T> permanece sin cambios. Los proyectos generados ya no envían uno: todas las tablas que registran están descritas, incluyendo contact y el rol de Gestor de Crédito.

Portal Roles

Un rol de portal es la forma preferida de asegurar un portal. Vincula a los proveedores de permisos a un nombre que los administradores asignan a los contactos en Dataverse, de modo que los proveedores solo se aplican a las personas que ocupan ese rol — y quienes lo poseen son datos, no código. Un proveedor registrado directamente Program.cs se aplica a todos los usuarios en comparación.

La división es deliberada. Dataverse posee los nombres y las asignaciones, que un administrador gestiona en la aplicación basada en modelos. Tu código es dueño de lo que significa cada nombre. Conceder o revocar el acceso a alguien es entonces un cambio de datos: no hay reconstrucción, no hay redistribución.

1. Crear el rol y asignarlo

Crea un registro de rol en el portal y asignalo a los contactos que deberían tenerlo. El registro de rol no contiene más que un nombre y una descripción — ningún dato de permisos está presente en Dataverse.

2. Vincular el rol a sus proveedores

Coincide con el nombre del registro de puesto y lista lo que concede. Los tipos de proveedor están registrados para ti, así que no los registras tú mismo.

Ese último punto importa: nunca registres también al proveedor de un rol con AddTablePermissionProvider<T>(). Eso lo coloca en el conjunto global y lo concede a todos, anulando silenciosamente el rol. Reserva AddTablePermissionProvider<T>() reglas que realmente se apliquen a todos los usuarios.

Cómo se combinan los roles

Los permisos de un usuario provienen de los proveedores registrados globalmente más cada rol que desempeña, y esos grupos se agrupan así:

Propina

En la composición aditiva nada se niega — algo permanece cerrado solo mientras ningún grupo lo abre. Un proveedor registrado globalmente es el hogar adecuado para una regla que se aplica a todos los usuarios, porque siempre está en el pliegue, pero no es un veto: un rol que otorga la operación, o nombra la columna, la reabre. Para mantener algo cerrado cualesquiera que sean los roles que tenga un usuario, concederlo en ningún rol — o establecer SecurityOptions.Roles.CompositionBehavior en Restrictive, donde todos los grupos tengan que estar de acuerdo.

Roles en las páginas y la navegación

Los nombres de roles llegan al navegador como reclamaciones estándar ASP.NET rol, por lo que la autorización de página y la interfaz condicional funcionan sin nada extra:

La pila React lee los mismos nombres de auth.user.roles, y <AuthorizedView roles="Dealer"> compuerta contenido de la misma manera. Los inicios de sesión internos (usuarios del sistema) llevan aquí sus nombres de roles de seguridad en Dataverse, así que una sola comprobación cubre ambos tipos de usuario.

Autorización para el tipo de puesto adecuado

Un rol de portal y un rol de seguridad de Dataverse pueden compartir un nombre y [Authorize(Roles = "…")] no pueden distinguirlos — coincide con la reclamación de rol no tipado, que conlleva ambos. Dos atributos plantean la pregunta más concreta:

Los nombres de los roles van en letra por palabra: comas, dos puntos y comillas están bien, porque el nombre nunca se elimina de una lista. Apilar dos atributos requiere ambos, como siempre ha hecho los atributos apilados [Authorize] ; listar dos nombres en un atributo requiere cualquiera de los dos. La misma comprobación está disponible en código como User.IsInPortalRole("Dealer") y User.IsInSecurityRole("Sales Manager").

La misma distinción en el marcado de Blazor. <AuthorizeView Roles="…"> lee la reivindicación de rol sin tipificar y por tanto lleva la misma ambigüedad que el atributo simple; <PortalRoleView> pide un tipo. Ponle PortalRole / SecurityRole para un solo nombre, o PortalRoles / SecurityRoles para varios — una colección en lugar de una cadena separada por comas, porque los nombres de Dataverse suelen contener comas:

React <AuthorizedView> toma las mismas dos puertas, junto con la existente roles . Suministrar varios nombres en una puerta significa cualquiera de ellos; suministrar dos puertas significa ambos. Los predicados detrás de ellos — hasPortalRole, hasSecurityRole, hasRole — se exportan para comprobaciones imperativas:

Buenas prácticas — filtrar en la fuente

Busca estos siempre que lo que se está protegiendo sea realmente administrativo. Crear un rol de portal es un estándar deliberadamente más bajo que recibir un rol de seguridad en Dataverse, así que un cheque que acepte permite a un administrador asignar acceso al rol que protegía Dataverse simplemente nombrando un rol de portal en su honor.

Nota

Los roles no son gratuitos. Cada uno que un usuario tiene se escribe en la cookie de autenticación dos veces — una como la reclamación estándar de rol, así [Authorize(Roles)] funciona, y otra como la reclamación específica de tipo que hace posibles las comprobaciones anteriores — que mide unos 160 bytes por rol. Unos quince roles por usuario siguen cabiendo una sola cookie; más allá de eso, la cookie se divide en bloques, y lo primero que se cierra suele ser el límite de cabecera de un proxy inverso, que reporta un opaco 400 en lugar de mencionar roles. Prefiero unos pocos roles amplios en lugar de muchos específicos.

Dando a los nuevos usuarios un rol inicial

Nombra los roles con los que debería empezar cada cuenta nueva y el rol que se aplica a los visitantes que han cerrado sesión:

O decidirlo en Dataverse, sin una liberación. La tabla de configuración de roles del portal empareja un rol con un modo de asignación, y un administrador puede cambiar quién obtiene qué de la aplicación basada en modelos:

Cuando los roles dependen de la persona — su dominio de correo, el proveedor con el que inició sesión, una invitación — regístrate y IPortalRoleAssignmentProvider en su lugar. Se consulta a cada proveedor registrado, así que el tuyo se suma a la lista configurada en lugar de reemplazarla. En cualquier caso, la asignación se ejecuta una vez, cuando se crea la cuenta; nunca se vuelve a aplicar al iniciar sesión, así que un rol que elimina un administrador permanece eliminado.

Nota

Un usuario adquiere un rol recién asignado cerrando sesión y volviendo a entrar — iniciar sesión relee sus roles. Las asignaciones de roles se almacenan en caché por usuario durante 24 horas, así que para aplicar un cambio a alguien que ya ha iniciado sesión, borra la caché de Roles del Portal desde el área de administración del sitio: su sesión lo recoge cuando se refresca de nuevo, en menos de diez minutos, y un rol eliminado deja de funcionar justo cuando empieza uno añadido. La tabla de Configuración de Roles del Portal se almacena en caché por separado durante quince minutos, por lo que una fila añadida allí llega al siguiente registro por sí sola — borra la caché "PortalRoleConfiguration" para que sea inmediata. Desactivar una fila de configuración impide que asigne su rol, de la misma manera que desactivar un rol lo revoca.

En su lugar, escribir a un proveedor

Busca una clase cuando una descripción no puede decir a qué te refieres — una regla que depende de algo que solo tu código conoce, o una que tenga que inspeccionar el registro en proceso. ITablePermissionProvider Es en lo que se convierte cada registro de cualquier forma: un proveedor gobierna una tabla, respondiendo a qué puede hacer un usuario con ella, a qué columnas puede leer y escribir, y — a través del filtro de consulta de abajo — cuáles de sus filas puede ver. Un registro descrito y uno escrito componen de forma idéntica, así que un portal puede usar ambos, y una tabla puede ser concedida por uno y ampliada por el otro.

La interfaz tiene un miembro obligatorio. GetPermissionsAsync recibe un UserInfo documento que lleva el ID del usuario, sus roles de portal y sus roles de seguridad en Dataverse, y devuelve un TablePermissions que describe todo lo que recibe ese usuario:

Registro de un proveedor

Un proveedor registrado de esta manera se aplica a todos los usuarios, hayan iniciado sesión o no:

Esta es también la única forma de quitarle algo a todos: los roles se componen aditivamente por defecto, así que un rol puede añadir acceso pero nunca eliminarlo. Las restricciones a nivel de portal pertenecen a un proveedor registrado globalmente, que siempre forma parte del grupo.

Operaciones

TablePermissions.Operations es un TableSecurityPermission valor de bandera — Read, Create, Write, Delete, y Append AppendTo. Hay dos cosas que merece la pena saber sobre él:

Nota

No existe deliberadamente un gancho de "inspeccionar cada fila tras cargarla". Filtrar así rompe la paginación — una página de 50 vuelta con menos — hace que los conteos totales sean incorrectos y paga a Dataverse para recuperar las filas que luego descarta. En cambio, el ámbito de la consulta mantiene la paginación y los conteos son correctos por construcción.

Buenas prácticas — filtrar en la fuente

Alcance de datos en la consulta, no después de ella. El framework deliberadamente no ofrece ningún gancho que inspeccione cada fila una vez que ha sido obtenida: filtrar así rompe la paginación (falta una página de 50), hace que el recuento total sea incorrecto y paga a Dataverse para recuperar las filas que luego descarta. GetQueryFilterAsync Añade las condiciones antes de que se ejecute la consulta, de modo que la paginación y los conteos permanecen correctos por construcción y las filas que un usuario puede no ver nunca se recuperan.

Seguridad a nivel de fila

GetQueryFilterAsync devuelve un filtro que el framework añade a la consulta antes de que Dataverse la ejecute, por lo que las filas que el usuario puede no ver nunca se recuperan. Se aplica a todas las consultas que el portal emite para la tabla — cuadrículas, consultas, subcuadras, gráficos y cargas de un solo registro — y se ejecuta bajo ambos modelos de seguridad, por lo que sigue vigente incluso donde la seguridad nativa de Dataverse evita la puerta de operaciones.

Construye el filtro con context.CreateFilter() y devuélvelo; devolver null significa que no hay restricción de fila. El contexto lleva al usuario actual como EntityReference, los roles que tiene y para qué se van a usar las filas. Las condiciones se añaden a través de la misma FetchXMLBuilder API que se usa en cualquier otro lugar: FetchXMLBuilder

Este proveedor concede tres columnas de contact y asigna cada consulta de contacto al propio registro del usuario iniciado sesión:

Leer, actualizar y borrar

TableQueryContext.Operation Explica por qué se van a buscar las filas, para que cada proveedor pueda asignarlas de forma diferente para cada una:

Cómo se combinan varios filtros

Una tabla puede tener más de un proveedor — uno registrado globalmente, más uno de cada rol que desempeñe el usuario. El framework decide cómo se combinan sus filtros, por lo que un proveedor nunca tiene que saber qué hicieron los demás:

Nota

Las filas no se cierran, como las columnas: un proveedor que devuelve null — o un filtro sin condiciones — no concede filas , y dentro de un grupo que vacía el grupo. Cada fila debe pedirse con TableQueryFilter.AllRows. Ahí es donde radica la única asimetría: la unión de cada fila con cualquier cosa es cada fila, así que si algún grupo que concede la tabla responde AllRows, la tabla vuelve sin filtrar por muy cuidadosamente que los otros roles la hayan definido. Eso es lo que significa composición aditiva, pero es la única forma en que el filtro de un rol puede parecer que está siendo ignorado.

Filtrado a través de una tabla relacionada

AddLink une una tabla para que el filtro pueda probar sus columnas. Coloca la prueba en el filtro en lugar de en el enlace — las condiciones dentro del filtro siguen funcionando cuando el marco relaja la unión a la exterior, y las condiciones en el enlace no:

Nota

La unión anterior llega hasta muchas filas, así que Dataverse devuelve la cuenta una vez por cada membresía — una cuadrícula que repite filas y un total que las cuenta. El framework reconoce esa forma y marca la consulta distinct, proyectando la clave primaria de la tabla para que la deduplicación solo pueda eliminar las filas añadidas por la unión. Una unión que en su lugar sube , una a la propia clave primaria de la tabla relacionada, coincide como mucho con una fila y se deja exactamente como estaba. De cualquier forma, escribes el filtro y nada más — pero vale la pena saber que una unión no es gratuita, y que una regla que puedes expresar como condiciones planas en las propias columnas de la tabla es la forma más económica.

Propina

Cuando una tabla necesita un alcance diferente por rol, aún puedes escribir un proveedor y hacer una rama en context.User.PortalRoles él, pero ya no es necesario. Dos roles pueden llevar cada uno su propio proveedor y el framework suelta sus filtros por ti.

Quién posee un nuevo disco

Un filtro de filas escala lecturas, actualizaciones y eliminaciones, pero un crear no tiene fila que filtrar. Así que una tabla con el alcance de "filas que poseo" seguiría permitiendo que un usuario cree una fila propiedad de otra persona — o de nadie, que su creador entonces no puede ver. Declara la columna que indica quién posee un registro, y el marco lo establece:

Emparejalo con un filtro de fila en la misma columna, de modo que los registros que crea un usuario sean los registros que puede ver. Para la propiedad que no es simplemente el contacto creador — por ejemplo, la cuenta del creador — implévalo ITableRecordOwnershipProvider y regístralo con AddTableRecordOwnershipProvider<T>(). No pongas un propietario en un ITableRecordInterceptor instead: los interceptores se ejecutan antes de las comprobaciones de permisos, por lo que lo que establecen se juzga como la escritura del propio usuario.

El framework lo llama en cada creación de esa tabla, tras las comprobaciones de permisos, y establece cada columna Columns en lo que devuelve — descartando todo lo que envió la solicitud y rechazando una actualización posterior que lo cambiaría, exactamente como para OwnedBy. Emparejalo con un filtro de fila que coincida con lo que establece, así las personas bajo las que archiva un registro sean las que pueden verlo — aquí RowsMatchingAny(r => r.RowsOfTheirAccount("customerid"), r => r.RowsOwnedByContact("customerid")), con WithoutStamping() , así que el registro deja la columna a este proveedor: dos que configuran una columna de forma diferente fallan la partida.

Seguridad a nivel de columna

La seguridad de columnas es opt-in. Un proveedor concede las columnas que pretende exponer, y todo lo demás — incluida una columna que alguien añade a la tabla el año siguiente — permanece retenido hasta que se nombre. El id principal del registro siempre es legible, ya que un registro que el framework no puede identificar no sirve de nada a nadie.

Las lecturas y escrituras son conjuntos independientes: una columna puede ser legible pero no escribible (el caso "mostrar el límite de créditos, no dejar que lo cambien"), o escribible pero no legible. Nómbralos con Reading, Writing y ReadingAndWriting, o optar por no participar en una dimensión completamente con ReadingAllColumns / WritingAllColumns:

Nota

ReadingAllColumns() es algo que tienes que escribir deliberadamente. No se abre para nada que se añada a la tabla después, que es el intercambio correcto solo cuando la tabla es realmente pública — así que el marco no lo asumirá en tu nombre.

La escritura también puede variar entre crear un registro y cambiar uno. Writing cubre ambos. WritingOnCreate permite al usuario establecer una columna al crear el registro y lo convierte en solo lectura a partir de entonces — la prioridad de un caso, elegida al registrarse. WritingOnUpdate es al revés: cambiable en un registro existente, no establecible al principio. Ambos hacen que la columna también sea legible, como Writing, y ambos existen para TablePermissions un proveedor propio. Reflejan los permisos separados de creación y actualización que concede la seguridad de campo de Dataverse:

El marco impone el resultado en cada ruta que los datos cruzan el límite del servidor:

Nota

La columna principal de id de una tabla nunca se oculta, sea lo que sea que diga el conjunto de lectura. El id es identidad y no datos — ya está en la URL que el llamante usó para acceder al registro — y las claves de fila, enlaces de edición, relaciones de subcuadrícula y eliminación se deshacen sin ella. Una lista de permisos que nombre las columnas que una página necesita y olvida el id desmontaría el portal sin proteger nada.

Cómo se comportan los componentes

Los componentes del framework respetan los permisos de columna por sí solos — no conectas nada. Una columna que el usuario no puede escribir se muestra en modo solo lectura y desactivada dondequiera que aparezca: todos los editores la recogen a través de su resolución compartida de solo lectura, y la cuadrícula no da a la celda un editor en línea, así que vuelve a mostrar texto plano. Una columna suministrada readOnly="false" por el consumidor no la anula — el servidor rechazaría la partida guardada de todas formas.

Una columna que el usuario puede no leer — una enmascarada — se renderiza en <ColumnDisplayValue> lugar de un editor, en ambas pilas. Eso no es solo una cortesia: una columna enmascarada no tiene valor alguno, solo la máscara como su valor formateado , por lo que un editor vinculado a ella se renderizaría en blanco; ColumnDisplayValue lee el valor formateado y así muestra el marcador de posición sea cual sea el tipo de columna. Las columnas retenidas por omisión nunca llegan a un componente — no están en el registro y los metadatos de la tabla no las listan.

Lo que recibe el cliente

Los permisos de columna vienen como un ColumnPermissions mapa — nombre lógico de columna a un ColumnSecurityPermission par de banderas — para las columnas cuyo acceso está restringido, lo que Write significa que la columna puede cambiarse en un registro existente. Todo lo ausente tiene acceso completo, por lo que una tabla sin restricciones no contiene nada en absoluto. Un registro recuperado por sí solo lleva el mapa; los registros recuperados juntos comparten un mapa, enviado una vez sobre la respuesta, ya que los permisos pertenecen al usuario y a la tabla en lugar de a una fila — los clientes de ambas pilas lo vuelven a poner en cada registro, por lo que leer los permisos de un registro funciona igual en cualquier caso. Las respuestas en cuadrícula también las reportan por columna en ResolvedColumn.Permissions. Un registro que se está creando aún no tiene un mapa propio, por lo que el extremo de permisos de tabla también devuelve NewRecordColumnPermissions — la misma forma, juzgada por lo que se puede establecer al crear — y ambas pilas RecordContext lo ponen en un nuevo registro para ti. Las columnas retenidas por omisión están deliberadamente ausentes en todos los mapas — omitir existe para que nada en la respuesta revele la columna, y nombrarla ahí lo desharía de menos. Léelo tú mismo en record.CanReadColumn(column) Blazor, record.CanWriteColumn(column) o los emparejamientos canReadColumn / canWriteColumn ayudantes de @powerportalspro/core React.

Omitir o enmascarar

Por defecto, una columna retenida está enmascarada: el registro no tiene valor para ella y SecurityOptions.WithheldColumnMask (***** por defecto) como su valor formateado, por lo que un formulario o cuadrícula sigue mostrando el campo y deja claro que el valor está retenido en lugar de en blanco. La máscara es la misma tenga o no valor de la columna, así que también lo oculta. En cambio, configúrase SecurityOptions.WithheldColumnBehavior para Omit eliminar la columna completamente del registro, como si la consulta nunca lo hubiera pedido, por lo que nada en la respuesta revela que la columna existe — la elección correcta cuando la propia existencia de la columna es sensible. Retener una columna también retiene cualquier columna que la republique — el compañero de nombre de una consulta, el gemelo de moneda base de una columna de dinero — por lo que una lista de denegación que nombre una columna no puede ser evitada a través de otra. Una sola tabla puede anular la elección a nivel de sitio a través TableColumnPermissions.WithheldColumnBehaviorde .

Nota

Empareja una columna enmascarada con una denegación de escritura. Una columna enmascarada no tiene valor en el registro, así que un llamante que publica un registro cargado completo no envía nada por él — pero el framework acepta una carga útil guardada al pie de la letra, así que una solicitud que establece la columna, incluida la máscara, escribe sobre el valor almacenado si la columna es escribible. La denegación de escritura es lo que la rechaza.

Columnas que republican otra columna

Retener una columna también retiene cualquier columna que tenga el mismo valor bajo un segundo nombre. Dataverse crea estas para ti: una consulta …name y …yominame socios, la etiqueta de una elección y un gemelo de moneda base para cada columna de moneda — creditlimit_base junto creditlimitcon . Son columnas ordinarias, así que una denominación creditlimit de lista de denegados no dice nada sobre creditlimit_base, y sin esto una cantidad enmascarada volvería directamente a través de su gemela. El enlace proviene de los propios metadatos de la plataforma en lugar de una regla de nombre, por lo que también se cumple para tus propias columnas, y se aplica en lecturas, en una consulta que nombra explícitamente al compañero, en metadatos de tabla, en columnas de cuadrícula y en guardados.

Buenas prácticas — filtrar en la fuente

Un caso que el framework no puede ver para ti: una columna calculada o de agrupación, y las columnas compuestas de la plataforma — fullname, yomifullname, address1_composite y sus hermanas. Dataverse no informa qué columnas las alimentan, así que retener lastname no fullnameretiene , y una columna calculada sobre una columna que has denegado seguirá mostrando su resultado. Nómbralos tú mismo en el conjunto de lectura cuando sus entradas sean sensibles. Una lista de permisos (ColumnPermissions.Allow(…)) evita el problema por completo, ya que nada es legible hasta que lo nombras — que es el mejor valor por defecto para una tabla que contiene cualquier cosa que valga la pena retener.

Nota

Cuando varios proveedores cubren una tabla, sus conjuntos de columnas se componen igual que sus operaciones: de forma aditiva entre roles y bajo MultiplePermissionHandlersBehavior dentro de un mismo grupo. Un proveedor que existe solo para definir filas y no dice nada sobre columnas queda completamente fuera del pliegue de columnas, por lo que no amplía ni reduce lo que los demás concedieron.

Dataverse-Native Security (Vista previa)

El modelo de seguridad recomendado para el futuro permite que Dataverse imponga la seguridad para los usuarios de tu portal, basado en la función unificada de seguridad de Power Pages. En lugar de escribir manejadores de permisos en código, gestionas el acceso con roles web y permisos de tabla de Power Pages, que la plataforma convierte en roles de seguridad de Dataverse que Dataverse aplica en cada solicitud. El modelo está actualmente en versión preliminar — tanto la función de Microsoft como el soporte de Power Portals Pro — y Power Portals Pro seguirá el calendario de lanzamientos de Microsoft hasta la disponibilidad general.

Cuando está habilitado, PowerPortalsPro provisiona automáticamente un sistema gestionado por el sistema (C2) systemuser para cada contacto del portal — al registrarse para nuevos contactos y de forma perezosa al iniciar sesión para los existentes — junto con el powerpagesusermapping registro que vincula el contacto, el usuario del sistema y tu sitio Power Pages. Cada llamada de Dataverse para la sesión se hace pasar por ese usuario del sistema, por lo que los roles de seguridad que Power Pages sincroniza desde tus permisos web de roles y tablas gobiernan exactamente lo que el usuario puede ver y hacer. La sesión lleva un PortalUserType de ContactStubUser para que tu interfaz siempre pueda distinguir a estos usuarios provisionados de los usuarios internos reales.

Nota

Para usar este modelo de seguridad debes crear un sitio web de Power Pages en tu entorno Dataverse — esto es lo que instala los componentes del framework de Microsoft y te permite activar la función de seguridad unificada. No necesitas un plan de pago de PowerPages, y puedes eliminar la web inmediatamente después de instalar y activar la función. El registro del sitio de Power Pages (powerpagesite) al que PowerPagesSiteId se refiere debe existir en el entorno, ya que los mapeos de usuario y la sincronización de seguridad-rol se resuelven en su contra.

Habilitación de la seguridad nativa de Dataverse

Activa el modelo desde SecurityOptions el Program.csservidor , proporcionando el id del registro de tu sitio de Power Pages:

La configuración se valida al iniciar la aplicación: cuando ProvisionSystemUsers está habilitada, PowerPagesSiteId debe establecerse y debe resolverse a un registro existente powerpagesite , de lo contrario la aplicación no arranca con guía.

Concede acceso exactamente como lo hace Power Pages: configura roles web y permisos de tablas — en la app Power Pages Management o en la página de Roles Web de tu portal desde la solución Power Portals Pro Enhanced Authorization — y asigna roles web a los contactos (a través de la app Management, de forma programática o automática para nuevos usuarios con reglas en esa misma página). La plataforma sincroniza esos roles de seguridad auto-generados (nombrados PowerPages_*) y los asigna automáticamente a medida que cambia la membresía de rol web — como la configuración está completamente en Power Pages, tu portal puede moverse hacia o desde un sitio real de Power Pages sin fricciones. Ten en cuenta que los cambios de roles y privilegios pueden tardar desde unos segundos hasta un par de minutos en propagarse a través de las cachés de Dataverse antes de hacer efecto.

Sigue la guía paso a paso de configuración

Emparejando un inicio de sesión externo con un contacto

Cuando alguien inicia sesión con Microsoft, Google u otro proveedor externo, el portal tiene que averiguar a qué contacto existente — si es que tiene alguno — ese inicio de sesión. Esto se resuelve en dos pasos:

  1. Un enlace existente. Si la cuenta ha iniciado sesión antes, una adx_externalidentity fila ya la vincula a un contacto. Esa es una declaración explícita y almacenada de "esta cuenta es esta persona", así que siempre gana y nunca se ve afectada por la configuración que aparece abajo.
  2. El respaldo del correo electrónico. Sin un enlace todavía, el portal coincide con la dirección de correo electrónico que proporcionó el proveedor con las columnas del contacto. Este es el paso que puedes configurar — y el paso que decide si un cliente recurrente se une a su contacto actual o recibe un duplicado.

Por defecto se buscan dos columnas, primero el nombre de usuario del portal. Los contactos creados a través del portal llevan adx_identity_username, mientras que los contactos importados o introducidos por el personal suelen tener solo emailaddress1 — buscar en ambos es lo que permite a un cliente existente iniciar sesión y aparecer en su propio registro en lugar de uno nuevo:

El orden importa: es la precedencia, no solo una lista. Las columnas se buscan juntas en una sola consulta, y la primera columna de tu lista que coincide con algo decide el ganador — así que si un contacto tiene la dirección como nombre de usuario del portal y otro la tiene en emailaddress1, la coincidencia de nombre de usuario gana bajo el orden por defecto.

Lista menos columnas para la coincidencia estrecha: [ContactEmailColumn.IdentityUsername] lo restringe a cuentas creadas por el portal, y una lista vacía desactiva por completo el respaldo del correo, dejando un enlace de identidad externa existente como la única forma en que una cuenta puede resolver a un contacto. Añade ContactEmailColumn.EmailAddress2 y ContactEmailColumn.EmailAddress3 amplía la relación — se omiten deliberadamente del predeterminado por la razón siguiente.

Buenas prácticas — filtrar en la fuente

Cada columna que listes es una forma de que quien controle una dirección de correo electrónico sea reconocido como el contacto que la posee. Solo lista las columnas que tu proceso de entrada de datos trate como pertenecientes al propio contacto — si emailaddress2 es donde tu equipo archiva la dirección de un asistente o una bandeja de entrada compartida de la empresa, listarla permite que quien lea esa bandeja inicie sesión como ese contacto.

Buenas prácticas — filtrar en la fuente

La coincidencia convierte la dirección de correo electrónico en un identificador, no solo en una etiqueta: decide en qué contacto existente se convierte un inicio de sesión. Así que el portal solo omite el correo de confirmación cuando el proveedor de identidad realmente verificó esa dirección exacta. Si la dirección fue escrita sobre la proporcionada por el proveedor, o el proveedor nunca la verificó, se envía un enlace de confirmación y el inicio de sesión externo no se asocia al contacto hasta que ese enlace se sigue.

Qué inicios de sesión cuentan como verificados no es propiedad del proveedor. Google verifica cada dirección que afirma. Microsoft no: una cuenta personal de Microsoft verificó su dirección, pero una cuenta de trabajo o escuela de Entra proporciona lo que esté en el atributo del mail directorio, que un administrador de inquilinos puede establecer a cualquier valor en cualquier dominio — incluido un dominio que su inquilino no posee. El portal lee el token del proveedor en su lugar: una cuenta personal se verifica, y una cuenta de trabajo o escolar solo se verifica cuando Entra confirma esa dirección exacta — su verified_primary_email reclamación verified_secondary_email la lista, o xms_edov dice que su dominio pertenece al propio inquilino del usuario. Entra envía esas reclamaciones solo cuando el registro de la app las solicita (véase Configuración de inicio de sesión de Entra ID); sin ellas, los inicios de sesión en el trabajo y la escuela confirman por correo electrónico la primera vez.

Nota

Estas configuraciones solo se aplican al inicio de sesión externo. El inicio de sesión local de nombre de usuario/contraseña, registro y restablecimiento de contraseña siguen coincidiendo adx_identity_username de forma independiente, deliberadamente — el flujo de restablecimiento de contraseña envía su enlace a la dirección introducida, así que coincidir con columnas secundarias de correo allí permitiría restablecer la contraseña de otra persona.

Permitir que solo los contactos existentes inicien sesión

Por defecto, cualquiera puede convertirse en usuario del portal: registrarse o iniciar sesión con un proveedor externo bajo una dirección que no tiene contacto crea un contacto. Cuando el portal es para personas que ya tienes en Dataverse — clientes, miembros, socios — desactiva el registro y solo ellos pueden iniciar sesión:

La página de registro y sus enlaces desaparecen, y el servidor se niega a crear un usuario como se le pida. Un inicio de sesión externo sigue encontrando su contacto como se ha descrito arriba y enlaza a él; uno que no coincide con nadie es rechazado en lugar de crear un contacto. Las cuentas locales no se ven afectadas para quienes ya tienen uno.

Nota

Un inicio de sesión rechazado solo se explica en pantalla cuando el proveedor ha verificado esa dirección exacta, porque entonces la persona que inicia sesión ya ha demostrado que es la propietaria. Para cualquier otra dirección, el portal responde exactamente igual que para una dirección que tiene un contacto — "revisa tu correo electrónico" — y envía la dirección con un aviso breve de que no está registrada. Informarlo directamente al visitante permitiría que cualquiera escriba direcciones en el formulario para saber quién tiene una cuenta.

El aviso se envía a través del propio remitente del portal. Un host que lo sustituya por su propia pila de correo también debería registrar un ISignUpRefusalEmailSender; sin uno, el rechazo se registra y no se envía ningún aviso.

Clases base integradas

El marco proporciona clases base para simplificar patrones de seguridad comunes:

Referencia API

AuthorizePortalRoleAttribute Clase

Propiedades

Nombre
Tipo
Default
Descripción
AuthenticationSchemesstring?
Policystring?
RoleNamesIReadOnlyList<string>
Los nombres de los roles que requiere este atributo, cualquiera de los cuales lo satisface.
Rolesstring?
TypeIdObject
Nombre: AuthenticationSchemes
Tipo: string?
Nombre: Policy
Tipo: string?
Nombre: RoleNames
Tipo: IReadOnlyList<string>
Descripción: Los nombres de los roles que requiere este atributo, cualquiera de los cuales lo satisface.
Nombre: Roles
Tipo: string?
Nombre: TypeId
Tipo: Object

Métodos

Nombre
Parámetros
Tipo
Descripción
IsDefaultAttributebool
MatchObject obj
bool
Nombre: IsDefaultAttribute
Tipo: bool
Nombre: Match
Parámetros: Object obj
Tipo: bool

ITablePermissionProvider Interface

Propiedades

Nombre
Tipo
Default
Descripción
Tablestring
Nombre lógico de la tabla a la que se aplica este proveedor. Coincide exactamente, así que debe ser el Nombre lógico de Dataverse en minúsculas.
Nombre: Table
Tipo: string
Descripción: Nombre lógico de la tabla a la que se aplica este proveedor. Coincide exactamente, así que debe ser el Nombre lógico de Dataverse en minúsculas.

Métodos

Nombre
Parámetros
Tipo
Descripción
GetPermissionsAsyncUserInfo user
Task<TablePermissions>
Qué user puede hacer con esta tabla y cuál de sus columnas pueden leer y escribir. Volver TablePermissions.None para un usuario que no debería tener acceso. Las operaciones son una puerta a nivel de tabla, no un filtro de fila: conceder TableSecurityPermission.Read si el usuario puede ver alguno de los tablones filas y alcance cuáles son en Services.TableQueryContext). Las columnas son opcionales. Nada es legible ni escribible hasta que se nombra — lo que concede TableSecurityPermission.Read Alone solo expone el ID del registro. Usar Reading(System.String[]) y Writing(System.String[]) nombrarles, o TablePermissions.AllColumns para optar por no tener la seguridad de columna en esta tabla. Un proveedor que solo existe para definir filas puede dejar las columnas intactas — ni hablar sobre ellos y compone como una opinión sin ampliar ni estrechar lo que la otra Proveedores sobre la mesa concedidos. No decir nada sigue siendo fallido-cerrado en general: cuando no El proveedor nombra una columna, ninguna es legible. Se llama una vez por tabla por usuario y se guarda en caché para la solicitud, así que puede ser tan caro como tiene que serlo.
GetQueryFilterAsyncTableQueryContext context
Task<TableQueryFilter>
Ámbitos en qué filas de esta tabla el usuario puede actuar: un filtro construido con Query.LogicalOperator), TableQueryFilter.AllRows para cada rema según las operaciones permitan o nullpara no tener filas. Las filas no se cierran. Un proveedor tiene que decir qué filas concede, igual que debe hacerlo Nombra las columnas: null — o un filtro sin condiciones — no concede ninguna, así que Olvidar poner el alcance de una tabla lo niega en lugar de publicar cada fila. Por ejemplo, TableQueryFilter.AllRows Cuando cada disputa es lo que quieres decir. El filtro se añade a la consulta antes de que Dataverse la ejecute, por lo que las filas que el usuario puede no ver son nunca se recoge. Se aplica a todas las consultas que el portal emite para la tabla: cuadrículas, consultas, subrejillas, gráficos y cargas de un solo registro, además de la búsqueda previa al vuelo antes de una actualización o un eliminar — que es lo que TableQueryContext.Operation distingue. También ejecuta bajo ambos modelos de seguridad, por lo que sigue vigente cuando la seguridad nativa de Dataverse evita Services.UserInfo). El marco decide cómo se combinan los filtros, no el proveedor. Filtros de proveedores en el mismo grupo se intersectan — dos proveedores en un mismo rol deben estar de acuerdo. Filtros de diferentes roles sindicalizados, así que ocupar otro rol amplía lo que ves, coincidiendo con cómo las operaciones componen. Ajusta PortalRoleOptions.CompositionBehavior a RoleCompositionBehavior.Restrictive Que también se cruzen entre roles. Dentro de un grupo, un proveedor que null responde no deja filas al grupo, y TableQueryFilter.AllRows deja que los filtros de los demás proveedores decidan. A lo largo Grupos, un grupo que concede TableQueryFilter.AllRows amplía el aditivo por defecto Unión a cada fila — así que el filtro de un rol solo significa algo cuando los otros grupos conceden Ese filtro de mesa también.
Nombre: GetPermissionsAsync
Parámetros: UserInfo user
Tipo: Task<TablePermissions>
Descripción: Qué user puede hacer con esta tabla y cuál de sus columnas pueden leer y escribir. Volver TablePermissions.None para un usuario que no debería tener acceso. Las operaciones son una puerta a nivel de tabla, no un filtro de fila: conceder TableSecurityPermission.Read si el usuario puede ver alguno de los tablones filas y alcance cuáles son en Services.TableQueryContext). Las columnas son opcionales. Nada es legible ni escribible hasta que se nombra — lo que concede TableSecurityPermission.Read Alone solo expone el ID del registro. Usar Reading(System.String[]) y Writing(System.String[]) nombrarles, o TablePermissions.AllColumns para optar por no tener la seguridad de columna en esta tabla. Un proveedor que solo existe para definir filas puede dejar las columnas intactas — ni hablar sobre ellos y compone como una opinión sin ampliar ni estrechar lo que la otra Proveedores sobre la mesa concedidos. No decir nada sigue siendo fallido-cerrado en general: cuando no El proveedor nombra una columna, ninguna es legible. Se llama una vez por tabla por usuario y se guarda en caché para la solicitud, así que puede ser tan caro como tiene que serlo.
Nombre: GetQueryFilterAsync
Parámetros: TableQueryContext context
Tipo: Task<TableQueryFilter>
Descripción: Ámbitos en qué filas de esta tabla el usuario puede actuar: un filtro construido con Query.LogicalOperator), TableQueryFilter.AllRows para cada rema según las operaciones permitan o nullpara no tener filas. Las filas no se cierran. Un proveedor tiene que decir qué filas concede, igual que debe hacerlo Nombra las columnas: null — o un filtro sin condiciones — no concede ninguna, así que Olvidar poner el alcance de una tabla lo niega en lugar de publicar cada fila. Por ejemplo, TableQueryFilter.AllRows Cuando cada disputa es lo que quieres decir. El filtro se añade a la consulta antes de que Dataverse la ejecute, por lo que las filas que el usuario puede no ver son nunca se recoge. Se aplica a todas las consultas que el portal emite para la tabla: cuadrículas, consultas, subrejillas, gráficos y cargas de un solo registro, además de la búsqueda previa al vuelo antes de una actualización o un eliminar — que es lo que TableQueryContext.Operation distingue. También ejecuta bajo ambos modelos de seguridad, por lo que sigue vigente cuando la seguridad nativa de Dataverse evita Services.UserInfo). El marco decide cómo se combinan los filtros, no el proveedor. Filtros de proveedores en el mismo grupo se intersectan — dos proveedores en un mismo rol deben estar de acuerdo. Filtros de diferentes roles sindicalizados, así que ocupar otro rol amplía lo que ves, coincidiendo con cómo las operaciones componen. Ajusta PortalRoleOptions.CompositionBehavior a RoleCompositionBehavior.Restrictive Que también se cruzen entre roles. Dentro de un grupo, un proveedor que null responde no deja filas al grupo, y TableQueryFilter.AllRows deja que los filtros de los demás proveedores decidan. A lo largo Grupos, un grupo que concede TableQueryFilter.AllRows amplía el aditivo por defecto Unión a cada fila — así que el filtro de un rol solo significa algo cuando los otros grupos conceden Ese filtro de mesa también.

TablePermissions Clase

Propiedades

Nombre
Tipo
Default
Descripción
ColumnsTableColumnPermissions
Las columnas que el usuario puede leer y escribir. TableColumnPermissions.None a menos que Algo llamado ellos: Se concede acceso a columnas, nunca se asume.
OperationsTableSecurityPermission
Las operaciones que el usuario puede realizar sobre la tabla como un valor de bandera. Esto es un valor a nivel de tabla gate, no un filtro de fila — incluyelo TableSecurityPermission.Read si el usuario puede ver cualquiera de las filas de la tabla y ampliar cuáles pasan por Services.TableQueryContext).
Nombre: Columns
Tipo: TableColumnPermissions
Descripción: Las columnas que el usuario puede leer y escribir. TableColumnPermissions.None a menos que Algo llamado ellos: Se concede acceso a columnas, nunca se asume.
Nombre: Operations
Tipo: TableSecurityPermission
Descripción: Las operaciones que el usuario puede realizar sobre la tabla como un valor de bandera. Esto es un valor a nivel de tabla gate, no un filtro de fila — incluyelo TableSecurityPermission.Read si el usuario puede ver cualquiera de las filas de la tabla y ampliar cuáles pasan por Services.TableQueryContext).

Métodos

Nombre
Parámetros
Tipo
Descripción
AllColumnsTablePermissions
Opta por no participar en la seguridad a nivel de columna — cada columna es legible y se puede escribir. El Comportamiento previo a la seguridad de columnas, explicado en lugar de heredado.
AllowTableSecurityPermission operations
TablePermissions
Añade operations a lo que este valor ya aporta.
AllowingTableSecurityPermission operations
TablePermissions
Concesiones operations y sin columnas. Cadena Reading(System.String[]), Writing(System.String[]) O TablePermissions.ReadingAllColumns para abrir columnas.
Readingstring[] columns
TablePermissions
Permite leer las columnas nombradas, además de las ya permitidas. Insensible a mayúsculas y mayúsculas, Así que la ortografía del portal del creador funciona tan bien como el nombre lógico.
ReadingAllColumnsTablePermissions
Opta por no tener seguridad de lectura a nivel de columna para esta tabla: cada columna, incluidas las añadidas a la mesa más tarde. Deliberadamente explícito — el marco no lo asumirá.
ReadingAllColumnsExceptstring[] columns
TablePermissions
Opta por no participar en la seguridad de lectura a nivel de columna excepto para las columnas nombradas — todas las columnas excepto Estos, incluidos los añadidos después. No se abre para nada nuevo, así que prefiero Reading(System.String[]) en tablas que contienen datos sensibles.
ReadingAndWritingstring[] columns
TablePermissions
Permite tanto leer como escribir las columnas nombradas.
WithColumnsTableColumnPermissions columns
TablePermissions
Sustituye las reglas de columna al por mayor, para un proveedor que preferiría construir un Services.TableColumnPermissions a sí mismo que encadenar los métodos fluidos.
WithholdingWithheldColumnBehavior behavior
TablePermissions
Cómo las columnas retenidas de esta tabla vuelven — omitidas, o presentadas con un valor enmascarado. Anula la regla de todo SecurityOptions.WithheldColumnBehavior el sitio para esta tabla.
Writingstring[] columns
TablePermissions
Permite escribir las columnas nombradas — cuando se crea un registro y cuando se actualiza — en Además de cualquiera ya permitida. Escribir una columna no implica leerla — nombrala en Reading(System.String[]) también si el usuario ve lo que escribieron.
WritingAllColumnsTablePermissions
Opta por no tener seguridad de escritura a nivel de columna para esta tabla: el usuario puede escribir cualquier columna, al crear y al actualizar. Reemplaza ambos conjuntos de escritura, así que llama WritingOnCreate(System.String[]) / WritingOnUpdate(System.String[]) después, no antes.
WritingAllColumnsExceptstring[] columns
TablePermissions
Opta por no participar en la seguridad de escritura a nivel de columna, excepto en las columnas nombradas, que permanecen en modo solo lectura. Reemplaza ambos conjuntos de escritura, así que llama WritingOnCreate(System.String[]) / WritingOnUpdate(System.String[]) Después de ella, no antes.
WritingOnCreatestring[] columns
TablePermissions
Permite establecer las columnas nombradas cuando se crea un registro, y solo entonces: una vez que exista son de solo lectura, incluso si una llamada anterior — Writing(System.String[]), TablePermissions.WritingAllColumns — los hacía escribibles. La prioridad de un caso, elegido cuando lo es Registrado y corregido a partir de entonces. Llámalo después de cualquier WritingAllColumn..., que sustituye Ambos escriben conjuntos. Por ejemplo Writing(System.String[]), no implica lectura.
WritingOnUpdatestring[] columns
TablePermissions
Permite cambiar las columnas nombradas en un registro existente, pero no configurarlas cuando está creadas, incluso si una llamada anterior las hiciera escribibles — notas de resolución que solo significan algo que una vez que el caso existe. Llámalo después de cualquier WritingAllColumn..., que sustituye Ambos escriben conjuntos. Por ejemplo Writing(System.String[]), no implica lectura.
Nombre: AllColumns
Tipo: TablePermissions
Descripción: Opta por no participar en la seguridad a nivel de columna — cada columna es legible y se puede escribir. El Comportamiento previo a la seguridad de columnas, explicado en lugar de heredado.
Nombre: Allow
Parámetros: TableSecurityPermission operations
Tipo: TablePermissions
Descripción: Añade operations a lo que este valor ya aporta.
Nombre: Allowing
Parámetros: TableSecurityPermission operations
Tipo: TablePermissions
Descripción: Concesiones operations y sin columnas. Cadena Reading(System.String[]), Writing(System.String[]) O TablePermissions.ReadingAllColumns para abrir columnas.
Nombre: Reading
Parámetros: string[] columns
Tipo: TablePermissions
Descripción: Permite leer las columnas nombradas, además de las ya permitidas. Insensible a mayúsculas y mayúsculas, Así que la ortografía del portal del creador funciona tan bien como el nombre lógico.
Nombre: ReadingAllColumns
Tipo: TablePermissions
Descripción: Opta por no tener seguridad de lectura a nivel de columna para esta tabla: cada columna, incluidas las añadidas a la mesa más tarde. Deliberadamente explícito — el marco no lo asumirá.
Nombre: ReadingAllColumnsExcept
Parámetros: string[] columns
Tipo: TablePermissions
Descripción: Opta por no participar en la seguridad de lectura a nivel de columna excepto para las columnas nombradas — todas las columnas excepto Estos, incluidos los añadidos después. No se abre para nada nuevo, así que prefiero Reading(System.String[]) en tablas que contienen datos sensibles.
Nombre: ReadingAndWriting
Parámetros: string[] columns
Tipo: TablePermissions
Descripción: Permite tanto leer como escribir las columnas nombradas.
Nombre: WithColumns
Parámetros: TableColumnPermissions columns
Tipo: TablePermissions
Descripción: Sustituye las reglas de columna al por mayor, para un proveedor que preferiría construir un Services.TableColumnPermissions a sí mismo que encadenar los métodos fluidos.
Nombre: Withholding
Parámetros: WithheldColumnBehavior behavior
Tipo: TablePermissions
Descripción: Cómo las columnas retenidas de esta tabla vuelven — omitidas, o presentadas con un valor enmascarado. Anula la regla de todo SecurityOptions.WithheldColumnBehavior el sitio para esta tabla.
Nombre: Writing
Parámetros: string[] columns
Tipo: TablePermissions
Descripción: Permite escribir las columnas nombradas — cuando se crea un registro y cuando se actualiza — en Además de cualquiera ya permitida. Escribir una columna no implica leerla — nombrala en Reading(System.String[]) también si el usuario ve lo que escribieron.
Nombre: WritingAllColumns
Tipo: TablePermissions
Descripción: Opta por no tener seguridad de escritura a nivel de columna para esta tabla: el usuario puede escribir cualquier columna, al crear y al actualizar. Reemplaza ambos conjuntos de escritura, así que llama WritingOnCreate(System.String[]) / WritingOnUpdate(System.String[]) después, no antes.
Nombre: WritingAllColumnsExcept
Parámetros: string[] columns
Tipo: TablePermissions
Descripción: Opta por no participar en la seguridad de escritura a nivel de columna, excepto en las columnas nombradas, que permanecen en modo solo lectura. Reemplaza ambos conjuntos de escritura, así que llama WritingOnCreate(System.String[]) / WritingOnUpdate(System.String[]) Después de ella, no antes.
Nombre: WritingOnCreate
Parámetros: string[] columns
Tipo: TablePermissions
Descripción: Permite establecer las columnas nombradas cuando se crea un registro, y solo entonces: una vez que exista son de solo lectura, incluso si una llamada anterior — Writing(System.String[]), TablePermissions.WritingAllColumns — los hacía escribibles. La prioridad de un caso, elegido cuando lo es Registrado y corregido a partir de entonces. Llámalo después de cualquier WritingAllColumn..., que sustituye Ambos escriben conjuntos. Por ejemplo Writing(System.String[]), no implica lectura.
Nombre: WritingOnUpdate
Parámetros: string[] columns
Tipo: TablePermissions
Descripción: Permite cambiar las columnas nombradas en un registro existente, pero no configurarlas cuando está creadas, incluso si una llamada anterior las hiciera escribibles — notas de resolución que solo significan algo que una vez que el caso existe. Llámalo después de cualquier WritingAllColumn..., que sustituye Ambos escriben conjuntos. Por ejemplo Writing(System.String[]), no implica lectura.

AuthClientOptions Clase

Propiedades

Nombre
Tipo
Default
Descripción
LocalAccountsEnabledbool
True
Si el portal acepta cuentas locales de usuario/contraseña. Por defecto cierto. Configura en falso para un portal solo interno (solo inicio de sesión de Microsoft/Entra). Esto desactiva las cuentas locales en el servidor, no solo en la interfaz. MapAuthEndpoints no asigna el inicio de sesión de contraseñas, registro, restablecimiento de contraseña, configuración o cambio de una contraseña, o gestión de dos factores, así que esas rutas 404. La capa de identidad del portal también rechaza iniciar sesión con contraseña y se niega a crear, añadir, cambiar o restablecer una contraseña, que también cubre páginas de cuentas renderizadas por servidores. Inicia sesión a través de proveedores externos, confirmación de correo electrónico, gestión de perfiles, inicio de sesión externo, descarga de datos personales y La eliminación de cuentas no se ve afectada. Los clientes lo leen para ocultar el formulario local de inicio de sesión y las páginas de registro/restablecimiento de contraseña. Las contraseñas ya almacenadas de cuentas existentes permanecen en Dataverse pero ya no pueden estarlo. Antes iniciaba sesión.
SignUpEnabledbool
True
Si iniciar sesión puede crear un usuario del portal. Por defecto cierto: cualquiera que se registre, o Inicia sesión a través de un proveedor externo con una dirección que no tiene contacto, y consigue un nuevo contacto. Configura en falso para que solo las personas que ya tengan contacto puedan iniciar sesión. Con él desactivado, un inicio de sesión externo sigue coincidiendo con un contacto existente — por un enlace anterior, o por las columnas de correo electrónico en SecurityOptions.ContactMatching — y enlaces a él, enviando un Confirmación primero cuando el proveedor no avaló la dirección. Un inicio de sesión que nadie coincide se niega en lugar de crear un contacto. La persona que inicia sesión solo recibe el mensaje cuando el el proveedor verificó la dirección; de lo contrario, la dirección recibe un aviso por correo y el inicio de sesión es respondió que coincidía, así que el formulario no puede usarse para saber qué direcciones tienen un contacto. MapAuthEndpoints no mapea el registro, así que la ruta 404s, y la la capa de Identidad del portal se niega a crear ningún usuario, lo que cubre cuentas renderizadas por el servidor Páginas también. Los clientes lo leen para ocultar la página de registro y el enlace, y para explicar un inicio de sesión denegado.
Nombre: LocalAccountsEnabled
Tipo: bool
Default: True
Descripción: Si el portal acepta cuentas locales de usuario/contraseña. Por defecto cierto. Configura en falso para un portal solo interno (solo inicio de sesión de Microsoft/Entra). Esto desactiva las cuentas locales en el servidor, no solo en la interfaz. MapAuthEndpoints no asigna el inicio de sesión de contraseñas, registro, restablecimiento de contraseña, configuración o cambio de una contraseña, o gestión de dos factores, así que esas rutas 404. La capa de identidad del portal también rechaza iniciar sesión con contraseña y se niega a crear, añadir, cambiar o restablecer una contraseña, que también cubre páginas de cuentas renderizadas por servidores. Inicia sesión a través de proveedores externos, confirmación de correo electrónico, gestión de perfiles, inicio de sesión externo, descarga de datos personales y La eliminación de cuentas no se ve afectada. Los clientes lo leen para ocultar el formulario local de inicio de sesión y las páginas de registro/restablecimiento de contraseña. Las contraseñas ya almacenadas de cuentas existentes permanecen en Dataverse pero ya no pueden estarlo. Antes iniciaba sesión.
Nombre: SignUpEnabled
Tipo: bool
Default: True
Descripción: Si iniciar sesión puede crear un usuario del portal. Por defecto cierto: cualquiera que se registre, o Inicia sesión a través de un proveedor externo con una dirección que no tiene contacto, y consigue un nuevo contacto. Configura en falso para que solo las personas que ya tengan contacto puedan iniciar sesión. Con él desactivado, un inicio de sesión externo sigue coincidiendo con un contacto existente — por un enlace anterior, o por las columnas de correo electrónico en SecurityOptions.ContactMatching — y enlaces a él, enviando un Confirmación primero cuando el proveedor no avaló la dirección. Un inicio de sesión que nadie coincide se niega en lugar de crear un contacto. La persona que inicia sesión solo recibe el mensaje cuando el el proveedor verificó la dirección; de lo contrario, la dirección recibe un aviso por correo y el inicio de sesión es respondió que coincidía, así que el formulario no puede usarse para saber qué direcciones tienen un contacto. MapAuthEndpoints no mapea el registro, así que la ruta 404s, y la la capa de Identidad del portal se niega a crear ningún usuario, lo que cubre cuentas renderizadas por el servidor Páginas también. Los clientes lo leen para ocultar la página de registro y el enlace, y para explicar un inicio de sesión denegado.