¿Por qué no exponer una clave principal?

48

En mi educación me han dicho que es una idea defectuosa exponer las claves primarias reales (no solo las claves de DB, sino todos los accesores primarios) al usuario.

Siempre pensé que era un problema de seguridad (porque un atacante podría intentar leer cosas que no son las suyas).

Ahora tengo que comprobar si el usuario tiene permiso para acceder de todas formas, ¿hay alguna otra razón?

Además, como mis usuarios tienen que acceder a los datos de todos modos, necesitaré una clave pública para el mundo exterior en algún punto intermedio. Ahora que la clave pública tiene los mismos problemas que la clave principal, ¿no es así?

Se ha solicitado un ejemplo sobre por qué hacerlo de todos modos, así que aquí hay uno. Tenga en cuenta que la pregunta tiene que ver con el principio en sí, no solo si se aplica en este ejemplo. Las respuestas a otras situaciones son explícitamente bienvenidas.

La aplicación (web, móvil) que maneja la actividad, tiene múltiples interfaces de usuario y al menos una API automatizada para la comunicación entre sistemas (por ejemplo, el departamento de contabilidad quiere saber cuánto cobrar al cliente según lo que se ha hecho). La aplicación tiene varios clientes, por lo que la separación de sus datos (lógicamente, los datos se almacenan en la misma base de datos) es una necesidad del sistema. Se comprobará la validez de cada solicitud, sin importar qué.

La actividad es muy fina granular, por lo que está junta en algún objeto contenedor, llamémosla "Tarea".

Tres casos de uso:

  1. El usuario A quiere enviar al usuario B a alguna tarea, por lo que le envía un enlace (HTTP) para que realice alguna actividad allí.
  2. El usuario B tiene que salir del edificio para que abra la Tarea en su dispositivo móvil.
  3. La contabilidad quiere cobrar al cliente por la Tarea, pero utiliza un sistema de contabilidad de terceros que carga automáticamente la Tarea / Actividad mediante algún código que se refiere a la API REST - de la aplicación

Cada una de las casos de uso requiere (o se vuelve más fácil si) el agente para tener algún identificador direccionable para la Tarea y la Actividad.

    
pregunta Angelo Fuchs 13.11.2013 - 07:49

9 respuestas

5

Esta es una respuesta combinada de las otras (también conocido como lo que he aprendido). Si tiene ganas de emitir este voto, debe al menos votar uno de los otros, así como el trabajo real. Si estás más interesado, lee las otras respuestas en su lugar.

No debe exponer la clave principal de la base de datos, sino que debe utilizar una clave sustituta

  1. Si desea que sus usuarios puedan recordar (al menos un poco) o reconocer el identificador de una entrada. ( Respuesta de Graystone28s )
  2. Si desea planificar por adelantado y considera que podría cambiar los sistemas (Base de datos u otros) que probablemente cambiarán su PK. ( Respuesta de Telastyns )
  3. Si desea asegurarse de que sus usuarios tengan una forma consistente de acceder a los datos que no cambiarán, incluso si su compañía cambia de propietario y los datos se migran a un sistema diferente por completo. ( Respuesta de Michael Durrants )
  4. Si su PK es predecible (como una secuencia), su sistema puede sufrir problemas de recolección de recursos. ( Respuesta de CodeCasters ) Esto solo se aplica si su sistema tiene información que vale la pena recopilar y que cualquiera puede acceder a ella. Al menos alguien que tenga un interés en la cosecha.

Nota: Su clave creada debe ser (un poco) humana comprensible ( Respuesta de Sqlvogels ).

Si su sistema no necesita de 1 a 4, entonces no hay razón para no usar las bases de datos PK como su identificador público (varias de las respuestas). Además, la seguridad no es un problema aquí (varias de las respuestas).

    
respondido por el Angelo Fuchs 14.11.2013 - 10:17
33
  

Además, como mis usuarios tienen que acceder a los datos de todos modos, necesitaré una clave pública para el mundo exterior en algún punto intermedio.

Exactamente. Tome el HTTP sin estado, que de otro modo no sabría qué recurso debería solicitar: expone el ID de su pregunta 218306 en la URL. ¿Quizás realmente se esté preguntando si un identificador expuesto puede ser predecible ?

