2013-08-23 24 views
2

我已經創建了我的MVC4應用自定義角色提供這樣我就能夠成功覆蓋CREATEROLE,GetAllRoles和RoleExists方法,並將其鏈接[授權(角色=「管理員」)爲MVC4應用我現有的數據庫如下:重寫User.IsInRole和

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) 

所以我試圖執行相同的方式我自定義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; 
    } 
} 

}

+0

延伸RolePrincipal你最後的代碼示例正在從什麼我都做了。 – Matthew

回答

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; 
    } 
} 

然後,一旦你的相應章節添加到您的webconfig爲RoleProvider和MembershipProvider都應該適合Authorize屬性。響應您的意見

UPDATE

網絡配置應該是這樣的:

... 
<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; } 

我沒有太多額外的意見,以幫助從您的意見解決。

UPDATE

一些例子我已經通過,並設置礦最多時發現的有用: 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=true

我看了很多其他文章和SO崗位上我的第一次經歷,但這些都是我打擾書籤的東西。我採取了角色/權利的方式來進行授權,這就是爲什麼其中一個方法適合這種方式。

+0

我試圖上述建議,我收到以下錯誤:「Project.Data.User」不實現接口成員「System.Security.Principal.IPrincipal.Identity」 – Jay

+0

我通過點擊的IPrincipal的端部實現的接口和單擊ALT + SHIFT + F10。現在,我得到一個非靜態方法需要一個目標錯誤 – Jay

+0

我的堆棧跟蹤似乎是在以下位置:System.Web.Security.RolePrincipal.IsInRole(字符串角色)我試圖實現我設置相同的方式自定義RolePrincipal定製提供商的任何想法我可以做到這一點?不知道是什麼構造PARAMS需要 – Jay

7

你只需要覆蓋您的自定義角色提供方法GetRolesForUser,而不是更合乎邏輯的isUserInRole,因爲這是由做一些不必要的高速緩存的默認實現調用。