Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling record/entity level security in an ASP.NET MVC application

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:

  • Do the security checks in the Data Access layer, directly in the retrieval and modification queries.
  • Check security in the Service layer, performing extra security queries before proceeding with the Business logic.
  • Create a Security layer that exists between the UI and the Service layer. The UI would make all requests through the Security layer.
  • Use aspect-oriented programming (AOP). Create security aspects and decorate the Service layer methods with security attributes.

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.)

like image 589
Sigray Avatar asked Nov 23 '11 19:11

Sigray


2 Answers

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.

like image 142
Wiktor Zychla Avatar answered Nov 04 '22 13:11

Wiktor Zychla


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

like image 33
Parminder Avatar answered Nov 04 '22 15:11

Parminder