Los únicos lugares donde escuché una respuesta negativa a eso, usaron la lógica: "¡Pero pueden cambiar la ID en la URL!" . Así que utilizaron GUID en lugar de implementar la autorización adecuada.

Puedo imaginar una situación en la que no desea que sus identificadores sean predecibles: la recolección de recursos. Si tiene un sitio que aloja públicamente ciertos recursos, puede que le interesen otros, y los aloja como /images/n.jpg o /videos/n.mp4 , donde n es un número creciente, cualquier persona que busque tráfico hacia y desde su sitio web puede cosechar todo tus recursos

Entonces, para responder directamente a su pregunta: no, no es malo "exponer" directamente los identificadores que solo tienen un significado para su programa, por lo general, incluso es necesario para que su programa funcione correctamente.

    
respondido por el CodeCaster 13.11.2013 - 09:52
28

No debe exponerlo porque las personas que lo vean comenzarán a utilizarlo como su 'número de cuenta', que NO es. Por ejemplo, para mi cuenta bancaria sé cuál es mi número de cuenta. Lo he memorizado, lo uso en el teléfono con el servicio al cliente, lo uso al completar formularios para que otros bancos realicen transferencias, para documentos legales, para mi servicio de pago automático, etc., etc. No quiero para cambiar La clave principal (para mi cuenta), por otro lado, no la conozco o nunca la veo.
El sistema que lo almacena cambia a lo largo de los años de un sistema a otro, a través de fusiones bancarias, actualizaciones y reemplazos del sistema, etc., etc. Las claves primarias pueden cambiar a través de algunas de estas transformaciones, por lo que si nunca han sido expuestas, escritas o recordadas por algún usuario regular, eso es algo realmente bueno .
Las claves que no tienen un significado comercial a menudo se denominan claves sustitutas y a menudo (pero no siempre) se utilizan como claves principales.

por cierto, esto incluso ocurre internamente cuando las personas construyen interfaces y programas que hacen mal uso y exponen las claves primarias y las hacen parte de dichos sistemas en lugar de que solo hagan una cosa: identificar de forma exclusiva un registro de base de datos internamente. De hecho, aprendí lo anterior a lo largo de un período de 6 años en un hospital que almacena datos.

    
respondido por el Michael Durrant 13.11.2013 - 20:09
22

Porque las claves primarias son un detalle de implementación.

Si migra bases de datos, sus claves principales pueden cambiar debido al orden de inserción, eliminación de registros antiguos ... por varias razones diferentes. Si migra la base de datos plataformas , es posible que ya no tenga una clave principal real. Exponer la PK sobre la capa de acceso a datos es una abstracción con fugas, con todas las preocupaciones de acoplamiento que conlleva.

    
respondido por el Telastyn 13.11.2013 - 15:05
8

Una de las razones que he encontrado, en la plenitud del tiempo que he visto a los usuarios finales solicitar que su identificador signifique algo (como tener un prefijo o un indicador del año en que se inició). Cambiar un PK es difícil, pero un sustituto es mucho más fácil.

Es probable que su clave principal sea algo en lo que desee que se indexe su base de datos por razones de rendimiento, y puede cambiar a tiempo por razones técnicas, por ejemplo, de un número a un guid ... simplemente no sabe qué razones hay nuevas Las tecnologías o el conocimiento pueden guiarte hacia abajo. Su pk es su elemento técnico de datos, la clave pública es para el consumo de los usuarios finales.

    
respondido por el Wayne M 13.11.2013 - 12:50
1

Esto es de un comentario en la respuesta de Greystone28 por CodeCaster. Es un ejemplo de lo que estás diciendo:

  

Expongo InvoiceNumber, que tiene un significado y es modificable por   El cliente, pero también expongo InvoiceID, que mi código utiliza para   Identificar de forma única la factura. No tienes que (y más a menudo no   desea) dejar que la clave de usuario sea la clave de almacenamiento. Esta pregunta es sobre este último.

¿Cuál es el propósito de su aplicación para mostrar la InvoiceID?

