web-dev-qa-db-ja.com

複数の役割とユーザーのMVC3動的承認

私は最近MVC3の開発を開始しましたが、以前からC#とASP.NETの両方の経験があります。だから私は私が達成しようとしていることから始めましょう。私は記事をホストするための小さなサイトを開発しました。 SQLServerベースのメンバーシップ管理をサイトに実装しました。次に、適切なユーザーが記事を作成、削除、更新できるように制限および許可する資格情報システムを作成したいと思います。これに対する1つの簡単な解決策があり、それは次のようにすることです。

[Authorize(Roles="Admin")]
    public ActionResult UpdateArticle(ArticleModel model, int articleid)
    {
        return View();
    }

今、これは本当に簡単です。 「管理者」の役割を持つメンバーだけが記事を更新できると言っているだけです。しかし、それは静的なものです。そこで、データベースに資格情報テーブルを作成しました。これは、最終的に「第5条はロール1、2、3、4およびユーザーA、b、Cで編集できる」というものです。ここまでは順調ですね。しかし、Authorizeソリューションでそれをどのように実装しますか?

私はこのようなことをしたいと思います:

[Authorize(getAuthorizedusers("update",this.articleid))]

ここで、getAuthorizedusersは、渡されたarticleidで記事を更新することを許可されているユーザーとロールを返します。

したがって、ここには(少なくとも)2つの問題があります。-Authorizeメソッドで複数のユーザーとロールを受け入れるようにする。 -UpdateArticleメソッドに送信された提供されたarticleidをgetAuthorizedusersメソッドに渡します。

19

AuthorizeAttributeから継承する独自のカスタム属性を作成し、OnAuthorizeメソッドをオーバーライドして必要な処理を実行できます。

これで始められるはずです:

public class ArticleAuthorizeAttribute : AuthorizeAttribute
{
    public enum ArticleAction
    { 
        Read,
        Create,
        Update,
        Delete
    }

    public ArticleAction Action { get; set; }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        //do custom authorizization using Action and getting ArticleID 
        //from filterContext.HttpContext.Request.QueryString or
        //filterContext.HttpContext.Request.Form
    }
}

使用法は次のようになります。

[ArticleAuthorize(Action=ArticleAuthorizeAttribute.ArticleAction.Update)]

編集:これをもう少し調べた後、this.articleIDを属性に渡すことができないようです。ただし、値の受け渡し方法に応じて、filterContext.HttpContext.RequestからQueryStringプロパティまたはFormプロパティを介してパラメータにアクセスできます。コードサンプルを適切に更新しました。

より完全な例を見つけることができます ここ

ユーザーロールとユーザーリストを使用して承認を確認するには、次のようにします。

        var allowedUsers = new List<string>();
        //populate allowedUsers from DB

        If (User.IsInRole("Update") || allowedUsers.Contains(User.Identity.Name))
        {
            //authorized
        }

または、1つのメソッドでDBに対して両方のチェックを直接実行して、2回の呼び出しを行わないようにすることもできます。

19
Jimmie R. Houts

AuthorizeCoreメソッドを無効にして、希望どおりに認証すると、希望どおりに機能するようになりました。

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException("httpContext");
        }

        IPrincipal user = httpContext.User;
        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }

        if ((_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) && (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole)))
        {
            return false;
        }

        return true;
    }
2

同じことを達成するためのはるかに簡単な方法は次のとおりです。

[Authorize]
public ActionResult UpdateArticle(ArticleModel model, int articleid)
{
    // if current user is an article editor
    return View();
    // else
    return View("Error");
}
2
David Wick