2013-02-15 2 views
5

У меня есть Windows-аутентифицированное MVC-приложение с уровнем репозитория. Все взаимодействие контроллера с базой данных осуществляется через репозиторий. Каждый контроллер имеет ссылку на репозиторий:Шаблон для выполнения авторизации в слое репозитория приложения 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); 
    } 
} 

Мой вопрос заключается в том, есть ли хороший способ, чтобы переместить мою логику авторизации в слой хранилище. Я хотел бы, чтобы функция Repository.DeletePost() отказала в удалении сообщений, которые не были созданы аутентифицированным пользователем. Проблема в том, что мой репозиторий не знает, кем является аутентифицированный пользователь. Контроллер знает (через Controller.User).

Передача Controller.User в конструктор Repository не работает, потому что Controller.User, по-видимому, не определен в момент вызова конструктора.

Как я могу сообщить Repository, кто является аутентифицированным пользователем? Было бы лучше всего построить Repository в каждом действии? Или это плохая идея справиться с этим на уровне репозитория?

ответ

1

Хорошие рекомендации от @BigDaddy и @ChrisPratt.

Я решил это решить, создав базовый контроллер, аналогичный this answer. Мой базовый класс контроллер выглядит следующим образом:

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())); 
     } 
    } 
} 

Все мои контроллеры наследовать от этого класса, и встроенный доступ к ленивым загруженным Repository, который имеет ссылку на текущую проверку подлинности пользователя.

+0

Это то, что я действительно делаю, но я чувствую, что не хватает «развязки», поскольку теперь наш репозиторий привязан к нашему пользователю, который может быть каким-то администратором, который не смог бы ничего сделать, если бы не был учтен для этого на каждом шагу – Worthy7

1

Просто сделать что-то вроде:

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

Тогда в вашем репозитории:

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

Хорошее предложение ... Я закончил с чем-то другим, потому что в моем репозитории может быть много раз, когда я хочу знать, кто является «Пользователь», и я бы хотел, чтобы он не добавлял его во многие подписи , – Eric

+1

@ Крис, но должны ли наши РЕПО делать авторизацию? – uriDium

+0

В принципе, @uriDium прав, репозитории предназначены только для получения и настройки. Они не защищены, от чего пользователь это делает. Это работа домена. О том, когда вам вдруг понадобится внести некоторые изменения в базу данных администратором? Кто обращается к нему, не имеет значения, если вы хотите ограничить доступ, тогда вы ограничиваете доступ на более низком уровне в контроллерах. Тогда сервисный уровень (который может быть в контроллере) будет выполнять проверку достоверности, если пользователь может внести эти изменения (даже если это связано с вызовом базы данных по какой-то нечетной причине) – Worthy7

3

Или это плохая идея, чтобы справиться с этим в хранилище слой?

Я думаю, что контроллер лучше для вашего разрешения. Пусть репозиторий будет шлюзом данных, а контроллер - привратником для вашего приложения. Я ожидаю увидеть логику авторизации/аутентификации как можно раньше на жизненном цикле.

+0

Я могу оценить это ... Я собираюсь посмотреть, как он чувствует, что моя логика авторизации находится в репозитории. Если это окажется грязным, тогда я, вероятно, вернусь к вашему предложению. – Eric

+0

У меня есть система с WebInterface & WebService, , конечно, мне нужны две логики аутентификации, но я не хочу дублировать код авторизации ... как вы решаете это? –

+1

Если вы не авторизуетесь на обоих уровнях, то как еще вы можете контролировать доступ? Вероятно, вы хотите пройти аутентификацию на уровне пользовательского интерфейса и проверить подлинность на уровне сервиса. Затем авторизуйтесь на пользовательском интерфейсе и уровне обслуживания. –