web-dev-qa-db-fra.com

Pourquoi ne pas exposer une clé primaire

Dans mon éducation, on m'a dit que c'est une idée erronée d'exposer les clés primaires réelles (non seulement les clés de base de données, mais tous les accesseurs principaux) à l'utilisateur.

J'ai toujours pensé que c'était un problème de sécurité (car un attaquant pourrait tenter de lire des trucs pas les leurs).

Maintenant, je dois vérifier si l'utilisateur est autorisé à accéder de toute façon, alors y a-t-il une raison différente derrière cela?

De plus, comme mes utilisateurs doivent accéder aux données de toute façon, je devrai avoir une clé publique pour le monde extérieur quelque part entre les deux. Maintenant, cette clé publique a les mêmes problèmes que la clé primaire, n'est-ce pas?


Il y a eu la demande d'un exemple expliquant pourquoi faire de toute façon, alors en voici un. Gardez à l'esprit que la question porte sur le principe lui-même, non seulement s'il s'applique dans cet exemple. Les réponses concernant d'autres situations sont explicitement les bienvenues.

Application (Web, Mobile) qui gère l'activité, possède plusieurs interfaces utilisateur et au moins une API automatisée pour la communication intersystèmes (par exemple, le service comptable veut savoir combien facturer le client en fonction de ce qui a été fait). L'application a plusieurs clients, donc la séparation de leurs données (logiquement, les données sont stockées dans la même base de données) est un must have du système. La validité de chaque demande sera vérifiée quoi qu'il arrive.

L'activité est très fine, donc elle est ensemble dans un objet conteneur, appelons-la "Tâche".

Trois cas d'utilisation:

  1. L'utilisateur A veut envoyer l'utilisateur B à une tâche, il lui envoie donc un lien (HTTP) pour y effectuer une activité.
  2. L'utilisateur B doit sortir du bâtiment pour ouvrir la tâche sur son appareil mobile.
  3. La comptabilité veut facturer le client pour la tâche, mais utilise un système de comptabilité tiers qui charge automatiquement la tâche/l'activité par un code qui fait référence à REST - API de l'application

Chacun des cas d'utilisation nécessite (ou devient plus facile si) l'agent doit avoir un identifiant adressable pour la tâche et l'activité.

54
Angelo Fuchs