Al exponer, supongo que quiere decir que el usuario puede verlo. Solo expóngalo si el usuario lo necesita para usar su aplicación. Podría ser utilizado por el soporte técnico o algunas cosas administrativas. He trabajado con algunas aplicaciones que hacen esto. Facilita la prestación de asistencia cuando conozco el registro específico en cuestión.

    
respondido por el JeffO 13.11.2013 - 14:58
1

Para la mayoría de las aplicaciones, es fundamental que exponga las claves a los usuarios. Para usar un sistema de información de manera efectiva, los usuarios de ese sistema normalmente necesitarán una forma de identificar la información que contiene y relacionar esa información con algo en el mundo fuera de la base de datos. En términos de bases de datos relacionales, esos identificadores son claves.

Un patrón de diseño bien utilizado es crear una clave adicional, puramente "técnica" para las tablas de base de datos como medio de abstracción. Por ejemplo, para proporcionar una clave estable (relativamente invariable) donde alguna clave alternativa está sujeta a cambios. Estas claves técnicas normalmente no están expuestas a los usuarios finales porque al hacerlo, socava la abstracción prevista de los requisitos del usuario. No tiene nada que ver con la seguridad.

El problema / malentendido implícito en su pregunta se debe al uso inadecuado del término primario . Una clave principal es solo una entre varias claves "candidatas" (varios identificadores posibles en una tabla de base de datos). La clave principal no requiere necesariamente ninguna propiedad fundamentalmente diferente a cualquier otra clave, por lo que las afirmaciones y los principios de diseño que se aplican específicamente a las claves primarias y no a otras claves son siempre sospechosos y, a menudo, incorrectos.

Dado que normalmente necesitará exponer una clave a su usuario, ¿cuál debería ser esa clave? Trate de hacer sus llaves familiar, simple y estable. La familiaridad y la simplicidad hacen que las claves sean fáciles de leer y recordar y ayudarán a evitar errores de entrada de datos. Estabilidad significa que los cambios clave con poca frecuencia también ayudan a evitar la posibilidad de identificación errónea.

    
respondido por el nvogel 13.11.2013 - 16:31
1

Es completamente normal que las entidades tengan un identificador único que esté expuesto al mundo exterior. Para algunos objetos podría ser posible encontrar un identificador que realmente tenga un significado (por ejemplo, número de factura), pero para otros no existe dicho identificador y, por lo tanto, debe generarse.

En aras de la coherencia y la legibilidad, me parece una buena práctica que todas las entidades en un sistema utilicen exactamente el mismo tipo y nombre para su identificador. Normalmente, este identificador estaría expuesto ( <type> getId() ) en alguna clase base abstracta.

Por la misma razón, cada servicio en el sistema (por ejemplo, el servicio de facturación) debe proporcionar métodos idénticos para acceder a las entidades por su identificador. Normalmente, este método ( findById(<type> id) ) se heredará de una interfaz de servicio genérica o una clase base.

Este identificador no tiene que ser la clave principal de la entidad, pero puede ser una. Lo único que uno tiene que asegurar es que la estrategia de generación de claves produzca identificadores razonablemente únicos (no necesariamente universales, pero al menos dentro del sistema).

Si el sistema se migra más tarde (grande si es mi experiencia) a otra base de datos, entonces no es un problema usar una estrategia diferente (no basada en claves primarias) para crear los identificadores siempre que la estrategia sea compatible con la original uno.

    
respondido por el Muton 14.11.2013 - 13:21
0

La clave principal está ahí, como un identificador de la tupla (registro, fila) a la que intentas acceder como desarrollador. También se usa en integridad referencial (restricciones de clave externa), y quizás tenga uno o más casos de uso también.

Esencialmente, no hay nada malo en exponerlo a los usuarios, o incluso a los hackers. Porque no conozco un ataque que use clave principal, por ejemplo.

Pero en seguridad, tenemos muchos principios (que aceptamos y no aprobamos) y debemos cumplirlos:

  1. El principio del privilegio de arrendamiento
  2. Seguridad a través de la oscuridad

Y algunos otros principios. Lo que dicen esencialmente es que:

Si no necesita exponer sus datos, ¿por qué lo haría?

    
respondido por el Saeed Neamati 13.11.2013 - 18:09

Lea otras preguntas en las etiquetas