Обработка безопасности на уровне записей / сущностей в приложении ASP.NET MVC - PullRequest
15 голосов
/ 23 ноября 2011

Что делают все для защиты (извлечения и изменения) отдельных записей в приложении ASP.NET MVC?Это приложение имеет уровень обслуживания / бизнеса и уровень доступа к данным, которые полностью отделены от пользовательского веб-интерфейса.Я уже использую поставщиков членства и ролей для обработки аутентификации и авторизации для определенных областей / функций в моем приложении, но теперь мне нужно защитить отдельные записи.

Например, скажем, Боб может создавать и редактировать свой собственный FooBarзаписей.Я хочу убедиться, что другие пользователи не могут просматривать или редактировать записи Боба.Я хочу защититься от манипулирования URL и / или ошибок программирования.Мы также можем захотеть разрешить Бобу делиться своими FooBars с другими пользователями, позволяя им просматривать, но не редактировать свои записи.

Существует несколько подходов, которые я предложил:

  • Выполните проверки безопасности на уровне доступа к данным, непосредственно в запросах на получение и изменение.
  • Проверьте безопасность на уровне служб, выполнив дополнительные запросы безопасности, прежде чем переходить к бизнес-логике.
  • СозданиеУровень безопасности, который существует между пользовательским интерфейсом и уровнем сервиса.Пользовательский интерфейс будет выполнять все запросы через уровень безопасности.
  • Использовать аспектно-ориентированное программирование (AOP).Создайте аспекты безопасности и украсьте методы уровня Service атрибутами безопасности.

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

Ответы [ 3 ]

2 голосов
/ 24 ноября 2011

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

public class FooBarController : Controller
{

    //this is easy as compared to edit
    [Authorized]
    public ActionResult Create()
    {


    }


    [AjaxAuthorize(Roles = "Administrator")]    
    public ActionResult Edit(int id)
    {


    }
}

public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {


        var id = filterContext.RouteData.Values["id"];
        // Here you can check if the id belongs to logged in user
        var content = SomeRepository.GetById(id);
        if (contet.OwnerId=LoggedInUser.Id)
           return;

        //otherwise check if logged in user is from some Admin or other role.


        string redirectPage = "/account/logon";
        var roles = base.Roles.Trim().Split(',');
        bool CanAccess = false;

        //If no role is there
        if (base.Roles.Equals(string.Empty) || roles.Count() == 0)
        {
            CanAccess = true;
        }
        else
        {
            foreach (var item in roles)
            {
                CanAccess = filterContext.HttpContext.User.IsInRole(item);
                if (CanAccess)
                    break;
            }
        }

        var request = filterContext.RequestContext.HttpContext.Request;
        if (request.IsAjaxRequest())
        {
            if (!(request.IsAuthenticated && CanAccess))
            {
                filterContext.Result = new AjaxAwareRedirectResult(redirectPage);
                return;
            }
        }

        base.OnAuthorization(filterContext);
    }
}

public class AjaxAwareRedirectResult : RedirectResult
{
    public AjaxAwareRedirectResult(string url)
        : base(url)
    {
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context.RequestContext.HttpContext.Request.IsAjaxRequest())
        {

            string destinationUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext);

            JavaScriptResult result = new JavaScriptResult()
            {
                Script = "window.location='" + destinationUrl + "';"
            };
            result.ExecuteResult(context);
        }
        else
            base.ExecuteResult(context);
    }
}

Теперь вы можете разрешить редактирование контента владельцем или администратором.Я называю этот Атрибут Ajax, потому что он также будет обрабатывать AjaxRequest.Надеюсь, это поможет.

С уважением

Parinder

2 голосов
/ 23 ноября 2011

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

AOP звучит как способ полностью потерять контроль над кодом, а безопасность в DAL звучит как неправильный подход, поскольку он смешивает разные обязанности.

0 голосов
/ 03 февраля 2012
public class Entity
{
     public Right[] Rights { get; set; }         
}

public class Right
{
     public User user {get;set;}
     public Permission[] permissions {get;set;}

}

public class Foo : Entity
{


}

public class Bar : Entity
{

}

В вышеприведенном подходе есть объект базового класса, в котором хранятся права, которые конкретный пользователь имеет над этим объектом.Унаследуйте все классы, которые вы хотите защитить, от класса Entity.

...