使用ASP.NET MVC对用户组的自定义授权

635 篇文章 16 订阅
82 篇文章 3 订阅

目录

介绍

示例MVC应用程序进行演示

步骤1:在系统中创建新的用户角色

创建一个管理员组并映射用户

创建用户组并映射用户

步骤2:创建项目

步骤3:在Web.config中配置用户组

步骤4:添加枚举类

步骤5:添加登录视图模型

步骤6:添加授权过滤器

步骤7:添加授权助手类

步骤8:添加MVC控制器

LogInController.cs

AdminController.cs

UserController.cs

步骤9:添加MVC视图

LogIn.cshtml

Admin.cshtml

User.cshtml

步骤10:运行应用程序


介绍

本文介绍了使用ASP.NET MVC通过用户角色实现自定义授权的方法。它可以防止未经授权的用户访问不应被访问的页面。

示例MVC应用程序进行演示

在此演示应用程序中,我使用的是Visual Studio 2019。我将向您展示如何禁止用户访问不应访问的页面。我们正在使用Windows身份验证,并且仅被授权访问特定用户组(Admin/NormalUser)的用户才能访问相应页面。例如,属于Admin组的用户只能访问Admin页面,而属于Normal User组的用户只能访问NormalUser页面

步骤1:在系统中创建新的用户角色

创建一个管理员组并映射用户

启动计算机管理窗口。创建一个新的用户组Admin,并将Windows用户映射到创建的组,如下图所示:

创建用户组并映射用户

启动计算机管理窗口。创建一个新的用户组User,并将Windows用户映射到创建的组,如下图所示:

步骤2:创建项目

Visual Studio中,创建一个新的ASP.NET MVC Web应用程序(C#)项目,如下图所示:

步骤3:在Web.config中配置用户组

配置文件中配置新创建的组,如下所示:

<appSettings>
   <add key="AdminUserRoles" value="Admin" />
   <add key="UserRoles" value="NormalUser" />
 </appSettings>

步骤4:添加枚举类

在项目下添加Enum Enums.cs类,并添加enum常量UserRoles,如下所示:

namespace CustomAuthorizationWithMVC
{
    public static class Enums
    {
        public enum UserGroups
        {
            /// <summary>
            /// No roles assigned
            /// </summary>
            None = 0,

            /// <summary>
            /// Admin role.
            /// </summary>
            Admin = 1,

            /// <summary>
            /// User role.
            /// </summary>
            NormalUser = 2,

            /// <summary>
            /// Both Administrator and  Normal user roles.
            /// </summary>
            All = 3
        }
    }
}

步骤5:添加登录视图模型

以下视图模型类可帮助用户存储已登录用户的详细信息。

using static CustomAuthorizationWithMVC.Enums;

namespace CustomAuthorizationWithMVC.Models
{
    public class LogInViewModel
    {
        /// <summary>
        /// Gets or sets the LoggedInUser once Authenticated.
        /// </summary>
        public string LoggedInUser { get; set; }

        /// <summary>
        /// Gets or sets the Admin flag true/false.
        /// </summary>
        public bool IsAdmin { get; set; }

        /// <summary>
        /// Gets or sets the User Role Type.
        /// </summary>
        public UserGroups UserGroup { get; set; }
    }
}

步骤6:添加授权过滤器

在项目下添加类文件UserAuthorizeAttribute.cs,并将以下代码添加到类文件中。此类继承自AuthorizeAttribute,并重写了方法OnAuthorization,该方法使用web.Config配置的方法验证登录的组/角色。如果用户未注册到这两个组/角色中,则该用户将被重定向到登录页面,而无权访问所请求的页面。

namespace UI.UserAuthorize
{
    using System;
    using System.Configuration;
    using System.Diagnostics;
    using System.Web.Mvc;
    using System.Web.Routing;
    using static CustomAuthorizationWithMVC.Enums;
    using AuthorizeUser.Common;

    public sealed class UserAuthorizeAttribute : AuthorizeAttribute
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="UserAuthorizeAttribute" /> class.
        /// </summary>
        /// <param name="allowedGroupTypes">allowed group types</param>
        public UserAuthorizeAttribute(params UserGroups[] userRoleTypes)
        {
            this.AllowedUserRoleTypes = userRoleTypes;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the admin user roles from configuration file.
        /// </summary>
        private string AdminUserRoles { get; } = 
                ConfigurationManager.AppSettings["AdminUserRoles"];

        /// <summary>
        /// Gets the user roles from configuration file.
        /// </summary>
        private string UserRoles { get; } = ConfigurationManager.AppSettings["UserRoles"];

        /// <summary>
        /// Gets or sets the allowed role types retrieved from controller or action method.
        /// </summary>
        private UserGroups[] AllowedUserRoleTypes { get; set; }
    
        #endregion

        #region Public Methods

        /// <summary>
        /// Method to do the authorization for user.
        /// </summary>
        /// <param name="filterContext">authorization context.</param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext != null)
            {
                var user = filterContext.RequestContext.HttpContext.User;

                base.OnAuthorization(filterContext);
               
                If user does not have any access, redirect him to login page.
                if (!AuthorizeUser.IsAdmin(AllowedUserRoleTypes, AdminUserRoles, user) 
                    && !AuthorizeUser.IsUser(AllowedUserRoleTypes, UserRoles, user))
                {                    
                    filterContext.Result = new RedirectToRouteResult(new
                        RouteValueDictionary(new { controller = "LogIn", action = "LogIn" }));
                }               
            }
        }
        #endregion        
    }
}

