In meiner Ausbildung wurde mir gesagt, dass es eine fehlerhafte Idee ist, dem Benutzer tatsächliche Primärschlüssel (nicht nur DB-Schlüssel, sondern alle primären Zugriffsmethoden) zur Verfügung zu stellen.
Ich dachte immer, es sei ein Sicherheitsproblem (weil ein Angreifer versuchen könnte, Dinge zu lesen, die nicht von ihm stammen).
Jetzt muss ich überprüfen, ob der Benutzer trotzdem Zugriff hat. Gibt es also einen anderen Grund dafür?
Da meine Benutzer ohnehin auf die Daten zugreifen müssen, muss ich irgendwo dazwischen einen öffentlichen Schlüssel für die Außenwelt haben. Nun, dieser öffentliche Schlüssel hat die gleichen Probleme wie der Primärschlüssel, nicht wahr?
Es gab die Anfrage eines Beispiels, warum das sowieso so ist, also hier ist eines. Denken Sie daran, dass es sich bei der Frage nicht nur um das Prinzip selbst handelt, wenn es in diesem Beispiel zutrifft. Antworten auf andere Situationen sind ausdrücklich erwünscht.
Eine Anwendung (Web, Mobile), die Aktivitäten abwickelt, verfügt über mehrere Benutzeroberflächen und mindestens eine automatisierte API für die systemübergreifende Kommunikation (z. B. möchte die Buchhaltungsabteilung wissen, wie viel dem Kunden basierend auf den durchgeführten Aktionen berechnet wird). Die Anwendung hat mehrere Kunden, sodass die Trennung ihrer Daten (logischerweise werden die Daten in derselben Datenbank gespeichert) ein Muss des Systems ist. Jede Anfrage wird auf ihre Gültigkeit hin überprüft.
Die Aktivität ist sehr feinkörnig, so dass sie in einem Containerobjekt zusammengefasst ist. Nennen wir sie "Task".
Drei Anwendungsfälle:
- Benutzer A möchte Benutzer B an eine Aufgabe senden, damit er ihm einen Link (HTTP) sendet, um dort eine Aktivität auszuführen.
- Benutzer B muss das Gebäude verlassen, damit er die Aufgabe auf seinem Mobilgerät öffnet.
- Das Rechnungswesen möchte dem Kunden die Aufgabe in Rechnung stellen, verwendet jedoch ein Buchhaltungssystem eines Drittanbieters, das die Aufgabe / Aktivität automatisch mit einem Code lädt, der auf die REST-API der Anwendung verweist
Für jeden Anwendungsfall muss (oder wird es einfacher, wenn) der Agent eine adressierbare ID für die Aufgabe und die Aktivität hat.
ON UPDATE CASCADE
wurde @gnat erstellt (mysql-spezifisch?). Wenn das Problem jedoch die Sicherheit ist, sollte die Zugriffskontrolle im Backend erfolgen und dem Benutzer sowieso nicht vertrauenAntworten:
Genau. Nehmen Sie das zustandslose HTTP, das sonst nicht wissen würde, welche Ressource es anfordern soll: Es macht die ID Ihrer Frage
218306
in der URL sichtbar. Vielleicht fragen Sie sich tatsächlich, ob eine exponierte Kennung vorhersehbar sein kann ?Die einzigen Stellen, an denen ich eine negative Antwort darauf gehört habe, benutzten die Begründung: "Aber sie können die ID in der URL ändern!" . Sie verwendeten also GUIDs, anstatt die richtige Autorisierung zu implementieren.
Ich kann mir eine Situation vorstellen, in der Ihre Identifikatoren nicht vorhersehbar sein sollen: Ressourcenernte. Wenn Sie eine Website, die öffentlich bestimmte Ressourcen andere Hosts kann interessant sein , in und hosten Sie sie mögen
/images/n.jpg
oder/videos/n.mp4
won
ist nur eine fortlaufende Nummer, jeder an Verkehr zu und von Ihrer Website suchen , können Sie alle Ihre Ressourcen ernten.Um Ihre Frage direkt zu beantworten: Nein, es ist nicht schlecht, Bezeichner, die nur eine Bedeutung für Ihr Programm haben, direkt "offenzulegen". In der Regel ist es sogar erforderlich, dass Ihr Programm erfolgreich ausgeführt wird.
quelle
Sie sollten es nicht offenlegen, da Personen, die es sehen, es als ihre "Kontonummer" verwenden, was NICHT der Fall ist. Beispielsweise weiß ich für mein Bankkonto, wie meine Kontonummer lautet. Ich habe es auswendig gelernt, ich benutze es am Telefon beim Kundendienst, ich benutze es beim Ausfüllen von Formularen für andere Banken, um Überweisungen zu tätigen, für juristische Dokumente, für meinen automatischen Zahlungsdienst usw. Ich möchte nicht es zu ändern. Den Primärschlüssel (für meinen Account) dagegen kenne ich nicht oder sehe ihn nie.
Das System, in dem es gespeichert wird, ändert sich im Laufe der Jahre von einem System zum anderen, durch Zusammenführung von Banken, System-Upgrades und -Ersetzungen usw. usw.
Die Primärschlüssel können sich durch einige dieser Transformationen ändern von jedem normalen Benutzer, der
Schlüssel ohne geschäftliche Bedeutung werden häufig als Ersatzschlüssel bezeichnet und werden häufig (aber nicht immer) als Primärschlüssel verwendet.
Übrigens geschieht dies sogar intern, wenn Benutzer Schnittstellen und Programme erstellen, die Primärschlüssel missbrauchen und verfügbar machen und sie zu einem Teil solcher Systeme machen, anstatt nur eine einzige Aufgabe zu übernehmen - die eindeutige interne Identifizierung eines Datenbankdatensatzes. Ich habe dies tatsächlich durch eine 6-jährige Tätigkeit als Support für ein Data-Warehouse-System in einem Krankenhaus gelernt.
quelle
Weil Primärschlüssel ein Implementierungsdetail sind.
Wenn Sie Datenbanken migrieren, können sich Ihre Primärschlüssel aufgrund der Reihenfolge des Einfügens und Entfernens alter Datensätze ändern. Dies kann verschiedene Gründe haben. Wenn Sie Datenbank migrieren Plattformen können Sie nicht mehr über einen tatsächlichen gar Primärschlüssel. Das Freilegen der PK über der Datenzugriffsschicht ist eine undichte Abstraktion mit allen damit verbundenen Kopplungsproblemen.
quelle
Dies ist eine kombinierte Antwort der anderen (aka. Was ich gelernt habe). Wenn Sie Lust haben, diesen zu verbessern, sollten Sie zumindest einen der anderen positiv bewerten, der die eigentliche Arbeit geleistet hat. Wenn Sie mehr interessiert sind, lesen Sie stattdessen die anderen Antworten.
Sie sollten den Primärschlüssel der Datenbank nicht offen legen, sondern einen Ersatzschlüssel verwenden
Hinweis: Ihr erstellter Schlüssel sollte (irgendwie) für den Menschen verständlich sein ( Sqlvogels Answer ).
Wenn Ihr System keine 1. bis 4. benötigt, gibt es keinen Grund, die Datenbank-PK nicht als öffentliche Kennung zu verwenden (mehrere der Antworten). Auch die Sicherheit spielt hier keine Rolle (einige der Antworten).
quelle
Ein Grund, warum ich festgestellt habe, war, dass Endbenutzer in der Fülle der Zeit nachfragen, ob ihre Kennung etwas bedeutet (z. B. ein Präfix oder einen Indikator für das Jahr, in dem sie begonnen hat). Das Ändern einer PK ist schwierig, aber ein Ersatz ist viel einfacher.
Ihr Primärschlüssel wird wahrscheinlich etwas sein, für das Ihre Datenbank aus Leistungsgründen indiziert werden soll, und Sie können ihn aus technischen Gründen rechtzeitig ändern, z. B. von einer Zahl in eine Anleitung. Sie wissen nur nicht, aus welchen Gründen neue Technologien oder Kenntnisse vorliegen könnte dich nach unten führen. Ihr pk ist Ihr technischer Datenbestandteil, der öffentliche Schlüssel ist für den Endbenutzerverbrauch bestimmt.
quelle
InvoiceNumber
, was für den Kunden eine Bedeutung hat und vom Kunden geändert werden kann, aber ich lege darInvoiceID
, was mein Code verwendet, um die Rechnung eindeutig zu identifizieren. Sie haben nicht zu (und oft nicht wollen auf) die Benutzer-Taste wird der Speicherschlüssel sein lassen. Bei dieser Frage handelt es sich um die letztere.InvoiceNumber
(für unterschiedliche Mandanten), aber mit unterschiedlichen Primärschlüsseln haben - ein Punkt (eine Art von) ) auch in der Antwort erwähnt.Für die meisten Anwendungen ist es ziemlich wichtig, dass Sie die Schlüssel den Benutzern zugänglich machen. Um ein Informationssystem effektiv zu nutzen, benötigen die Benutzer dieses Systems normalerweise eine Möglichkeit, die darin enthaltenen Informationen zu identifizieren und diese Informationen mit etwas in der Welt außerhalb der Datenbank in Beziehung zu setzen. In relationalen Datenbankbegriffen sind diese Bezeichner Schlüssel.
Ein häufig verwendetes Entwurfsmuster besteht darin, einen zusätzlichen, rein "technischen" Schlüssel für Datenbanktabellen als Abstraktionsmittel zu erstellen. Zum Beispiel, um einen stabilen (relativ unveränderlichen) Schlüssel bereitzustellen, bei dem sich ein alternativer Schlüssel ändern kann. Solche technischen Schlüssel sind für Endbenutzer normalerweise nicht zugänglich, da dies die beabsichtigte Abstraktion von den Benutzeranforderungen untergräbt. Es hat nichts mit Sicherheit zu tun.
Das in Ihrer Frage enthaltene Problem / Missverständnis beruht auf einer unangemessenen Verwendung des Begriffs Primärschlüssel . Ein Primärschlüssel ist nur einer von mehreren "Kandidaten" -Schlüsseln (mehrere mögliche Bezeichner in einer Datenbanktabelle). Der Primärschlüssel erfordert nicht unbedingt eine grundlegend andere Eigenschaft als jeder andere Schlüssel, sodass Behauptungen und Entwurfsprinzipien, die speziell für Primärschlüssel und nicht für andere Schlüssel gelten, immer verdächtig und häufig falsch sind.
Angesichts der Tatsache, dass Sie normalerweise einen Schlüssel für Ihren Benutzer bereitstellen müssen, was sollte dieser Schlüssel sein? Versuchen Sie, Ihre Schlüssel vertraut, einfach und stabil zu machen. Vertrautheit und Einfachheit erleichtern das Lesen und Merken von Schlüsseln und helfen, Fehler bei der Dateneingabe zu vermeiden. Stabilität bedeutet, dass sich der Schlüssel selten ändert, was auch dazu beiträgt, die Möglichkeit einer falschen Identifizierung zu vermeiden.
quelle
Dies ist aus einem Kommentar zu Greystone28s Antwort von CodeCaster. Es ist ein Beispiel für das, was Sie sagen:
Welchen Zweck hat die Anzeige der InvoiceID in Ihrer App?
Ich gehe davon aus, dass Sie damit meinen, dass der Benutzer es sehen kann. Stellen Sie es nur zur Verfügung, wenn der Benutzer es zur Verwendung Ihrer App benötigt. Es kann vom technischen Support oder von Verwaltungspersonal verwendet werden. Ich habe mit einigen Apps gearbeitet, die dies tun. Dies erleichtert die Bereitstellung von Support, wenn ich den betreffenden Datensatz kenne.
quelle
Es ist völlig normal, dass Entitäten eine eindeutige Kennung haben, die der Außenwelt ausgesetzt ist. Für einige Objekte kann es möglich sein, eine Kennung zu finden, die tatsächlich eine Bedeutung hat (z. B. Rechnungsnummer), für andere jedoch ist keine solche Kennung vorhanden und muss daher generiert werden.
Aus Gründen der Konsistenz und Lesbarkeit empfehle ich, dass alle Entitäten in einem System den gleichen Typ und Namen für ihre Kennung verwenden. Normalerweise wird dieser Bezeichner
<type> getId()
in einer abstrakten Basisklasse verfügbar gemacht ( ).Aus demselben Grund sollte jeder Dienst im System (z. B. Rechnungsdienst) identische Methoden für den Zugriff auf Entitäten anhand ihrer Kennung bereitstellen. Normalerweise wird diese Methode (
findById(<type> id)
) von einer generischen Dienstschnittstelle oder Basisklasse geerbt.Dieser Bezeichner muss nicht der Primärschlüssel der Entität sein, er kann jedoch einer sein. Man muss nur sicherstellen, dass die Strategie zur Schlüsselgenerierung einigermaßen eindeutige Kennungen erzeugt (nicht unbedingt universell eindeutig, aber zumindest innerhalb des Systems).
Wenn das System später in eine andere Datenbank migriert wird (nach meiner Erfahrung sehr umfangreich), ist es kein Problem, eine andere Strategie (die nicht auf Primärschlüsseln basiert) zum Erstellen der Bezeichner zu verwenden, solange die Strategie mit der ursprünglichen kompatibel ist.
quelle
Der Primärschlüssel befindet sich dort, genau wie ein Handle für das Tupel (Datensatz, Zeile), auf das Sie als Entwickler zugreifen möchten. Es wird auch in Bezug auf die referenzielle Integrität (Fremdschlüsseleinschränkungen) verwendet und hat möglicherweise auch einen oder mehrere Anwendungsfälle.
Im Grunde genommen ist es nichts Schlimmes, es Benutzern oder sogar Hackern auszusetzen. Weil mir kein Angriff bekannt ist, bei dem zum Beispiel der Primärschlüssel verwendet wird.
Aber in Bezug auf die Sicherheit haben wir viele Grundsätze (die wir akzeptieren und nicht akzeptieren) und die wir einhalten müssen:
Und einige andere Prinzipien. Was sie im Wesentlichen sagen, ist das:
Wenn Sie Ihre Daten nicht offenlegen müssen, warum sollten Sie das überhaupt tun?
quelle