简体   繁体   中英

FluentSecurity 2.0 support for action with parameters

In my .net mvc 4 app I am using the latest release of FluentSecurity (1.4) in order to secure my actions.

Here is an example that illustrates my problem:

Suppose I have a controller with 2 edit actions (get and post):

    public class MyController : Controller
{
    //
    // GET: /My/

    public ActionResult Edit(decimal id)
    {
        var modelToReturn = GetFromDb(id);
        return View(modelToReturn);
    }

    [HttpPost]
    public ActionResult Edit(MyModel model)
    {
        Service.saveToDb(model);
        return View(model);
    }

}

Now, I would like to have a different security policy for each action. To do that I define (using fluent security):

    configuration.For<MyController>(x => x.Edit(0))
                                         .AddPolicy(new MyPolicy("my.VIEW.permission"));
    configuration.For<MyController>(x => x.Edit(null))
                                         .AddPolicy(new MyPolicy("my.EDIT.permission"));

The first configuration refers to the get while the second to the post. If you wonder why I'm sending dummy params you can have a look here and here .

Problem is that fluent security can't tell the difference between those 2, hence this doesn't work.

Couldn't find a way to overcome it (I'm open for ideas) and I wonder if installing the new 2.0 beta release can resolve this issue.

Any ideas?

It is currently not possible to apply different policies to each signature in FluentSecurity. This is because FluentSecurity can not know what signature will be called by ASP.NET MVC. All it knows is the name of the action. So FluentSecurity has to treat both action signatures as a single action.

However , you can apply multiple policies to the same action (you are not limited to have a single policy per action). With this, you can apply an Http verb filter for each of the policies. Below is an example of what it could look like:

1) Create a base policy you can inherit from

public abstract class HttpVerbFilteredPolicy : ISecurityPolicy
{
    private readonly List<HttpVerbs> _httpVerbs;

    protected HttpVerbFilteredPolicy(params HttpVerbs[] httpVerbs)
    {
        _httpVerbs = httpVerbs.ToList();
    }

    public PolicyResult Enforce(ISecurityContext securityContext)
    {
        HttpVerbs httpVerb;
        Enum.TryParse(securityContext.Data.HttpVerb, true, out httpVerb);

        return !_httpVerbs.Contains(httpVerb)
            ? PolicyResult.CreateSuccessResult(this)
            : EnforcePolicy(securityContext);
    }

    protected abstract PolicyResult EnforcePolicy(ISecurityContext securityContext);
}

2) Create your custom policy

public class CustomPolicy : HttpVerbFilteredPolicy
{
    private readonly string _role;

    public CustomPolicy(string role, params HttpVerbs[] httpVerbs) : base(httpVerbs)
    {
        _role = role;
    }

    protected override PolicyResult EnforcePolicy(ISecurityContext securityContext)
    {
        var accessAllowed = //... Do your checks here;
        return accessAllowed
            ? PolicyResult.CreateSuccessResult(this)
            : PolicyResult.CreateFailureResult(this, "Access denied");
    }
}

3) Add the HTTP verb of the current request to the Data property of ISecurityContext and secure your actions

SecurityConfigurator.Configure(configuration =>
{
    // General setup goes here...

    configuration.For<MyController>(x => x.Edit(0)).AddPolicy(new CustomPolicy("my.VIEW.permission", HttpVerbs.Get));
    configuration.For<MyController>(x => x.Edit(null)).AddPolicy(new CustomPolicy("my.EDIT.permission", HttpVerbs.Post));

    configuration.Advanced.ModifySecurityContext(context => context.Data.HttpVerb = HttpContext.Current.Request.HttpMethod);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM