Perché non esporre una chiave primaria

48

Nella mia formazione mi è stato detto che è un'idea sbagliata quella di esporre le chiavi primarie reali (non solo le chiavi DB, ma tutte le principali utilità di accesso) all'utente.

Ho sempre pensato che fosse un problema di sicurezza (perché un utente malintenzionato potrebbe tentare di leggere cose non proprie).

Ora devo controllare se l'utente è autorizzato ad accedere comunque, quindi c'è un motivo diverso dietro di esso?

Inoltre, poiché i miei utenti devono accedere comunque ai dati, dovrò avere una chiave pubblica per il mondo esterno da qualche parte nel mezzo. Ora quella chiave pubblica ha gli stessi problemi della chiave primaria, vero?

C'è stata la richiesta di un esempio sul perché farlo comunque, quindi eccone uno. Tieni presente che la domanda è intesa a riguardare il principio stesso non solo se si applica in questo esempio. Le risposte che affrontano altre situazioni sono esplicitamente benvenute.

Applicazione (Web, Mobile) che gestisce l'attività, ha più interfacce utente e almeno un'API automatizzata per la comunicazione tra sistemi (e.G. il reparto contabilità desidera sapere quanto addebitare il cliente in base a ciò che è stato fatto). L'applicazione ha più clienti quindi la separazione dei loro dati (logicamente, i dati sono memorizzati nello stesso DB) è un must del sistema. Ogni richiesta verrà verificata per la validità non importa quale.

L'attività è molto dettagliata, quindi è insieme in un oggetto contenitore, chiamiamola "Attività".

Tre casi d'uso:

  1. L'utente A desidera inviare l'utente B a qualche attività in modo che gli invii un collegamento (HTTP) per ottenere un'attività svolta lì.
  2. L'utente B deve uscire dall'edificio, quindi apre l'attività sul suo dispositivo mobile.
  3. Contabilità desidera addebitare al cliente l'attività, ma utilizza un sistema di contabilità di terze parti che carica automaticamente l'attività / attività da un codice che fa riferimento a REST - API dell'applicazione

Ciascuno dei casi d'uso richiede (o diventa più facile se) l'agente di avere un identificatore indirizzabile per l'attività e l'attività.

    
posta Angelo Fuchs 13.11.2013 - 07:49
fonte

9 risposte

5

Questa è una risposta combinata delle altre (ovvero ciò che ho imparato). Se hai voglia di svaligiare questo, dovresti almeno sviare uno degli altri e fare il lavoro vero e proprio. Se sei più interessato, leggi invece le altre risposte.