Ceci est une réponse combinée des autres (aka. Ce que j'ai appris). Si vous avez envie de voter pour celui-ci, vous devriez au moins voter pour l'un des autres ainsi que pour le travail réel. Si vous êtes plus intéressé, lisez plutôt les autres réponses.

Vous ne devez pas exposer la clé primaire de la base de données mais utiliser à la place une clé de substitution

  1. Si vous souhaitez que vos utilisateurs se souviennent (au moins un peu) ou reconnaissent l'identifiant d'une entrée. ( Réponse de Graystone28s )
  2. Si vous souhaitez planifier à l'avance et envisager de changer de système (base de données ou autre), cela changera probablement votre PK. ( Réponse Telastyns )
  3. Si vous voulez vous assurer que vos utilisateurs ont un moyen cohérent d'accéder aux données qui ne changeront pas même si votre entreprise change de propriétaire et que les données sont migrées par milliers vers un système différent. ( Réponse de Michael Durrants )
  4. Si votre PK est prévisible (comme une séquence), votre système peut souffrir de problèmes de récolte de ressources. ( Réponse CodeCasters ) Cela ne s'applique que si votre système contient des informations qui méritent d'être récoltées et qui sont accessibles à toute personne ou au moins à toute personne intéressée par la récolte.

Remarque: Votre clé créée doit être (un peu) compréhensible par l'homme ( Sqlvogels Answer ).

Si votre système n'a pas besoin de 1. à 4. alors il n'y a aucune raison de ne pas utiliser les bases de données PK comme identifiant public (plusieurs des réponses). La sécurité n'est pas non plus un problème ici (plusieurs des réponses).

10
Angelo Fuchs

De plus, comme mes utilisateurs doivent accéder aux données de toute façon, je devrai avoir une clé publique pour le monde extérieur quelque part entre les deux.

Exactement. Prenez le HTTP sans état, qui autrement ne saurait pas quelle ressource il devrait demander: il expose l'ID de votre question 218306 dans l'URL. Vous vous demandez peut-être si un identifiant exposé peut être prévisible?

Les seuls endroits où j'ai entendu une réponse négative à cela, ont utilisé la justification: "Mais ils peuvent changer l'ID dans l'URL!". Ils ont donc utilisé des GUID au lieu de mettre en œuvre une autorisation appropriée.

Je peux imaginer une situation où vous ne voulez pas que vos identifiants soient prévisibles: la récolte des ressources. Si vous avez un site qui héberge publiquement certaines ressources, d'autres peuvent être intéressantes et que vous les hébergez comme /images/n.jpg ou /videos/n.mp4n est juste un nombre incrémentiel, toute personne qui regarde le trafic vers et depuis votre site Web peut récolter toutes vos ressources.

Donc, pour répondre directement à votre question: non, il n'est pas mauvais d'exposer directement des identifiants qui n'ont de sens que pour votre programme, généralement il est même nécessaire pour que votre programme fonctionne correctement.

40
CodeCaster

Vous ne devriez pas l'exposer, car les personnes qui le verront commenceront à l'utiliser comme leur "numéro de compte", ce qui n'est PAS le cas. Par exemple, pour mon compte bancaire, je sais quel est mon numéro de compte. Je l'ai mémorisé, je l'utilise au téléphone avec le service client, je l'utilise lorsque je remplis des formulaires pour que d'autres banques fassent des virements, pour des documents juridiques, pour mon service de paiement automatique, etc., etc. Je ne veux pas pour changer. Par contre, la clé primaire (pour mon compte), je ne la connais pas ou je ne la vois jamais.
Le système qui le stocke change au fil des ans d'un système à l'autre, par le biais de fusions bancaires, de mises à niveau et de remplacements de systèmes, etc., etc.
Les clés primaires peuvent changer à travers certaines de ces transformations, donc si elles n'ont jamais été exposées, écrites ou mémorisées par un utilisateur régulier, c'est une vraie bonne chose .
Les clés sans signification commerciale sont souvent appelées clés de substitution et sont souvent (mais pas toujours) utilisées comme clés primaires.

btw, cela se produit même en interne lorsque les gens ont créé des interfaces et des programmes qui utilisent et exposent les clés primaires de manière abusive et les font faire partie de ces systèmes au lieu de les faire faire une seule chose - identifier de manière unique un enregistrement de base de données en interne. En fait, j'ai appris ce qui précède grâce à un séjour de 6 ans en soutenant un système d'entrepôt de données dans un hôpital.

29
Michael Durrant

Parce que les clés primaires sont un détail d'implémentation.

Si vous migrez des bases de données, vos clés primaires peuvent changer en raison de l'ordre d'insertion, de la suppression des anciens enregistrements ... pour différentes raisons. Si vous migrez la base de données plateformes il se peut que vous n'ayez plus du tout de clé primaire réelle. L'exposition du PK au-dessus de la couche d'accès aux données est une abstraction qui fuit, avec tous les problèmes de couplage que cela implique.

28
Telastyn

L'une des raisons pour lesquelles j'ai trouvé, au fil du temps, j'ai vu des utilisateurs finaux demander que leur identifiant signifie quelque chose (comme avoir un préfixe ou un indicateur de l'année où il a été accepté). Changer un PK est difficile, mais un substitut est beaucoup plus facile.

Votre clé primaire sera probablement quelque chose que vous voulez que votre base de données indexe pour des raisons de performances, et vous pouvez à temps pour des raisons techniques la changer par exemple d'un nombre en un guide ... vous ne savez tout simplement pas pour quelles raisons les nouvelles technologies ou connaissances pourrait vous guider vers le bas. Votre pk est votre donnée technique, la clé publique est destinée à la consommation des utilisateurs finaux.

8
Wayne M

Pour la plupart des applications, il est à peu près essentiel d'exposer les clés aux utilisateurs. Pour utiliser efficacement un système d'information, les utilisateurs de ce système auront normalement besoin d'un moyen d'identifier les informations qu'il contient et de relier ces informations à quelque chose dans le monde en dehors de la base de données. En termes de base de données relationnelle, ces identifiants sont des clés.

