0

我正在寻找在控制器级别加载和授权资源的实现/示例。我正在寻找与ruby​​ on railsload_and_authorize_resource中的cancan gem 相同的功能。

有没有人遇到过/有一个例子如何使用 Mvc .Net 属性实现类似的东西?

谢谢!

load_and_authorize_resource 行为

使用rails,控制器和模型名称按照约定连接起来。该属性load_and_authorize_resource利用了它的优势。当需要资源实例的操作被命中时,load_and_authorize_resource验证是否可以访问资源实例。如果可以,它会将其加载到实例变量中,如果不能,它将返回 404 或您已配置属性以产生的任何错误行为。

例如,如果我有一张资源图片,并且只有拥有某张图片的用户才能编辑该图片的名称。

所以我们会有一个 Edit 动作,它显然会有一个你想要编辑的图片的 pictureId。load_and_authorize_resource 将验证当前上下文/用户是否有权访问资源。

是该模块的小视频介绍。

4

1 回答 1

2

我不知道这种 ASP.NET MVC 插件的存在。为了模仿它的功能,你可以编写一个自定义Authorize属性:

public class LoadAndAuthorizeResourceAttribute : AuthorizeAttribute
{
    private class ModelDescriptor
    {
        public string Name { get; set; }
        public Type ModelType { get; set; }
    }

    private const string ModelTypeKey = "__ModelTypeKey__";
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var parameters = filterContext.ActionDescriptor.GetParameters();
        if (parameters.Length > 0)
        {
            // store the type of the action parameter so that we could access it later
            // in the AuthorizeCore method
            filterContext.HttpContext.Items[ModelTypeKey] = new ModelDescriptor
            {
                Name = parameters[0].ParameterName,
                ModelType = parameters[0].ParameterType,
            };
        }
        base.OnAuthorization(filterContext);
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            // the user is not authenticated or authorized => no need to continue
            return false;
        }

        // get the currently authenticated username
        string username = httpContext.User.Identity.Name;

        // get the id of the resource that he is trying to manipulate
        // the id should be sent either as part of the query string or the routes
        string id = httpContext.Request.RequestContext.RouteData.Values["id"] as string;

        // get the action param type
        var modelDescriptor = httpContext.Items[ModelTypeKey] as ModelDescriptor;

        if (modelDescriptor == null)
        {
            throw new InvalidOperationException("The controller action that was decorated with this attribute must take a model as argument");
        }

        // now load the corresponding entity from your database given the 
        // username, id and type
        object model = LoadModel(id, username, modelDescriptor.ModelType);

        if (model == null)
        {
            // the model that satisfies the given criteria was not found in the database
            return false;
        }

        httpContext.Request.RequestContext.RouteData.Values[modelDescriptor.Name] = model;

        return true;
    }

    private object LoadModel(string id, string username, Type modelType)
    {
        // TODO: depending on how you are querying your database
        // you should load the corresponding model here or return null
        // if not found
        throw new NotImplementedException();
    }
}

现在你可以有一个用这个属性装饰的控制器动作:

[LoadAndAuthorizeResource]
public ActionResult Edit(Picture model)
{
    ... if we get that far the user is authorized to modify this model
}
于 2012-10-09T15:58:28.817 回答