0

コントローラーレベルでリソースをロードして承認する実装/例を探していました。load_and_authorize_resourceRubyonRailsのカンカンジェムと同じ機能を探しています。

誰かが1つに出くわした/Mvc.Net属性を使用して同様の何かを実装する方法の例がありますか?

ありがとう!

load_and_authorize_resourceの動作

Railsでは、コントローラーとモデルの名前は慣例によりリンクされています。属性load_and_authorize_resourceはそれを利用します。リソースのインスタンスを必要とするアクションがヒットすると、リソースload_and_authorize_resourceのインスタンスにアクセスできるかどうかを検証します。可能であれば、インスタンス変数にロードし、できない場合は、生成する属性を構成した404またはエラー動作を返します。

たとえば、リソース画像があり、特定の画像を所有しているユーザーのみが画像の名前を編集できる場合です。

したがって、編集アクションがあります。これには、編集する画像の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 に答える