步骤7:添加授权助手类

授权过滤器类UserAuthorizeAttribute” 使用此类方法检查登录的用户是否属于已配置的Admin组或NormalUser组。

namespace AuthorizeUser.Common
{
    using System.Linq;
    using System.Security.Principal;
    using System.Text.RegularExpressions;
    using static CustomAuthorizationWithMVC.Enums;

    /// <summary>
    /// Class to check user group
    /// </summary>
    public static class AuthorizeUser
    {
        /// <summary>
        /// Method to check whether user is admin user
        /// </summary>
        /// <param name="allowedAuditUserGroupTypes">allowed audit user group types</param>
        /// <param name="admUserGroups">admin user groups</param>
        /// <param name="user">user</param>
        /// <returns>true or false</returns>
        public static bool IsAdmin(UserGroups[] allowedAuditUserGroupTypes,
               string auditAdminUserGroups, IPrincipal user)
        {
            bool isAdmin = false;
            var adminUserGroups = 
                Regex.Replace(auditAdminUserGroups, @"\s", string.Empty).Split(',');

            //If allowed group is configured for Administrator.
            if (allowedAuditUserGroupTypes.Any
               (allowedGroupType => allowedGroupType == UserGroups.Admin))
            {
                isAdmin = adminUserGroups.Any(admGrp => user.IsInRole(admGrp));
            }
            return isAdmin;
        }

        /// <summary>
        ///  Method to check whether user is audit user
        /// </summary>
        /// <param name="allowedAuditUserGroupTypes">allowed audit user group types</param>
        /// <param name="admUserGroups">admin user groups</param>
        /// <param name="user">user</param>
        /// <returns>true or false</returns>
        public static bool IsUser(UserGroups[] allowedAuditUserGroupTypes, 
             string auditUserGroups, IPrincipal user)
        {
            bool isUser = false;
            var userGroups = Regex.Replace(auditUserGroups, @"\s", string.Empty).Split(',');
            If allowed group is configured for Normal user.
            if (allowedAuditUserGroupTypes.Any
               (allowedGroupType => allowedGroupType == UserGroups.NormalUser))
            {
                isUser = userGroups.Any(usrGrp => user.IsInRole(usrGrp));
            }
            return isUser;
        }
    }
}

步骤8:添加MVC控制器

在项目的Controllers文件夹下添加以下控制器类:

  • LogInController.cs
  • AdminController.cs
  • UserController.cs

LogInController.cs

以下控制器类可帮助用户导航至登录视图并根据用户角色启用/禁用登录按钮。管理员登录按钮功能用于导航到管理页面,而“NormalUser登录按钮用于将用户导航至“NormalUser”页面。

using CustomAuthorizationWithMVC.Models;
using System.Configuration;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using static CustomAuthorizationWithMVC.Enums;

namespace CustomAuthorizationWithMVC.Controllers
{
    public class LogInController : Controller
    {        
        /// <summary>
        /// Gets the admin user groups from config file.
        /// </summary>
        private string AdminUserRoles { get; } = 
                ConfigurationManager.AppSettings["AdminUserRoles"];

        /// <summary>
        /// Gets the user groups from config file.
        /// </summary>
        private string UserRoles { get; } = ConfigurationManager.AppSettings["UserRoles"];

        // GET: LogIn
        public ActionResult LogIn()
        {
            // Check the user is enrolled into any of the Admin user roles.
            bool isAdmin = Regex.Replace(this.AdminUserRoles, @"\s", string.Empty).Split(',')
                            .Any(admRole => User.IsInRole(admRole));

            // Check the user is enrolled into any of the normal user roles.
            bool isUser = Regex.Replace(this.UserRoles, @"\s", string.Empty).Split(',')
                            .Any(usrRole => User.IsInRole(usrRole));

            LogInViewModel logInViewModel = new LogInViewModel()
            {
                LoggedInUser = User.Identity.Name,                
                UserGroup = this.GetUserRole(isAdmin, isUser)
            };
            return View(logInViewModel);
        }

