Domanda

Diciamo che ho un'app ASP.Net MVC e questa app (UI) fa riferimento a un livello di logica aziendale (BLL) e il BLL fa riferimento al mio livello di accesso ai dati (DAL).

Sto utilizzando un provider di appartenenza e ruolo personalizzato per l'autorizzazione.

Sto cercando di determinare quali livelli devono fare riferimento al mio provider di appartenenza.

In MVC è possibile eseguire i controlli di autorizzazione nel modo seguente:

[Authorize(Roles = "SomeRoleName")]
public ActionResult Index()
{
//do something
}

E nel mio BLL potrei voler verificare se anche un utente ha un ruolo:

public static bool IsRoleEditor(User user, Role userRole)
  {
   bool retValue = false;

   if (user.Application.AppID == UserRole.Application.AppID)
   {
        if (Roles.IsUserInRole("ModifyRoles"))
        {
           retValue = true;
        }


    return retValue;
   }

Dovrei fare riferimento e creare un'istanza delle classi di appartenenza in entrambi i livelli se lo faccio. È questo il modo corretto di progettare un'app come questa? Sembra molta ridondanza.

Dato che ho un BLL, evito di usare il " [Autorizza (Ruoli = " SomeRoleName ")] " e invece chiama una funzione BLL dal codice MVC per verificare se l'utente ha un ruolo? Se lo faccio, MVC ha ancora bisogno di un riferimento al provider di appartenenza per l'autenticazione e comunque per sfruttare il login e altri controlli ASP, giusto?

Sono lontano dalla base e sto andando nella direzione sbagliata?

È stato utile?

Soluzione

Dal mio punto di vista questa è una debolezza nella progettazione di appartenenza / ruolo.

Il modo in cui vorrei aggirare il problema, ad esempio per avere un'autorizzazione basata sui ruoli su entrambi i livelli UI e BLL in un'app distribuita di livello n, sarebbe quello di esporre un servizio nel livello BLL che espone i bit rilevanti (GetRolesForUser ecc.) e viene implementato chiamando il RoleProvider sul server.

Quindi implementare un RoleProvider personalizzato sul client che viene implementato chiamando il servizio esposto dal BLL.

In questo modo il livello UI e il livello BLL condividono entrambi lo stesso RoleProvider. Il livello dell'interfaccia utente può utilizzare la conoscenza dei ruoli dell'utente corrente per migliorare l'interfaccia utente (ad esempio nascondere / disabilitare i controlli dell'interfaccia utente corrispondenti a funzionalità non autorizzate) e BLL può garantire che gli utenti non possano eseguire logica aziendale per la quale non sono autorizzati.

Altri suggerimenti

Ottima domanda, oggi mi sono posto la stessa cosa. Una delle idee che ho avuto (ma non sono davvero sicuro che sia il modo migliore di procedere) è quella di utilizzare un'interfaccia (es: IRoleProvider) che puoi passare al tuo BLL per testare il tuo accesso.

public static bool IsRoleEditor(User user, IRoleProvider rp)
{
     return (rp.IsUserInRole(user,"ModifyRoles"));
}

Con questo, verifichi ancora il tuo accesso nel tuo BLL, puoi usare un finto nei test delle unità per controllare la tua logica e devi solo creare una classe (o implementarla in una classe baseController) nel tuo sito Web MVC che implementerà IRoleProvider e farà il controllo corretto utilizzando l'API di autorizzazione ASP.NET.

Spero che questo possa aiutare.

Ottieni l'oggetto Utente per implementare l'interfaccia IPrincipal e lanciarlo attorno ai livelli. Quindi è ancora possibile utilizzare l'attributo [Autorize] incorporato.

Pensato oltre 3 anni fa e dedicato al castello, questo articolo può essere d'aiuto. Comincia a entrare nella roba di IPrincipal a metà strada.

HTHS
Charles

Perché non passare i ruoli nel tuo BLL in modo da non avere alcuna dipendenza dall'iscrizione. Oppure usa un'interfaccia come suggerito MartinB.

Che cosa succederà in futuro quando i tuoi stakeholder decidono di scegliere una diversa forma di autenticazione e non lavori più con un oggetto Ruolo ?

Esempio:

IsRoleEditor(User user, string[] roles)
{
  return roles.Contains("ModifyRoles");
}

Non ti manca il punto di MVC. MVC si divide naturalmente in livelli. Modello (DAL), controller (BLL), vista (presentazione). Questi possono andare in diversi progetti, se lo desideri, ma poiché il controller ha tutte le logiche aziendali, devi solo accedere al RoleProvider lì.

Quindi applica pattern come il repository, pattern etc per suddividere ulteriormente se vuoi.

Davy

Chiamare il controller MVC 'UI' è lontano dal segno. La 'C' in MVC è parte del tuo BLL, anche se fa riferimento a classi che tu chiamerebbe BLL. Tuttavia, non è questo il punto della tua domanda.

Penso che risolverei questo problema ponendo la domanda, "esiste un reale requisito per la separazione al 100% della tua app" UI "e della tua" BLL "?". Se entrambi i componenti condividono una dipendenza dai provider di membri / ruoli, lascia che sia così e mettiti al lavoro.

Nel caso in cui scolleghi il BLL e ne colleghi uno nuovo, forse avere una dipendenza condivisa su un provider .NET è qualcosa con cui puoi convivere. Sai che probabilmente è ok e la tua app potrebbe non andare in pezzi.

Penso che la risposta di Joe sopra abbia molto senso però ...

Penso che quello che stai facendo vada bene.

L'autorizzazione e l'autenticazione dovrebbero vivere all'interno di un livello di servizi, che forse viene passato ai controller.

Se il controller imposta Principal e Identity e quindi lo usi nel controller attraverso l'uso degli attributi MVC, allora sembra una buona idea.

Sarebbe bello nascondere il proprio provider di appartenenze MVC dietro un'interfaccia, in questo modo è possibile scambiarlo con un provider di appartenenze WinForms (ad esempio) e poter testare l'unità di controllo dei propri controller.

L'accesso al ruolo normalmente non dovrebbe essere nel BLL. L'accesso è una responsabilità dell'interfaccia utente.

Detto questo, sfrutta l'interfaccia IPrinciple come indicato dai poster sopra. Hai accesso a IPrinciple a livello di thread.

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