2011-10-06 11 views
8

Ho un'applicazione MVC che ha il (semplificato) Struttura come di seguito (da sinistra a destra)Quale livello della mia applicazione ASP.NET MVC dovrei controllare le informazioni sull'iscrizione?

UI -> REGOLATORI -> Servizi -> REPOSITORY -> DATABASE

Abbiamo cercato per mantenere ogni livello disaccoppiato dal prossimo. Stiamo usando .NET Membership per gestire la sicurezza, e abbiamo una funzione basata sulle autorizzazioni, diciamo "Mostrami tutti i documenti per il mio tipo di utente".

caso:

  1. Lo strato di servizi non hanno alcuna consapevolezza del nostro provider di appartenenze .NET? Avremmo quindi i metodi del livello di servizio che assomigliavano a "GetDocumentsByUserType (int UserTypeId) {..}"?

  2. Il metodo GetDocumentsByUserType() è consapevole del fatto che stiamo usando .NET Membership, utilizzare i metodi Membership per ottenere il tipo di utente corrente e restituire i documenti rilevanti?

anche:

  • Ha # 1 fare il mio livello di servizi meno sicuro, come il mio livello di controllo
    potrebbe passare in qualsiasi cosa si voleva come UserType?
  • Il numero 2 rende il livello dei miei servizi troppo dipendente da una tecnologia specifica, ovvero .NET
    Membership? C'è un altro modo di considerare qui?

Spero di aver fornito abbastanza dettagli. Per favore, grida se no e io aggiungo.

Grazie.

risposta

7

È necessario conservare tutti gli elementi di appartenenza all'interno del livello di presentazione (controller). Supponiamo che tu voglia aggiungere un altro livello di presentazione (o apportare modifiche al tuo livello esistente), sarà difficile correggerlo. Inoltre, stai duplicando il codice tra il tuo livello di presentazione e il tuo livello di servizi, che non è mai una buona idea.

Detto questo, non vi è alcun motivo per non eseguire controlli di sicurezza all'interno del livello dei servizi, ma è possibile farlo senza dover utilizzare le classi di appartenenza. Innanzitutto, l'utente attualmente autenticato è disponibile da Thread.CurrentPrincipal (all'interno dei metodi del livello di servizio). È possibile utilizzare questo IPrincipal per eseguire i controlli di sicurezza.

In secondo luogo, è possibile utilizzare lo PrincipalPermissionAttribute per applicare le regole di sicurezza sui metodi o classi del livello di servizio. Per esempio:

[PrincipalPermission(SecurityAction.Demand, Role="Administrator")] 
public void MySecureServiceLayerMethod() 
{ 
    var p = Thread.CurrentPrincipal; 
    .... 
} 

per la roba ruolo da lavorare, devi anche usare un'implementazione RoleProvider.

UPDATE: Come spiega Wyatt Barnett in un commento, l'utilizzo di PrincipalPermission presenta alcuni svantaggi. Prima di tutto, testare il codice diventa più difficile. Un altro (più grande) svantaggio è che si codificano i nomi dei ruoli nel codice. Questi nomi di solito non sono di proprietà dello sviluppatore.

+3

+1, IPrincipal è la strada da percorrere. IPrincipals specialmente personalizzati. PrincipalPermission è davvero ingegnoso, ma avendolo usato pesantemente su un progetto, avrei davvero discusso contro di usarlo - è un po 'una mina terrestre per la gente e rende davvero difficili i test pur essendo difficili da testare. –

+0

Mille grazie, ragazzi. Molto utile. – christofr

+0

Ecco dove diventa interessante, cosa succede se ho bisogno del campo chiave primaria che rappresenta l'utente nel database? So che potrei ottenere il campo del nome per l'utente, ma preferirei usare il campo della chiave primaria. Come potrei accedere a questo da IPrincipal senza impostare il campo del nome sul valore della chiave primaria (so che suona male). – user1790300

Problemi correlati