Un modèle de conception bien utilisé consiste à créer une clé supplémentaire, purement "technique" pour les tables de base de données comme moyen d'abstraction. Par exemple, pour fournir une clé stable (relativement immuable) où une autre clé est susceptible de changer. Ces clés techniques ne sont généralement pas exposées aux utilisateurs finaux, car cela sape l'abstraction prévue des exigences des utilisateurs. Cela n'a rien à voir avec la sécurité.

Le problème/malentendu implicite dans votre question est dû à une utilisation inappropriée du terme primaire clé. Une clé primaire n'est qu'une parmi plusieurs clés "candidates" (plusieurs identifiants possibles dans une table de base de données). La clé primaire ne nécessite pas nécessairement une propriété fondamentalement différente de toute autre clé, donc les assertions et les principes de conception qui s'appliquent spécifiquement aux clés primaires et non aux autres clés sont toujours suspects et souvent erronés.

Étant donné que vous devrez généralement exposer une clé à votre utilisateur, quelle devrait être cette clé? Essayez de rendre vos clés familières, simples et stables. La familiarité et la simplicité rendent les clés faciles à lire et à mémoriser et aideront à éviter les erreurs de saisie de données. La stabilité signifie que la clé change rarement, ce qui permet également d'éviter la possibilité d'une erreur d'identification.

2
nvogel

Il est tout à fait normal que les entités aient un identifiant unique qui est exposé au monde extérieur. Pour certains objets, il pourrait être possible de trouver un identifiant qui a réellement une signification (par exemple le numéro de facture) mais pour d'autres, aucun identifiant de ce type n'existe et il doit donc être généré.

Par souci de cohérence et de lisibilité, je trouve que c'est une bonne pratique pour toutes les entités d'un système d'utiliser exactement le même type et le même nom pour leur identifiant. Normalement, cet identifiant serait exposé (<type> getId()) dans une classe de base abstraite.

Pour la même raison, chaque service du système (par exemple le service de facturation) doit fournir des méthodes identiques pour accéder aux entités par leur identifiant. Normalement, cette méthode (findById(<type> id)) serait héritée d'une interface de service générique ou d'une classe de base.

Cet identifiant ne doit pas être la clé primaire de l'entité mais il peut en être un. La seule chose que l'on doit s'assurer est que la stratégie de génération de clés produit des identifiants raisonnablement uniques (pas nécessairement universellement uniques mais au moins dans le système).

Si le système est migré plus tard (gros si d'après mon expérience) vers une autre base de données, ce n'est pas un problème d'utiliser une stratégie différente (non basée sur des clés primaires) pour créer les identifiants tant que la stratégie est compatible avec celle d'origine.

1
Muton

Ceci provient d'un commentaire sur la réponse de Greystone28 par CodeCaster. C'est un exemple de ce que vous dites:

J'expose InvoiceNumber, qui a une signification et est modifiable par le client, mais j'expose également InvoiceID, que mon code utilise pour identifier de manière unique la facture. Vous n'avez pas à (et le plus souvent ne voulez pas) laisser la clé utilisateur être la clé de stockage. Cette question concerne ce dernier.

À quoi sert dans votre application l'affichage du InvoiceID?

En exposant, je suppose que vous voulez dire que l'utilisateur peut le voir. Exposez-le uniquement si l'utilisateur en a besoin pour utiliser votre application. Il pourrait être utilisé par le support technique ou par des trucs administratifs. J'ai travaillé avec quelques applications qui font cela. Il est plus facile de fournir une assistance lorsque je connais le dossier spécifique en question.

1
JeffO

La clé primaire est là, tout comme une poignée pour le tuple (enregistrement, ligne) auquel vous essayez d'accéder en tant que développeur. Il est également utilisé dans l'intégrité référentielle (contraintes de clé étrangère), et peut-être qu'il a également un ou plusieurs cas d'utilisation.

Essentiellement, il n'y a rien de mal à l'exposer aux utilisateurs, voire aux pirates. Parce que je ne connais pas d'attaque utilisant la clé primaire par exemple.

Mais en matière de sécurité, nous avons de nombreux principes (que nous acceptons et n'approuvons pas) et nous devons les respecter:

  1. Le principe du privilège de location
  2. La sécurité par l'obscurité

Et quelques autres principes. Ce qu'ils disent essentiellement, c'est que:

Si vous n'avez pas besoin d'exposer vos données, pourquoi le feriez-vous?

0
Saeed Neamati