n utenti - 1 account (1 utente può appartenere a un solo account, n utenti possono appartenere a 1 account, dove n è 0..infinity):
accounts (
account_id primary key
)
users (
user_id primary key,
account_id not null references accounts(account_id)
)
n utenti - m account; che probabilmente è ciò di cui hai bisogno (un utente può appartenere a m account, un account potrebbe avere n utenti)
accounts (
account_id primary key
)
users (
user_id primary key
)
user_accounts (
user_id not null references accounts(user_id)
account_id not null references accounts(account_id)
unique(user_id, account_id)
)
per garantire che nessuna informazione sia trapelata, esistono diversi approcci. Alcuni database e framework potrebbero permetterti di specificare questo requisito "dichiarativamente", che ti darà la massima sicurezza (o sicurezza pari all'implementazione - che in molti casi sarà migliore di quella che potresti ottenere - come le persone che sviluppano il database / framework probabilmente avrà più risorse).
Sfortunatamente, le soluzioni RDBMS complete e pure non sono implementate in sistemi ampiamente disponibili, e anche se esistessero, immagino che sarebbero legate al sistema dei ruoli RDBMS; cioè, è possibile concedere privilegi di selezione su determinate righe a determinati ruoli del database, ma questo potrebbe non essere applicabile al problema (ad esempio, dovresti creare ruoli per utente nella tua app ed eseguire query come utente appropriato; come so che questo non è pratico in nessuna piattaforma che conosco).
Se stai utilizzando un ORM per accedere al tuo database, potresti avere più fortuna. So che Hibernate implementa qualcosa in cui è possibile controllare le condizioni prima di eseguire qualsiasi operazione ( collegamento ) o filtri i dati, e credo che l'ORM di Yii consenta qualcosa di simile.
Se quelli non sono disponibili, o non sono adatti per il tuo caso particolare, dovrai lavorare più a fondo nello stack. Una soluzione tradizionale è quella di imporre a tutti gli accessi ai dati di passare attraverso un livello che impone la sicurezza - in realtà questa è una delle migliori ragioni per implementare una separazione di livello DAO / Servizio; I DAO contengono l'accesso ai dati "raw" e il livello di servizio controlla i privilegi. Se si evita l'accesso a DAO all'esterno dei Servizi, si dispone di tutta la logica di sicurezza in un luogo prevedibile (ad esempio la stessa classe / classi) e quindi è più semplice da controllare.
Un'altra soluzione comune è accedere al tuo database attraverso stored procedure che rafforzano la sicurezza. Questo ha spesso l'inconveniente che le stored procedure sono considerate meno belle da scrivere (ad esempio PL / SQL è poco amichevole di Java), anche se è discutibile. D'altra parte, se hai diverse applicazioni che accedono al database, ed esp. se usano lingue diverse, non dovrai duplicare tutte le voci di controllo degli accessi ovunque.
Inoltre, questo potrebbe essere un problema appropriato per la programmazione orientata all'aspetto.
Infine, tieni presente che tutti i precedenti forniscono solo la sicurezza "in uscita" (ad esempio, assicurati che l'applicazione non possa agire in modo non corretto a causa dell'azione dell'utente). Se gli attaccanti possono manomettere "dentro" l'applicazione, è game over - questo significa che devi aderire al codice di sicurezza standard (ad esempio evitare sovraccarichi di buffer, XSS, ecc.).