2011-01-13 13 views
6

Ci sono motivi per cui non si dovrebbero utilizzare i Contratti di codice per applicare le regole aziendali?I contratti di codice dovrebbero essere utilizzati per motivi di sicurezza?

Immaginate di avere una classe User che rappresenta un singolo utente di un sistema e definisce le azioni che possono essere eseguite contro altri utenti. Si potrebbe scrivere un metodo ChangePassword come questo ...

public void ChangePassword(User requestingUser, string newPassword) 
{ 
    Contract.Requires<ArgumentNullException>(requestingUser); 
    Contract.Requires<ArgumentNullException>(newPassword); 

    // Users can always change their own password, but they must be an 
    // administrator to change someone else's. 
    if (requestingUser.UserId != this.UserId && 
     !requestingUser.IsInRole("Administrator")) 
     throw new SecurityException("You don't have permission to do that."); 

    // Change the password. 
    ... 
} 

Oppure si potrebbe implementare il controllo di sicurezza come condizione preliminare con Contract.Requires ...

public void ChangePassword(User requestingUser, string newPassword) 
{ 
    Contract.Requires<ArgumentNullException>(requestingUser != null); 
    Contract.Requires<ArgumentNullException>(newPassword != null); 

    // Users can always change their own password, but they must be an 
    // administrator to change someone else's. 
    Contract.Requires<SecurityException>(
     requestingUser.UserId == this.UserId || 
     !requestingUser.IsInRole("Administrator"), 
     "You don't have permission to do that."); 

    // Change the password. 
    ... 
} 

Quali sono i vantaggi e gli svantaggi di questi due metodi ?

risposta

2

Penso che la risposta sia no. I contratti di codice sono progettati per scenari in cui il loro errore indica un errore grave nel codice. Dovrebbero essere non essere qualcosa che può essere recuperato da un input utente errato.

Requires<T> è destinato a essere utilizzato solo su metodi pubblici di una libreria che verrà utilizzato da altri che non utilizzano Contratti di codice o se si dispone di codice legacy che deve rimanere compatibile in termini di quali eccezioni può generare.

Per il nuovo codice, si dovrebbe utilizzare solo Requires, non Requires<T>. Normale Requires genera un'eccezione non modificabile per impostazione predefinita, per costringerti ad affrontare il problema.

Inoltre, se qualcuno disattiva il controllo del runtime dei Contratti di codice, tutta la sicurezza scompare!

+0

Si potrebbe anche argomentare che in alcuni casi, l'esempio che hai fornito * è * un bug grave nel codice. Ad esempio, se il metodo che stai scrivendo è sepolto diversi livelli e tutte le verifiche devono essere eseguite sul livello esterno dell'applicazione, questa può essere considerata parte del contratto del metodo. Tutto dipende :) – porges

+0

Buona risposta! Non mi ero reso conto dell'incompatibilità di "ContractException", ma la tua risposta mi ha indirizzato nella giusta direzione: http://www.infoq.com/articles/code-contracts-csharp - grazie! :) –

Problemi correlati