Asp.net

ASP.NET MVC 如何創建自定義角色提供程序

  • August 12, 2021

作為 ASP MVC 的新手,我不確定哪個更適合我的需要。我已經使用 Windows 身份驗證建構了一個 Intranet 站點,並且我能夠使用 Active Directory 角色保護控制器和操作,例如

[Authorize(Roles="Administrators")]
[Authorize(Users="DOMAIN\User")]
public ActionResult SecureArea()
{
   ViewBag.Message = "This is a secure area.";
   return View();
}

我需要獨立於 AD 角色定義自己的安全形色。所需的功能是根據我的應用程序數據庫中與他們的個人資料關聯的一個或多個角色授予經過身份驗證的使用者對特定操作的訪問權限,例如:“經理”、“使用者”、“訪客”、“分析師”、“開發人員”等。

如何創建自定義角色提供者和/或自定義授權屬性?

我的解決方案是創建一個自定義角色提供程序。以下是我採取的步驟,以防其他人以後需要幫助:

創建您的自定義使用者和角色類

using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Security.Models.Security
{
   public class AppRole : IdentityRole
   {
   }
}

using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Security.Models.Security
{
   public class AppUser : IdentityUser
   {
   }
}

設置數據庫上下文

using Microsoft.AspNet.Identity.EntityFramework;
using Security.Models.Security;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace Security.Models.DAL
{
   public class UserContext : IdentityDbContext<AppUser>
   {
       public UserContext() : base("UserContext")
       {
           Database.SetInitializer<UserContext>(new CreateDatabaseIfNotExists<UserContext>());
       }
   }
}

創建您的角色提供者並實現以下方法

using Security.Models.DAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;

namespace Security.Models.Security
{
   public class AppRoleProvider : RoleProvider
   {
       public override string[] GetAllRoles()
       {
           using (var userContext = new UserContext())
           {
               return userContext.Roles.Select(r => r.Name).ToArray();
           }
       }

       public override string[] GetRolesForUser(string username)
       {
           using (var userContext = new UserContext())
           {
               var user = userContext.Users.SingleOrDefault(u => u.UserName == username);
               var userRoles = userContext.Roles.Select(r => r.Name);

               if (user == null)
                   return new string[] { };
               return user.Roles == null ? new string[] { } :
                   userRoles.ToArray();
           }
       }

       public override bool IsUserInRole(string username, string roleName)
       {
           using (var userContext = new UserContext())
           {
               var user = userContext.Users.SingleOrDefault(u => u.UserName == username);
               var userRoles = userContext.Roles.Select(r => r.Name);

               if (user == null)
                   return false;
               return user.Roles != null &&
                   userRoles.Any(r => r == roleName);
           }
       }
   }
}

編輯您的 web.config 以設置數據庫連接和角色提供程序參考

<connectionStrings>
   <add name="UserContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\UserContext.mdf;Initial Catalog=UserContext;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>

<system.web>
   ...
   <authentication mode="Windows" />        
   <roleManager enabled="true" defaultProvider="AppRoleProvider">
     <providers>
       <clear/>
       <add name="AppRoleProvider" type="Security.Models.Security.AppRoleProvider" connectionStringName = "UserContext"/>
     </providers>
     ...
   </roleManager>
 </system.web>

在包管理器控制台中,啟用遷移

enable-migrations

在新創建的 Configurations.cs 中設置使用者/角色儲存和管理器,並將使用者管理器驗證器配置為接受“\”字元

namespace Security.Migrations
{
   using Microsoft.AspNet.Identity;
   using Microsoft.AspNet.Identity.EntityFramework;
   using Security.Models.Security;
   using System;
   using System.Data.Entity;
   using System.Data.Entity.Migrations;
   using System.Linq;

   internal sealed class Configuration : DbMigrationsConfiguration<Security.Models.DAL.UserContext>
   {
       public Configuration()
       {
           AutomaticMigrationsEnabled = true;
           ContextKey = "Security.Models.DAL.UserContext";
       }

       protected override void Seed(Security.Models.DAL.UserContext db)
       {
           // Set up the role store and the role manager
           var roleStore = new RoleStore<AppRole>(db);
           var roleManager = new RoleManager<AppRole>(roleStore);

           // Set up the user store and the user mananger
           var userStore = new UserStore<AppUser>(db);
           var userManager = new UserManager<AppUser>(userStore);

           // Ensure that the user manager is able to accept special characters for userNames (e.g. '\' in the 'DOMAIN\username')            
           userManager.UserValidator = new UserValidator<AppUser>(userManager) { AllowOnlyAlphanumericUserNames = false };

           // Seed the database with the administrator role if it does not already exist
           if (!db.Roles.Any(r => r.Name == "Administrator"))
           {
               var role = new AppRole { Name = "Administrator" };
               roleManager.Create(role);
           }

           // Seed the database with the administrator user if it does not already exist
           if (!db.Users.Any(u => u.UserName == @"DOMAIN\admin"))
           {
               var user = new AppUser { UserName = @"DOMAIN\admin" };
               userManager.Create(user);
               // Assign the administrator role to this user
               userManager.AddToRole(user.Id, "Administrator");
           }
       }
   }
}

在包管理器控制台中,確保數據庫已創建並播種

update-database

創建一個自定義授權屬性,該屬性將在失敗時重定向到拒絕訪問頁面

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Security.Models.Security
{
   public class AccessDeniedAuthorizationAttribute : AuthorizeAttribute
   {
       public override void OnAuthorization(AuthorizationContext filterContext)
       {
           base.OnAuthorization(filterContext);

           if(filterContext.Result is HttpUnauthorizedResult)
           {
               filterContext.Result = new RedirectResult("~/Home/AccessDenied");
           }
       }
   }
}

你完成了!您現在可以創建一個拒絕訪問頁面(在本例中為 ~/Home/AccessDenied)並將該屬性應用於任何操作,例如

using Security.Models.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Security.Controllers
{
   public class HomeController : Controller
   {
        ...    

       [AccessDeniedAuthorizationAttribute(Roles = "Administrator")]
       public ActionResult SecureArea()
       {
           return View();
       }

       public ActionResult AccessDenied()
       {
           return View();
       }

       ...
   }
}

希望這對將來的某人有所幫助。祝你好運!

引用自:https://stackoverflow.com/questions/41940905