Domanda

Nella mia tipica app, l'utente fa clic su un pulsante in una pagina aspx, invoca un oggetto business C #, quindi esegue una procedura memorizzata.

I controlli di ruolo devono essere eseguiti nella parte superiore della pila, nella parte inferiore della pila o ad ogni livello? Sembra che se un utente malintenzionato può invocare un metodo, potrebbe invocarne uno, quindi per una sicurezza efficace, avresti bisogno di un controllo su ogni metodo (e questo è un sacco di codice extra per scrivere).

Ecco un tipico stack di chiamate per illustrare la mia domanda:

Page_Load()
{
  if(p.IsInRole("Managers"))  //or equivalent attribute
  {
    AddAccount.Visible =true;
  }
}

AddAccount_OnClick()
{
  if(p.IsInRole("Managers"))  //or equivalent attribute
  {
    //Add the account
    Account.Add(...);  //and maybe another role check...
  }
}

-- TSQL doesn't understand .NET authorization, this call is in a 'trusted' subsystem
create proc Add_Account @user, @account_name
If @user in (Select user from role_table where role='manager')
-- Add the account
È stato utile?

Soluzione

A mio avviso, dovresti metterlo il più vicino possibile ai dati. Più ti avvicini ai dati, migliore è la possibilità di assicurarti che non sia possibile percorrere un percorso tortuoso attraverso la tua base di codice per aggirare un controllo di accesso.

Tale argomento richiederebbe l'inserimento di controlli di sicurezza nell'origine dati stessa, se lo supporta (come il tuo RDBMS preferito) o nel livello di accesso ai dati.

Tuttavia, alcuni vincoli di sicurezza hanno un forte odore di logica aziendale; per esempio. " se l'utente ha questo ruolo e sta tentando di modificare i dati che soddisfano queste specifiche, l'operazione dovrebbe essere consentita; altrimenti non " ;. Mi sembra una politica e qualcosa che appartiene al livello della logica di business di una sorta di motore delle regole separato.

Ho scritto di qualcosa di simile nel contesto di WCF qualche tempo fa .

Altri suggerimenti

Dal punto di vista dell'implementazione sarebbe la soluzione migliore per implementare i controlli il più in basso possibile perché c'è il minor numero di funzioni che richiedono protezione, quindi il minor numero di cose da incasinare e tutti gli input dell'utente passare attraverso il livello protetto. Se la tua fondazione è protetta, non devi preoccuparti di tutto ciò che si basa su quella fondazione.

Questa soluzione ha un inconveniente ovvio: l'interfaccia utente non sa nulla di autenticazione, autorizzazione, verifica dei dati e tutto il resto. Quindi ogni input scende nello stack, potrebbe causare un errore e sale nuovamente nello stack per informare l'utente. Ciò causerà un'esperienza utente spiacevole poiché gli errori che potrebbero essere facilmente rilevati nell'interfaccia utente vengono rilevati solo dopo aver passato i dati ai sistemi di back-end. Di conseguenza aggiungerai anche molti controlli all'interfaccia utente, al fine di offrire un'esperienza utente migliore.

Se si utilizza la programmazione basata su interfaccia, questo non è affatto un problema, poiché è possibile condividere il codice di verifica tra i livelli dell'applicazione. Ciò ti consente inoltre di aggiungere facilmente un codice di verifica a tutti i livelli dell'applicazione e ti fornirà una difesa approfondita: un bug in un livello dell'applicazione può essere rilevato da un altro livello. Ovviamente, se il codice di verifica stesso è errato e lo si condivide su tutti i livelli dell'applicazione, il bug e la presenza di un errore probabilmente verteranno su tutti i livelli dell'applicazione.

Posizionerei i controlli di accesso al ruolo negli oggetti business che eseguono effettivamente le cose potenzialmente pericolose / sensibili.

L'aggiunta del controllo del ruolo al caricamento della pagina e gli eventi di clic sui pulsanti sarebbero estranei, IMHO. Inoltre, se hai intenzione di proteggere la pagina, proteggi la pagina utilizzando le direttive sulla posizione dichiarativa nel tuo web.config ... ad es. metti tutte le tue " admin " pagine in una cartella separata e proteggere l'intera cartella, in modo dichiarativo.

Ma dovresti sempre avere i controlli sui metodi dei tuoi oggetti business, come minimo.

Devi metterlo a livello di metodo. Non puoi presumere di raggiungere quel metodo in alcun modo specifico. Tale metodo può essere chiamato dal gestore di pulsanti o può essere chiamato in codice normale come risultato di qualsiasi tipo di logica. Quante volte hai visto qualcosa del genere chiamare un gestore di pulsanti ...

private void MyBypassingCall()
{
  if( myLogic )
  {
    AddAccount_OnClick();
  }
}

Quindi metterlo su Page_Load non è abbastanza. Dovresti anche provare a decorare il metodo con un PrincipalPermissionAttribute . Ciò riduce un sacco di codice.

Questo è solo un commento aneddotico su quanto possa essere importante eseguire la convalida della sicurezza sul lato aziendale. Nel nostro caso non era abbastanza buono essere ottimisti sulle basse aspettative di hacking delle richieste. Non abbiamo avuto alcun tipo di convalida nei nostri oggetti business e siamo stati bruciati in modo inaspettato. Un client ha creato uno script per automatizzare l'utilizzo del nostro sito. È finito seguendo i collegamenti previsti nella loro sceneggiatura che non sono stati effettivamente resi. Ha finito per corrompere i dati. Naturalmente, questo è più un problema di stato del sistema e di integrità dei dati per noi piuttosto che una violazione della sicurezza, ma suppongo che entrambi si applichino davvero.

Oggetti business.

Ma in fase di costruzione. Lascia che ogni istanza acquisisca un ruolo molto specifico.

Modifica: più conciso in questo modo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top