Безопасность документов в ASP.NET MVC - PullRequest
5 голосов
/ 05 октября 2009

Я уже знаю о безопасности пользователей и ролей в ASP.NET MVC. Но теперь мне нужно что-то более гранулярное.

Допустим, у меня есть список документов, для некоторых из которых пользователь авторизован, для некоторых нет. Каждый документ имеет соответствующую запись в таблице документов в базе данных. Документы можно скачать для просмотра, если у пользователя есть безопасный доступ. Документы также могут быть добавлены, если у вас есть роль. У каждого документа есть URL, а у каждого списка документов есть URL.

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

Подходит ли для этого встроенная модель безопасности на основе ролей или мне нужно создать отдельную безопасность на основе таблиц? Могу ли я установить безопасность в своем хранилище, чтобы возвращаемые записи уже были обрезаны, или это должно быть частью контроллера? Нужен ли мне атрибут безопасности для проверки запроса контроллера, или я должен просто поместить его в метод контроллера в качестве первых нескольких строк кода?

Ответы [ 2 ]

1 голос
/ 06 октября 2009

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

Прежде чем я напишу код, я отвечу на ваши вопросы.

Нужно ли создавать отдельно, безопасность на основе таблиц?

1009 * Да *

Могу ли я поставить безопасность в моем хранилище, так что возвращаемый записи уже обрезаны или должны это будет частью контроллера?

-Я думаю, что безопасность должна быть частью бизнес-логики, поэтому я бы поместил ее где-то между контроллером и хранилищем.

Нужен ли мне атрибут безопасности для проверить запрос контроллера?

-В моем проекте я поместил его в атрибут, но иногда мне нужно получить к нему доступ от контроллера к, но с тех пор я сохраняю логику безопасности на бизнес-уровне, я не думаю, что это проблема.

Первый атрибут - это простой атрибут, который позволяет зарегистрированным пользователям выполнять действие:

public class LoggedUserFilterAttribute : ActionFilterAttribute
{
    public bool Logged { get; set; }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!SessionManager.IsUserLogged)
        {
            filterContext.Result = new RedirectToRouteResult(GetRedirectToNotLoggedRouteValues());
            this.Logged = false;
        }
        else
            this.Logged = true;
    }

    public RouteValueDictionary GetRedirectToNotAuthorizedRouteValues()
    {
        RouteValueDictionary routeValues = new RouteValueDictionary();
        routeValues.Add("action", "NotAuthorized");
        routeValues.Add("controller", "Authorization");
        return routeValues;
    }
    public RouteValueDictionary GetRedirectToNotLoggedRouteValues()
    {
        RouteValueDictionary routeValues = new RouteValueDictionary();
        routeValues.Add("action", "NotLogged");
        routeValues.Add("controller", "Authorization");
        return routeValues;
    }
}

и затем у меня есть, например, атрибут, который позволяет только SuperUsers получить к нему доступ:

public class SuperUserFilterAttribute : LoggedUserFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);

        if (Logged)
        {
            MyBaseController controller = filterContext.Controller as MyBaseController;
            if (controller == null)
                throw new Exception("Please use MyBaseController instead of built in Controller");

            User loggedUser = controller.Model.UserBO.GetUserByID(SessionManager.LoggedUser.UserID);

            if(!loggedUser.IsSuperUser)
            {
                filterContext.Result = new RedirectToRouteResult(GetRedirectToNotAuthorizedRouteValues());
            }
        }
    }
}

MyBaseController - это класс, который наследует Controller и имеет экземпляр класса Model, который представляет контейнер для бизнес-объектов. В теле действия контроллеров, при необходимости, я проверяю права пользователей на текущую сущность и в зависимости от этого возвращаю правильное представление:

    [LoggedUserFilter]
    public ActionResult LoadSomeEntity(int customerServiceID,int entityID)
    {
        UserRights userPermissionsView = Model.SecurityBO.GetUsersRightsOnEntity(SessionManager.LoggedUser.UserID, entityID);

        if(userPermissionsView.Write) 
            return View("EditEntity",Model.EntityBO.GetEntityByID(entityID));
        if(userPermissionsView.Read) 
            return View("ViewEntity",Model.EntityBO.GetEntityByID(entityID));

        return View("NotAuthorized");     
    }

p.s. Я не уверен, что могу что-то предложить кому-то, у кого явно больше опыта, чем у меня :), поэтому, если я спамлюсь, прошу прощения за это.

1 голос
/ 06 октября 2009

@ Роберт, я думаю, что вы уже ответили на свой вопрос, когда сказали, что должны урезать их (до того, как они достигнут представления). Таким образом, в вашей бизнес-логике, в качестве предпочтения над хранилищем, вы, возможно, захотите сделать лямду, чтобы обрезать лишнее, так сказать.

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

Что касается закладок, я думаю, что вам нужно будет выполнить некоторую бизнес-логику, чтобы они не переходили на URL, когда доступ больше не существует.

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

Возможно, это не то, что вы имели в виду, но, если нет лучшего подхода, я бы использовал его.

...