3

MVC4 アプリケーション用のカスタム ロール プロバイダーを作成しました。ここで、CreateRole、GetAllRoles、および RoleExists メソッドを正常にオーバーライドし、次のように既存のデータベースにリンクすることができました。

namespace Project.Providers
{
  public class MyProvider : System.Web.Security.SqlRoleProvider
  {
    private MyContext dbcontext = new MyContext(System.Configuration.ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);
    private Repository<MyUser> userRepository;
    private Repository<Role> roleRepository;

    public MyProvider()
    {
        this.userRepository = new Repository<MyUser>(dbcontext);
        this.roleRepository = new Repository<Role>(dbcontext);
    }

    public override string[] GetAllRoles()
    {
        IEnumerable<Role> dbRoles = roleRepository.GetAll();
        int dbRolesCount = roleRepository.GetAll().Count();
        string[] roles = new string[dbRolesCount];
        int i = 0;
        foreach(var role in dbRoles)
        {
            roles[i] = role.Name;
            i++;
        }
        return roles;
    }

    public override bool RoleExists(string roleName)
    {
        string[] roles = { "Admin", "User", "Business" };
        if(roles.Contains(roleName))
            return true;
        else
            return false;
    }

    public override void CreateRole(string roleName)
    {
        Role newRole = new Role();
        newRole.Name = roleName;
        roleRepository.Add(newRole);
        roleRepository.SaveChanges();
    }

    public override bool IsUserInRole(string userName, string roleName)
    {
        MyUser user = userRepository.Get(u => u.Username == userName).FirstOrDefault();
        Role role = roleRepository.Get(r => r.Name == roleName).FirstOrDefault();
        if (user.RoleID == role.RoleID)
            return true;
        else
            return false;
    }
  }
}

をオーバーライドする方法を見つけることができませんでした

User.IsInRole(string roleName)

他に何をしなければなりませんか?

[Authorize(Roles = "Admin")]

これは、設定したロール プロバイダーに基づいており、asp のデフォルトではありません。

私のユーザークラスは次のようになりました:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using System.Security.Principal;

namespace Project.Data
{
  public class MyUser : IPrincipal
  {
    [Key]
    public int UserID { get; set; }

    [StringLength(128)]
    public string Username { get; set; }              

    .....other properties

    public IIdentity Identity { get; set; }

    public bool IsInRole(string role)
    {
        if (this.Role.Name == role)
        {
            return true;
        }
        return false;
    }

    public IIdentity Identity
    {
        get { throw new NotImplementedException(); }
    }
  }
}

私のスタック トレースは次の場所に続いているようです。

System.Web.Security.RolePrincipal.IsInRole(String role) 

だから私は、カスタム Provider を設定するのと同じ方法でカスタム RolePrincipal を実装しようとしましたが、これを行う方法はありますか? 必要なコンストラクターのパラメーターがわからない。これが私の試みです:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration.Provider;
using Project.Data;
using System.Web.Security;
using System.Security.Principal.IIdentity;

namespace Project.Principal
{
  public class MyPrincipal : System.Web.Security.RolePrincipal
  {
    private MyContext dbcontext = new MyContext(System.Configuration.ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);
    private Repository<MyUser> userRepository;
    private Repository<Role> roleRepository;        

    public MyPrincipal()
    {
        this.userRepository = new Repository<MyUser>(dbcontext);
        this.roleRepository = new Repository<Role>(dbcontext);
    }

    public override bool IsInRole(string role)
    {
        //code to be added
        return true;
    }
}

}

4

3 に答える 3

7

You just need to override method GetRolesForUser in your custom role provider, instead of the more logical IsUserInRole, because that is what is called by the default implementation that does some unwanted caching.

于 2014-05-06T19:44:29.103 に答える
2

IPrincipal クラスで IsInRole をオーバーライドすると、私の EF は次のようになります。

public class MyUser : IPrincipal {
    //Properties
    ...
    public bool IsInRole(string role) {
        if (Roles.Any(m=>m.NameKey.ToLower().Equals(role.ToLower()))) {
            return true;
        }
        return false;
    }
}

次に、RoleProvider と MembershipProvider の両方の webconfig に適切なセクションを追加すると、Authorize 属性に適しているはずです。

コメントに応じて更新

web Config は次のようになります。

...
<authentication mode="Forms">
  <forms loginUrl="~/Login" timeout="2880"></forms>
</authentication>
<authorization>
</authorization>

..

<membership defaultProvider="MyMembershipProvider">
  <providers>
    <add name="MyMembershipProvider" type="MyApp.Infrastructure.MyMembershipProvider" connectionStringName="connectionstring" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" />
  </providers>
</membership>
<roleManager defaultProvider="MyRoleProvider" enabled="true" cacheRolesInCookie="true">
  <providers>
    <clear />
    <add name="MyRoleProvider" type="MyApp.Infrastructure.MyRoleProvider" />
  </providers>
</roleManager>
...

プロバイダーでは、ユーザーはあなたIPrincipalですか?

public MyUser User { get; private set; }

ユーザーは、IIdentity

MyUser.cs で:

    ...
    public virtual ICollection<Role> Roles { get; set; }
    public IIdentity Identity { get; set; }

あなたのコメントからのトラブルシューティングに役立つ追加のアドバイスはあまりありません。

アップデート

私が経験したいくつかの例は、鉱山をセットアップするときに役立ちました: http://www.brianlegg.com/post/2011/05/09/Implementing-your-own-RoleProvider-and-MembershipProvider-in-MVC-3. aspx

http://www.mattwrock.com/post/2009/10/14/Implementing-custom-MembershipProvider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx

http://blogs.msdn.com/b/rickandy/archive/2012/03/23/securing-your-asp-net-mvc-4-app-and-the-new-allowanonymous-attribute.aspx?Redirected=真実

最初の実行で他の多くの記事や SO の投稿を読みましたが、これらはわざわざブックマークしたものでした。私は承認に対して役割/権利のアプローチを採用しました。そのため、そのうちの1つはそのように調整されています。

于 2013-08-23T22:59:50.257 に答える