ASP.NET MVC 5 中的简单角色管理器和授权,无需使用 Identity(CustomRoleProvider)

Posted

技术标签:

【中文标题】ASP.NET MVC 5 中的简单角色管理器和授权,无需使用 Identity(CustomRoleProvider)【英文标题】:Simple Role Manager and authorization In ASP.NET MVC 5 without using Identity(CustomRoleProvider) 【发布时间】:2018-07-23 11:00:31 【问题描述】:

在 ASP.NET MVC 5 中不使用身份的自定义角色提供程序和授权

【问题讨论】:

【参考方案1】:

这里是角色控制器

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

namespace SN.Helios.Portal.Controllers

    [Authorize(Roles = "Admin")]
    public class RolesController : Controller
    
        // GET: Roles
        public ActionResult Index()
        
            var context = new ApplicationDbContext();

            var rolelist = context.Roles.OrderBy(r => r.RoleName).ToList().Select(rr =>
            new SelectListItem  Value = rr.RoleName.ToString(), Text = rr.RoleName ).ToList();
            ViewBag.Roles = rolelist;

            var userlist = context.Employees.OrderBy(u => u.FullName).ToList().Select(uu =>
            new SelectListItem  Value = uu.FullName.ToString(), Text = uu.FullName ).ToList();
            ViewBag.Users = userlist;

            ViewBag.Message = "";

            return View();

        

        // GET: /Roles/Create
        public ActionResult Create()
        
            return View();
        


        //
        // POST: /Roles/Create
        [HttpPost]
        public ActionResult Create(Role role)
        

            try
            
                var context = new ApplicationDbContext();
                context.Roles.Add(role);
                context.SaveChanges();
                ViewBag.Message = "Role created successfully !";
                return RedirectToAction("Index");
            
            catch
            
                return View();
            
        


        public ActionResult Delete(string RoleName)
        
            var context = new ApplicationDbContext();
            var thisRole = context.Roles.Where(r => r.RoleName.Equals(RoleName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
            context.Roles.Remove(thisRole);
            context.SaveChanges();
            return RedirectToAction("Index");
        


        //
        // GET: /Roles/Edit/5
        public ActionResult Edit(string roleName)
        
            var context = new ApplicationDbContext();
            var thisRole = context.Roles.Where(r => r.RoleName.Equals(roleName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();

            return View(thisRole);
        


        //
        // POST: /Roles/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Role role)
        
            try
            
                var context = new ApplicationDbContext();
                context.Entry(role).State = System.Data.Entity.EntityState.Modified;
                context.SaveChanges();

                return RedirectToAction("Index");
            
            catch
            
                return View();
            
        

        //  Adding Roles to a user
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult RoleAddToUser(string UserName, string RoleName)
        
            var context = new ApplicationDbContext();

            if (context == null)
            
                throw new ArgumentNullException("context", "Context must not be null.");
            

            Employee user = context.Employees.Where(u => u.FullName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
            Role role = context.Roles.Where(u => u.RoleName.Equals(RoleName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();

            AssignUserRole assignUserRole = new AssignUserRole
            
                EmployeeId = user.EmployeeID,
                RoleId = role.RoleID
            ;

            var EmpRoleToAdd = (from emprole in context.AssignUserRoles

                                where emprole.EmployeeId == user.EmployeeID && emprole.RoleId == role.RoleID

                                select emprole).FirstOrDefault();
            if (EmpRoleToAdd == null)
            
                context.AssignUserRoles.Add(assignUserRole);
                context.SaveChanges();
                ViewBag.Message = "Role created successfully !";
            
            else
            
                ViewBag.Message = " This Role already exists for this user !";
            

            // Repopulate Dropdown Lists
            var rolelist = context.Roles.OrderBy(r => r.RoleName).ToList().Select(rr => new SelectListItem  Value = rr.RoleName.ToString(), Text = rr.RoleName ).ToList();
            ViewBag.Roles = rolelist;
            var userlist = context.Employees.OrderBy(u => u.FullName).ToList().Select(uu =>
            new SelectListItem  Value = uu.FullName.ToString(), Text = uu.FullName ).ToList();
            ViewBag.Users = userlist;

            return View("Index");
        


        //Getting a List of Roles for a User
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult GetRoles(string UserName)
        
            if (!string.IsNullOrWhiteSpace(UserName))
            
                var context = new ApplicationDbContext();
                Employee user = context.Employees.Where(u => u.FullName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();

                var roles = user.AssignUserRoles.Select(u => u.Role).Select(u => u.RoleName).ToArray();

                ViewBag.RolesForThisUser = roles;


                // Repopulate Dropdown Lists
                var rolelist = context.Roles.OrderBy(r => r.RoleName).ToList().Select(rr => new SelectListItem  Value = rr.RoleName.ToString(), Text = rr.RoleName ).ToList();
                ViewBag.Roles = rolelist;
                var userlist = context.Employees.OrderBy(u => u.FullName).ToList().Select(uu =>
                new SelectListItem  Value = uu.FullName.ToString(), Text = uu.FullName ).ToList();
                ViewBag.Users = userlist;
                ViewBag.Message = "Roles retrieved successfully !";
            

            return View("Index");
        


        //Deleting a User from A Role
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteRoleForUser(string UserName, string RoleName)
        
            var context = new ApplicationDbContext();
            Employee user = context.Employees.Where(u => u.FullName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
            Role role = context.Roles.Where(u => u.RoleName.Equals(RoleName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();

            var EmpRoleToDelete = (from emprole in context.AssignUserRoles

                                   where emprole.EmployeeId == user.EmployeeID && emprole.RoleId == role.RoleID

                                   select emprole).FirstOrDefault();

            if (EmpRoleToDelete != null)
            
                context.AssignUserRoles.Remove(EmpRoleToDelete);
                context.SaveChanges();
                ViewBag.Message = "Role removed from this user successfully !";
            
            else
            
                ViewBag.Message = "This user doesn't belong to selected role.";
            

            // Repopulate Dropdown Lists
            var rolelist = context.Roles.OrderBy(r => r.RoleName).ToList().Select(rr => new SelectListItem  Value = rr.RoleName.ToString(), Text = rr.RoleName ).ToList();
            ViewBag.Roles = rolelist;
            var userlist = context.Employees.OrderBy(u => u.FullName).ToList().Select(uu =>
            new SelectListItem  Value = uu.FullName.ToString(), Text = uu.FullName ).ToList();
            ViewBag.Users = userlist;

            return View("Index");
        


    

为角色控制器创建索引视图

@

                ViewBag.Title = "Index";
                Layout = "~/Views/Shared/_mainView.cshtml";

<div class="row col-sm-12 col-lg-12 col-md-12">
    <h1 style="text-align:center">Role Manager</h1>
    <br />
</div>

<div class="row col-sm-12 col-lg-12 col-md-12">


    <div class="col-sm-6 col-lg-6 col-md-6">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h4>Role List</h4>
            </div>
            <div class="panel-body">
                <table class="table table-striped table-hover col-sm-6 col-lg-6 col-md-6 ">
                    @foreach (var role in ViewBag.Roles)
                    
                        <tr>
                            <td class="col-sm-1 col-lg-5 col-md-5">
                                <strong>@role.Text </strong>
                            </td>
                            <td class="col-sm-1 col-lg-1 col-md-1">
                                <span onclick="return confirm('Are you sure to delete?')"><a href="/Roles/Delete?RoleName=@role.Text" class="delLink" style="color:red;">Delete</a></span> |
                                @Html.ActionLink("Edit", "Edit", new  roleName = @role.Text )
                            </td>
                        </tr>
                    
                </table>
            </div> <!-- End Panel Body-->
        </div> <!-- End Panel -->

        <div class="panel panel-primary">
            <div class="panel-heading">
                <h4>Create A New Role</h4>
            </div>
            <div class="panel-body">
                @using (Html.BeginForm("Create", "Roles", new  @class = "form-horizontal" ))
                
                    @Html.AntiForgeryToken()
                    @Html.ValidationSummary(true)

                    <div>
                        Role name: @Html.TextBox("RoleName")
                        <input type="submit" value="Save" class="btn-primary" />
                    </div>
                

            </div> <!--End Panel Body-->
        </div> <!--End Panel-->
    </div> <!--End First Column-->

    <div class="col-sm-6 col-lg-6 col-md-6">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h4>Add a Role to a User</h4>
            </div>
            <div class="panel-body">
                @using (Html.BeginForm("RoleAddToUser", "Roles"))
                
                    @Html.AntiForgeryToken()
                    @Html.ValidationSummary(true)

                    <p>User Name: @Html.DropDownList("UserName", (IEnumerable<SelectListItem>)ViewBag.Users, "Select ...")</p>
                    <p>Role Name: @Html.DropDownList("RoleName", (IEnumerable<SelectListItem>)ViewBag.Roles, "Select ...")</p>
                    <p><input type="submit" value="Save" class="btn-primary" /></p>

                
            </div> <!-- End Panel Body-->
        </div> <!-- End Panel -->


        <div class="panel panel-primary">
            <div class="panel-heading">
                <h4>List Roles for a User</h4>
            </div>
            <div class="panel-body">
                @using (Html.BeginForm("GetRoles", "Roles"))
                
                    @Html.AntiForgeryToken()
                    <p>
                        User Name: @Html.DropDownList("UserName", (IEnumerable<SelectListItem>)ViewBag.Users, "Select ...")
                        <input type="submit" value="Get Roles for this User" class="btn-primary" />
                    </p>
                

                @if (ViewBag.RolesForThisUser != null)
                
                    <div class="alert-info">
                        <strong>Roles for this user </strong>
                        <ol>
                            @foreach (string s in ViewBag.RolesForThisUser)
                            
                                <li>@s</li>
                            
                        </ol>
                    </div>
                
            </div> <!-- End Panel Body-->
        </div> <!-- End Panel -->

        <div class="panel panel-primary">
            <div class="panel-heading">
                <h4>Remove Role from User</h4>
            </div>
            <div class="panel-body">
                @using (Html.BeginForm("DeleteRoleForUser", "Roles"))
                
                    @Html.AntiForgeryToken()
                    @Html.ValidationSummary(true)

                    <p>User Name: @Html.DropDownList("UserName", (IEnumerable<SelectListItem>)ViewBag.Users, "Select ...")</p>
                    <p>Role Name: @Html.DropDownList("RoleName", (IEnumerable<SelectListItem>)ViewBag.Roles, "Select ...")</p>
                    <p><input type="submit" value="Delete this user from Role" class="btn-primary" /></p>

                
            </div> <!-- End Panel Body-->
        </div> <!-- End Panel -->

    </div> <!--End Second Column-->

</div>  <!--Overall Page Wrapper-->

<div class="alert-info col-sm-12 col-lg-12 col-md-12">
    @ViewBag.Message
</div>


---------------------------------------------------------------------

为角色控制器创建编辑视图

@model yournamespace.Role
@
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_mainView.cshtml";


<h2>Edit Role</h2>

@Html.ActionLink("Return to Role Manager", "Index")
<hr />
@using (Html.BeginForm())

    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    @Html.HiddenFor(model => model.RoleID)
    <div>
        Role name
    </div>
    <p>
        @Html.TextBoxFor(model => model.RoleName)
    </p>
    <input type="submit" value="Save" />


创建角色并分配给用户

创建类 CustomRoleProvider

从RoleProvider类继承CustomRoleProvider如下图并实现抽象类。对类进行如下修改

using System;
using System.Linq;
using System.Web.Security;


namespace yournamespace.Models

    public class CustomRoleProvider : RoleProvider
    
        public override string ApplicationName  get => throw new NotImplementedException(); set => throw new NotImplementedException(); 

        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        
            throw new NotImplementedException();
        

        public override void CreateRole(string roleName)
        
            throw new NotImplementedException();
        

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        
            throw new NotImplementedException();
        

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        
            throw new NotImplementedException();
        

        public override string[] GetAllRoles()
        
            using (var usersContext = new SNHeliosWork2017Entities())
            
                return usersContext.Roles.Select(r => r.RoleName).ToArray();
            
        

        public override string[] GetRolesForUser(string username)
        
            using (var usersContext = new SNHeliosWork2017Entities())
            

                var user = usersContext.Employees.SingleOrDefault(u => u.FullName == username);
                if (user == null)
                    return new string[]  ;
                return user.AssignUserRoles == null ? new string[]   :
                  user.AssignUserRoles.Select(u => u.Role).Select(u => u.RoleName).ToArray();
            
        

        public override string[] GetUsersInRole(string roleName)
        
            throw new NotImplementedException();
        

        public override bool IsUserInRole(string username, string roleName)
        
            using (var usersContext = new SNHeliosWork2017Entities())
            
                var user = usersContext.Employees.SingleOrDefault(u => u.FullName == username);
                if (user == null)
                    return false;
                return user.AssignUserRoles != null && user.AssignUserRoles.Select(
                     u => u.Role).Any(r => r.RoleName == roleName);
            
        

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        
            throw new NotImplementedException();
        

        public override bool RoleExists(string roleName)
        
            throw new NotImplementedException();
        
    

在 web.config 中在 system.web 标签中添加以下代码

<system.web>       
     <sessionState mode="InProc" timeout="20" cookieless="false"></sessionState>
    <authentication mode="Forms">
      <forms loginUrl="~/Home/LogIn" defaultUrl="~/" timeout="20" slidingExpiration="true"/>
    </authentication>
    <roleManager enabled="true" defaultProvider="CustomRoleProvider">
      <providers>
        <clear/>
        <add name="CustomRoleProvider"  type="MyProject.Models.CustomRoleProvider" />
      </providers>
    </roleManager>
  </system.web>

首先要注意的是,我已将 enabled 属性设置为 true,以便框架启用角色管理器。然后您必须指定 defaultProvider 属性,如果指定了多个提供程序,则该属性用于标识默认提供程序。但是在这种情况下,我将只有一个提供者 CustomRoleProvider,仍然必须指定默认提供者。这包含在 providers 元素中。 clear 元素用于清除之前为此应用程序存储的所有提供程序,例如默认提供程序。然后,我通过指定名称“CustomRoleProvider”来定义自定义角色提供程序,该名称在 defaultProvider 属性中使用。这包含许多属性。最重要的是 type 属性,其中指定了自定义角色提供程序的完全限定名称 (MyProject.Models.CustomRoleProvider),然后是包含此类型的程序集 (MyProject) 和版本。请注意,如果类型包含在同一个程序集(Web 应用程序本身)中,则只有类型名称是必需的,其他名称是可选的。其他属性是不言自明的,我不会让你厌烦所有这些细节!

使用 authorize 属性来授权控制器 作为,

[Authorize(Roles = "Admin")]
public class RolesController : Controller


【讨论】:

以上是关于ASP.NET MVC 5 中的简单角色管理器和授权,无需使用 Identity(CustomRoleProvider)的主要内容,如果未能解决你的问题,请参考以下文章

asp.net core 5 mvc 超级管理员连接

如何在asp.net mvc 5身份中的授权属性中使用动态角色

将控制器操作权限动态分配给 asp.net MVC 中的角色

ASP.NET MVC:窗体身份验证及角色权限管理示例

ASP.NET MVC 中的非字符串角色名称?

ASP.NET MVC 异常“角色管理器功能尚未启用”