Обработка безопасности записи/уровня сущности в приложении ASP.NET MVC
Что все делают для обработки безопасности (поиска и изменения) отдельных записей в приложении ASP.NET MVC? Это приложение имеет уровень Service/Business и уровень доступа к данным, которые полностью отделены от пользовательского интерфейса Web. Я уже использую поставщики членства и ролей для проверки подлинности и авторизации для определенных областей/функций в моем приложении, но теперь мне нужно защитить отдельные записи.
Например, скажем, Боб может создавать и редактировать собственные записи FooBar. Я хочу, чтобы другие пользователи не могли просматривать или редактировать записи Боба. Я хочу защитить от манипулирования URL-адресами и/или ошибок программирования. Мы также можем разрешить Бобу делиться своими FooBars с другими пользователями, позволяя им просматривать, но не редактировать свои записи.
Есть несколько подходов, которые я придумал:
- Выполняйте проверки безопасности на уровне доступа к данным непосредственно в запросах поиска и изменения.
- Проверьте безопасность на уровне сервиса, выполняя дополнительные запросы безопасности, прежде чем приступать к бизнес-логике.
- Создайте уровень безопасности, который существует между пользовательским интерфейсом и уровнем сервиса. Пользовательский интерфейс выполнит все запросы через уровень безопасности.
- Используйте аспектно-ориентированное программирование (АОП). Создайте аспекты безопасности и украсьте методы уровня сервиса атрибутами безопасности.
Я сделал безопасность на уровне доступа к данным (в запросах) в предыдущих проектах, и он всегда превращается в беспорядок. Я хотел бы знать, что делают все остальные, и какие рамки вы используете, чтобы помочь вам (рамки AOP.)
Ответы
Ответ 1
Я всегда принимаю 2-й и/или 3-й из ваших подходов - явный уровень безопасности где-то между пользовательским интерфейсом и логическими обработчиками.
AOP звучит как способ полностью потерять контроль над кодом, а безопасность в DAL звучит как неправильный подход, поскольку он смешивает различные обязанности.
Ответ 2
Я думаю, что повсеместное применение логики может быть проблемой. У меня такая же ситуация. Позвольте мне объяснить, как я его обрабатываю.
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
Ответ 3
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, который сохраняет права, которые определенный пользователь имеет над этим объектом. Наследуйте все классы, которые вы хотите защитить от класса Entity.