Non dovresti esporre la chiave primaria del database ma usare una chiave surrogata

  1. Se vuoi che i tuoi utenti siano in grado di ricordare (almeno un po ') o riconoscere l'identificatore di una voce. ( Risposta di Graystone28s )
  2. Se vuoi pianificare in anticipo e considera che potresti cambiare i sistemi (Database o altro) che probabilmente cambierà il tuo PK. ( Risposta di Telastyns )
  3. Se vuoi garantire che i tuoi utenti abbiano un modo coerente di accedere ai dati che non cambieranno anche se la tua azienda cambierà proprietà e i dati saranno spostati in un altro sistema. ( Risposta di Michael Durrants )
  4. Se il tuo PK è prevedibile (come una sequenza) il tuo sistema può subire problemi di raccolta delle risorse. ( Risposta CodeCasters ) Questo si applica solo se il tuo sistema ha informazioni che valgono la pena di essere raccolte e che è accessibile a chiunque oa almeno qualcuno che ha un interesse per la raccolta.

Nota: la chiave creata deve essere (kinda) comprensibile per l'uomo ( Risposta Sqlvogels ).

Se il tuo sistema non ha bisogno di 1. a 4. allora non vi è alcun motivo per non utilizzare il database PK come identificatore pubblico (molte delle risposte). Anche la sicurezza non è un problema qui (molte delle risposte).

    
risposta data 14.11.2013 - 10:17
fonte
33

Also, as my users have to access the data anyway I will need to have a public key for the outside world somewhere in between.

Esattamente. Prendi l'HTTP stateless, che altrimenti non saprebbe quale risorsa dovrebbe richiedere: espone l'ID della tua domanda 218306 nell'URL. Forse ti stai davvero chiedendo se un identificatore esposto potrebbe essere prevedibile ?

Gli unici posti in cui ho sentito una risposta negativa, hanno utilizzato la logica: "Ma possono cambiare l'ID nell'URL!" . Quindi hanno usato GUID invece di implementare un'autorizzazione appropriata.

Posso immaginare una situazione in cui non vuoi che i tuoi identificatori siano prevedibili: raccolta delle risorse. Se disponi di un sito che ospita pubblicamente determinate risorse, altre potrebbero essere interessanti e le ospitali come /images/n.jpg o /videos/n.mp4 dove n è solo un numero incrementale, chiunque guarda al traffico da e verso il tuo sito web può raccogliere tutto le tue risorse.

Quindi, per rispondere direttamente alla tua domanda: no, non è male per "esporre" direttamente gli identificatori che hanno solo un significato per il tuo programma, di solito è anche richiesto che il tuo programma funzioni con successo.

    
risposta data 13.11.2013 - 09:52
fonte
28

Non dovresti esporlo perché le persone che lo vedranno inizieranno a usarlo come "numero di conto" che NON è. Ad esempio, per il mio conto bancario so qual è il mio numero di conto. L'ho memorizzato, lo uso al telefono con il servizio clienti, lo uso durante la compilazione di moduli per altre banche per effettuare trasferimenti, per documenti legali, per il mio servizio di pagamento automatico, ecc. Ecc. Non voglio per cambiare. D'altra parte, la chiave primaria (per il mio account) non lo so o non vedo mai.
Il sistema che lo memorizza cambia nel corso degli anni da un sistema a un altro, attraverso fusioni bancarie, aggiornamenti di sistema e sostituzioni, ecc. Ecc.
Le chiavi primarie possono cambiare attraverso alcune di queste trasformazioni, quindi se non sono mai state esposte, scritte o ricordate da un normale utente che è una vera cosa buona .
Le chiavi prive di significato commerciale sono spesso definite chiavi surrogate e sono spesso (ma non sempre) utilizzate come chiavi primarie.

btw, questo succede anche internamente quando le persone costruiscono interfacce e programmi che usano impropriamente ed espongono le chiavi primarie e le rendono parte di tali sistemi invece di fare solo una cosa - identificando un record di database internamente in modo univoco. In realtà ho imparato quanto sopra attraverso uno stint di 6 anni che supporta un sistema di data warehouse in un ospedale.

    
risposta data 13.11.2013 - 20:09
fonte
22

Perché le chiavi primarie sono un dettaglio di implementazione.

Se si migrano i database, le chiavi primarie potrebbero cambiare a causa dell'ordine di inserimento, rimozione dei vecchi record ... per diversi motivi. Se esegui la migrazione delle piattaforme del database, potresti non avere più una vera chiave primaria. L'esposizione del PK sopra il livello di accesso ai dati è un'astrazione che perde, con tutti i problemi di accoppiamento che ciò comporta.

    
risposta data 13.11.2013 - 15:05
fonte
8

Una ragione per cui ho trovato, nel tempo che ho visto, gli utenti finali richiedono che il loro identificatore indichi qualcosa (come avere un prefisso o un indicatore dell'anno in cui è stato inserito). Cambiare un PK è difficile, ma un surrogato è molto più semplice.

Probabilmente la tua chiave primaria sarà qualcosa su cui vuoi che il tuo database indicizzi per motivi di prestazioni, e in tempo per motivi tecnici potresti cambiarlo, ad esempio da un numero a un guid ... semplicemente non sai quali sono i motivi le tecnologie o la conoscenza potrebbero guidarti verso il basso. Il tuo pk è il tuo elemento tecnico di dati, la chiave pubblica è per il consumo degli utenti finali.

    
risposta data 13.11.2013 - 12:50
fonte
1

Questo è da un commento sulla risposta di Greystone28 di CodeCaster. È un esempio di ciò che stai dicendo:

I expose InvoiceNumber, which has a meaning to and is changeable by the customer, but I also expose InvoiceID, which my code uses to uniquely identify the invoice. You don't have to (and more often don't want to) let the user-key be the storage-key. This question is about the latter.

Qual è lo scopo della tua app che mostra l'InvoiceID?

Esponendo, suppongo che tu voglia dire che l'utente possa vederlo. Esponilo solo se l'utente ne ha bisogno per usare la tua app. Potrebbe essere utilizzato da supporto tecnico o alcune cose amministrative. Ho lavorato con alcune app che fanno questo. Semplifica il supporto quando conosco il record specifico in questione.

    
risposta data 13.11.2013 - 14:58
fonte
1

Per la maggior parte delle applicazioni è praticamente indispensabile che tu esponga le chiavi agli utenti. Per utilizzare efficacemente un sistema informativo, gli utenti di quel sistema normalmente avranno bisogno di un modo per identificare le informazioni al suo interno e per mettere in relazione tali informazioni con qualcosa nel mondo esterno al database. Nei termini dei database relazionali, tali identificatori sono chiavi.

Uno schema di progettazione ben utilizzato consiste nel creare una chiave aggiuntiva, puramente "tecnica" per le tabelle del database come mezzo di astrazione. Ad esempio, per fornire una chiave stabile (relativamente invariabile) in cui alcune chiavi alternative sono soggette a modifiche. Tali chiavi tecniche in genere non sono esposte agli utenti finali perché ciò pregiudica l'astrazione prevista dai requisiti dell'utente. Non ha nulla a che fare con la sicurezza.

Il problema / incomprensione implicito nella tua domanda è dovuto all'uso inappropriato del termine chiave primaria . Una chiave primaria è solo una tra diverse chiavi "candidate" (diversi possibili identificatori in una tabella di database). La chiave primaria non richiede necessariamente alcuna proprietà fondamentalmente diversa rispetto a qualsiasi altra chiave, quindi le asserzioni ei principi di progettazione che si applicano specificamente alle chiavi primarie e non ad altre chiavi sono sempre sospetti e spesso sbagliati.

Dato che di solito hai bisogno di esporre una chiave per il tuo utente, quale dovrebbe essere quella chiave? Prova a rendere le tue chiavi familiari, semplici e stabili. La familiarità e la semplicità rendono le chiavi facili da leggere e da ricordare e aiutano a evitare errori di immissione dei dati. Stabilità significa che la chiave cambia raramente, il che aiuta anche a evitare la possibilità di errori di identificazione.

    
risposta data 13.11.2013 - 16:31
fonte
1

È del tutto normale che le entità abbiano un identificatore univoco esposto al mondo esterno. Per alcuni oggetti potrebbe essere possibile trovare un identificatore che abbia effettivamente un significato (ad esempio numero di fattura) ma per altri non esiste un identificatore di questo tipo e quindi deve essere generato.

Per motivi di coerenza e leggibilità, trovo una buona pratica per tutte le entità in un sistema utilizzare lo stesso identico tipo e nome per il loro identificatore. Normalmente questo identificatore verrebbe esposto ( <type> getId() ) in qualche classe base astratta.

Per lo stesso motivo, ogni servizio nel sistema (ad esempio il servizio di fatturazione) dovrebbe fornire metodi identici per l'accesso alle entità tramite il loro identificatore. Normalmente questo metodo ( findById(<type> id) ) sarebbe ereditato da una generica interfaccia di servizio o classe base.

Questo identificatore non deve essere la chiave primaria dell'entità, ma può essere uno. L'unica cosa che si deve assicurare è che la strategia di generazione delle chiavi produca identificatori ragionevolmente univoci (non necessari universalmente unici ma almeno all'interno del sistema).

Se il sistema viene successivamente migrato (grande se la mia esperienza) in un altro database, non è un problema utilizzare una strategia diversa (non basata su chiavi primarie) per creare gli identificatori purché la strategia sia compatibile con l'originale uno.

    
risposta data 14.11.2013 - 13:21
fonte
0

La chiave primaria è lì, proprio come un handle per la tupla (record, riga) che si tenta di accedere come sviluppatore. Viene anche utilizzato nell'integrità referenziale (vincoli di chiave esterna) e forse ha anche uno o più casi d'uso.

In sostanza, non c'è niente di male nell'esporlo agli utenti, o persino agli hacker. Perché non conosco un attacco che usa la chiave primaria, per esempio.

Ma in sicurezza, abbiamo molti principi (che accettiamo e non approviamo) e dobbiamo rispettarli:

  1. Il principio del privilegio del leasing
  2. Sicurezza attraverso l'oscurità

E alcuni altri principi. Quello che dicono in sostanza è questo:

Se non hai bisogno di esporre i tuoi dati, perché dovresti farlo?

    
risposta data 13.11.2013 - 18:09
fonte

Leggi altre domande sui tag