2013-02-15 11 views
5

Mam aplikację MVC uwierzytelnianą w systemie Windows z warstwą repozytorium. Cała interakcja kontrolera z bazą danych odbywa się za pośrednictwem repozytorium. Każdy kontroler ma odniesienie do repozytorium:Wzór wykonywania autoryzacji w warstwie repozytorium aplikacji MVC

public class PostController : Controller 
{ 
    private Repository db = new Repository(); 

    [HttpPost] 
    public ActionResult DeletePost(int id) 
    { 
     // Authorize that the user is allowed to delete this post... 

     db.DeletePost(id); 
    } 
} 

Moje pytanie brzmi, czy jest to dobry sposób, aby przenieść moją logikę autoryzacji w repozytorium warstwy. Chciałbym, aby funkcja Repository.DeletePost() odmawiała usuwania wpisów, które nie zostały utworzone przez uwierzytelnionego użytkownika. Problem polega na tym, że moje repozytorium nie wie, kto jest uwierzytelnionym użytkownikiem. Sterownik wie (przez Controller.User).

Mijając Controller.User do konstruktora Repository nie działa, ponieważ Controller.User najwyraźniej nie zdefiniowane w momencie, gdy konstruktor jest tzw.

W jaki sposób mogę poinformować użytkownika, którego uwierzytelnionym użytkownikiem jest? Czy najlepiej byłoby po prostu zbudować Repository w ramach każdej akcji? Czy jest to zły pomysł, aby obsłużyć go w warstwie repozytorium?

Odpowiedz

1

Dobre sugestie zarówno od @BigDaddy, jak i @ChrisPratt.

W końcu rozwiązałem to, tworząc kontroler podstawowy, podobny do this answer. Moja klasa kontrolera baza wygląda następująco:

public class BaseController : Controller 
{ 
    private ILog _log; 
    private Repository _db; 

    protected Repository Db 
    { 
     get 
     { 
      return _db ?? (_db = new Repository(User)); 
     } 
    } 

    protected ILog Log 
    { 
     get 
     { 
      return _log ?? (_log = LogManager.GetLogger(this.GetType())); 
     } 
    } 
} 

Wszystkie moje kontrolerów dziedziczą z tej klasy, i wbudowany dostęp do leniwy załadowane Repository który ma odniesienie do aktualnie uwierzytelnionego użytkownika.

+0

To właśnie robię, ale uważam, że nie ma wystarczającego "oddzielenia", ponieważ teraz nasze repozytorium jest powiązane z naszym Użytkownikiem, którym może być jakiś Administrator, który nie byłby w stanie nic zrobić, gdyby nie za to na każdym kroku – Worthy7

1

Wystarczy zrobić coś takiego:

db.DeletePostForUser(id, User.Identity.UserId); 

potem w repozytorium:

public void DeletePostForUser(int id, int userId) 
{ 
    var post = context.Posts.SingleOrDefault(m => m.PostId == id && m.User.UserId == userId) 
    if (post != null) 
    { 
     context.Posts.Remove(post); 
     context.SaveChanges(); 
    } 
} 
+0

Dobra sugestia ... Skończyłem z czymś innym, ponieważ może być wiele razy w moim repozytorium, kiedy chcę wiedzieć, kim jest "Użytkownik", i chciałbym uniknąć dodania go do wielu podpisów . – Eric

+1

@Chris, ale czy nasze biura repo powinny wykonywać autoryzację? – uriDium

+0

Zasadniczo, @uriDium ma rację, repositorys są po prostu dla uzyskania i ustawienia. Nie są tam, aby chronić przed tym, który użytkownik to robi. To jest zadanie domeny. Co zrobić, gdy nagle trzeba wprowadzić pewne zmiany w bazie danych przez administratora? Kto ma do niego dostęp, nie ma znaczenia, jeśli chcesz ograniczyć dostęp, ograniczysz dostęp na niższym poziomie w kontrolerach. Następnie warstwa usługi (która może znajdować się w kontrolerze) wykona zadanie sprawdzania poprawności, jeśli użytkownik może wprowadzić te zmiany (nawet jeśli wiąże się to z wywołaniem bazy danych z jakiegoś dziwnego powodu). – Worthy7

3

Czy jest to zły pomysł, aby obsłużyć to w warstwie repozytorium?

Myślę, że kontroler jest lepszym miejscem do autoryzacji. Niech repozytorium będzie bramą do danych, a kontroler będzie strażnikiem do twojej aplikacji. Spodziewam się, że logika autoryzacji/uwierzytelniania będzie widoczna na wczesnym etapie cyklu życia.

+0

Mogę docenić to ... Zobaczę, jak to jest umieszczać moją logikę autoryzacji w repozytorium. Jeśli skończy się uczucie brudu, prawdopodobnie wrócę do twojej sugestii. – Eric

+0

Mam system z WebInterface i WebService, oczywiście potrzebuję dwóch logik uwierzytelniania, ale nie chcę duplikować kodu autoryzacji ... jak rozwiązać ten problem? –

+1

Jeśli nie autoryzujesz na obu poziomach, to w jaki inny sposób możesz kontrolować dostęp? Prawdopodobnie chcesz uwierzytelnić się w warstwie interfejsu użytkownika i zweryfikować uwierzytelnianie w warstwie usługi. Następnie autoryzuj w interfejsie użytkownika i warstwie usług. –

Powiązane problemy