        public ActionResult AdminView()
        {
            return this.RedirectToAction("RenderAdminView", "Admin");           
        }

        public ActionResult UserView()
        {
            return this.RedirectToAction("RenderUserView", "User");
        }

        private bool IsUserInGroup(string groupName)
        {
            return User.IsInRole(groupName);
        }
        private UserGroups GetUserRole(bool isAdmin, bool isUser)
        {
            if (isAdmin && isUser)
            {
                return Enums.UserGroups.All;
            }

            if (isAdmin)
            {
                return Enums.UserGroups.Admin;
            }

            if (isUser)
            {
                return Enums.UserGroups.NormalUser;
            }

            return Enums.UserGroups.None;
        }
    }
}

AdminController.cs

以下控制器类可帮助用户导航到管理员页面(如果他/她已注册为管理员角色)。通过在AdminController类之前添加授权过滤器UserAuthorize装饰(如下面的代码中突出显示的粗体所示),将针对web.cofig配置的Admin角色验证登录用户。如果通过验证,它将执行RenderAdminView方法并导航到管理页面。否则,它将重定向到登录页面。

using System.Web.Mvc;
using UI.UserAuthorize;
using static CustomAuthorizationWithMVC.Enums;

namespace CustomAuthorizationWithMVC.Controllers
{
    [UserAuthorize(UserGroups.Admin)]
    public class AdminController : Controller
    {
        
       public ActionResult RenderAdminView()
       {
            return View("Admin");
       }
    }
}

UserController.cs

以下控制器类可帮助用户在已注册NormalUser角色的情况下导航至用户页面通过在UserController类(在下面的代码中以粗体突出显示)之前进行授权过滤器UserAuthorize装饰,将针对web.config配置的用户角色验证登录用户。如果通过验证,它将执行RenderUserView方法并导航到用户页面。否则,它将重定向到登录页面。

using System.Web.Mvc;
using UI.UserAuthorize;
using static CustomAuthorizationWithMVC.Enums;

namespace CustomAuthorizationWithMVC.Controllers
{
    [UserAuthorize(UserGroups.NormalUser)]
    public class UserController : Controller
    {
        public ActionResult RenderUserView()
        {
            return View("User");
        }
    }
}

步骤9:添加MVC视图

在项目的视图文件夹下添加以下视图:

  • LogIn.cshtml
  • Admin.cshtml
  • User.cshtml

LogIn.cshtml

在此视图中,我们收到了LogInViewModel作为模型,并根据enum常量验证了登录用户组。如果登录的用户组是Admin,则启用以管理员身份登录按钮;如果登录的用户组是NormalUser,则启用以普通用户身份登录按钮。

@model CustomAuthorizationWithMVC.Models.LogInViewModel
@{
    ViewBag.Title = "LogIn";
}

<h2>LogIn Page.</h2>
<div>
    @if (Model.UserGroup == Enums.UserGroups.Admin || Model.UserGroup == Enums.UserGroups.All)
    {
        <button id="btnAdministrator" 

        onclick="location.href = '@Url.Action("AdminView", "LogIn")'"

                class="btn btn-primary">Login as Administrator</button>
    }
    @if (Model.UserGroup == Enums.UserGroups.NormalUser || 
         Model.UserGroup == Enums.UserGroups.All)
    {
        <button id="btnAuditUser" 

        onclick="location.href = '@Url.Action("UserView", "LogIn")'" 

                class="btn btn-primary">Login as NormalUser</button>
    }
    @if (Model.UserGroup == Enums.UserGroups.None)
    {
        <button id="btnClose" onclick="window.close();" 

        class="btn btn-primary">Close</button>
    }
</div>

Admin.cshtml

该视图将消息显示为Admin Page。当管理员导航到该视图时:

@{
    ViewBag.Title = "Admin";
}

<h2>Admin Page.</h2>

User.cshtml

该视图将消息显示为User Page。当用户导航到该视图时:

@{
    ViewBag.Title = "Admin";
}

<h2>NormalUser Page.</h2>

步骤10:运行应用程序

我只注册了NormalUser组。因此,启动时,我只能在登录页面中查看以普通用户身份登录按钮,如下所示:

并能够通过单击登录按钮导航到普通用户页面 ”

作为普通组的用户,我仍然可以尝试通过在浏览器中键入URL来访问管理页面。在这种情况下,已通过授权过滤器验证了登录用户的身份,由于我是管理员页面的未授权用户,因此会将我重定向回到登录页面,如下所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值