What is everyone doing to handle security (retrieval and modification) of individual records in an ASP.NET MVC application? This application has a Service/Business layer and a Data Access layer that are completely separate from the Web user interface. I am already using the membership and roles providers to handle authentication and authorization for specific areas/features in my application, but now I need to secure individual records.
For example, say Bob can create and edit his own FooBar records. I want to ensure that other users cannot view or edit Bob's records. I want to protect against URL manipulation and/or programming mistakes. We may also want to allow Bob to share his FooBars with other users, allowing them to view but not edit his records.
There are several approaches I have come up with:
I've done security in the Data Access layer (in the queries) in previous projects, and it always turns into a mess. I would like to know what everyone else is doing, and what frameworks you are using to help you (AOP frameworks.)
I always take 2nd and/or 3rd of your approaches - an explicit security layer somewhere between the UI and logic handlers.
AOP sounds like a way to completely lose control over the code and the security in DAL sounds like a wrong approach as it mixes up different responsibilities.
I think putting logic everywhere might be a problem. I am having similar situation. Let me explain how I am handling it.
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);
}
}
Now you can allowing Editing of the content either by the owner or by the administrator. I am calling this Attribute as Ajax, because it will handle AjaxRequest also. I hope this helps.
Regards
Parinder
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With