ASP.NET Core 2.0 基于用户角色的动态菜单管理(使用依赖注入)






4.95/5 (11投票s)
在本篇文章中,我们将详细介绍用户登录后如何显示基于角色的动态菜单。为此,我们将创建一个 `Menu Master` 表并插入一些记录,以便根据登录用户的角色来显示菜单和链接 URL。
引言
在开始阅读本文之前,请先阅读我之前的文章
在之前的文章中,我们详细讨论了如何在 MVC 应用程序中使用 ASP.NET Core Identity 来创建用户角色并根据用户角色显示菜单。
在本篇文章中,我们将详细介绍用户登录后如何显示基于角色的动态菜单。为此,我们将创建一个 `Menu Master` 表并插入一些记录,以便根据登录用户的角色来显示菜单和链接 URL。
在这里,我们将看到如何
- 创建默认的管理员和经理用户
- 创建 `MenuMaster` 表并插入一些 `Admin` 和 `Manager` 角色的示例记录以显示菜单
- 将未经验证的用户重定向到登录页面
- 根据登录用户动态显示菜单
背景
必备组件
请确保您已在计算机上安装了所有先决条件。如果没有,请一个接一个地下载并安装它们。
- 首先,从此 链接 下载并安装 Visual Studio 2017
- SQL Server 2014 或更高版本
Using the Code
步骤 1 - 创建数据库
这与我们之前的文章是相关的;正如我们之前提到的,我们将使用一个通用数据库来存放 ASP.NET `Identity` 表和我们自己的新表。
在我们之前的文章中,我们已经解释了如何创建用户角色,而在这里,对于基于角色的菜单管理,我们需要在 ASP.NET `Roles` 表和我们的 `menu` 表之间建立一个关系表。
让我们详细了解如何创建我们的新 `Menu` 表,该表与 ASP.NET Identity 的 `AspNetRoles` 表有关系。
在这里,我们可以看到 `MenuMaster` 使用的字段
首先,我们将创建一个数据库,并在 `appsettings.json` 文件中为 `DefaultConnection` 设置连接字符串,指向我们的新数据库连接。我们将使用此数据库来创建 ASP.NET Core Identity 表。
创建数据库
运行以下脚本来创建我们的数据库 `MenuMaster` 表和示例 `Menu` 插入行脚本。
USE MASTER
GO
-- 1) Check for the Database Exists. If the database exists, then drop and create new DB
IF EXISTS (SELECT [name] FROM sys.databases WHERE [name] = 'AttendanceDB' )
DROP DATABASE AttendanceDB
GO
CREATE DATABASE AttendanceDB
GO
USE AttendanceDB
GO
IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'MenuMaster' )
DROP TABLE MenuMaster
GO
CREATE TABLE MenuMaster
(
MenuIdentity int identity(1,1),
MenuID VARCHAR(30) NOT NULL,
MenuName VARCHAR(30) NOT NULL,
Parent_MenuID VARCHAR(30) NOT NULL,
User_Roll [varchar](256) NOT NULL,
MenuFileName VARCHAR(100) NOT NULL,
MenuURL VARCHAR(500) NOT NULL,
USE_YN Char(1) DEFAULT 'Y',
CreatedDate datetime
CONSTRAINT [PK_MenuMaster] PRIMARY KEY CLUSTERED
(
[MenuIdentity] ASC ,
[MenuID] ASC,
[MenuName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, _
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
select * from MenuMaster
-- Insert Admin User Details
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('AUSER','ADMIN Dashboard','*','ADMIN','INDEX','ADMINC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('AAbout','About Admin','*','ADMIN','INDEX','ADMINAC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('LStock','Live Stock','AUSER','ADMIN','INDEX','StockC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('Profile','User Details','AUSER','ADMIN','INDEX','MemberC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('MUSER','Manager Dashboard','*','ADMIN','INDEX','ManagerC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('MAbout','About Manager','*','ADMIN','INDEX','ManagerAC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('Accounts','Account Details','MUSER','ADMIN','INDEX','AccountC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,_
MenuURL,USE_YN,CreatedDate)
Values('Inventory','Inventory Details','MUSER','ADMIN','INDEX','InventoryC','Y',getDate())
-- Insert Manager User Details
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('MUSER','Manager Dashboard','*','Manager','INDEX','ManagerC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('MAbout','About Manager','*','Manager','INDEX','ManagerAC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('Accounts','Account Details','MUSER','Manager','INDEX','AccountC','Y',getDate())
Insert into MenuMaster(MenuID ,MenuName,Parent_MenuID,User_Roll,MenuFileName,MenuURL,USE_YN,CreatedDate)
Values('Inventory','Inventory Details','MUSER','Manager','INDEX','InventoryC','Y',getDate())
select * from MenuMaster
select * from AspnetUserRoles
在这里,我们可以看到我们在 `Menu Master` 表中用于根据用户角色显示菜单的记录的格式。
- `MenuID = 'AUSER'` (我们将给出唯一的菜单 ID)。
- `MenuName = 'ADMIN Dashboard'` (我们将给出菜单显示文本),
- `Parent_MenuID = '*'` (如果这是主菜单,那么我们将在这里给出“`*`”,否则我们将给出前一条记录的 `MenuID` 以显示此记录作为子菜单)。
- `User_Roll = 'ADMIN'` (在这里,我们将给出用户角色,如果同一菜单需要用于多个角色的用户,例如 `Admin`、`Manager`、`Accountant` 等,那么我们将插入相同的菜单详细信息,但具有不同的用户角色。在我们的示例中,我们为 `Admin` 和 `Manager` 用户添加了相同的菜单详细信息,因为两者都可以查看菜单和页面)。
- `MenuFileName = 'INDEX'` (在这里,我们给出点击菜单时要显示的 `View` 名称)。
- `MenuURL = 'ADMINC'` (在这里,我们给出点击菜单时要显示的 `Controller` 名称)。
- `USE_YN = 'Y'` (这是一个可选字段,因为我们可以使用它来显示菜单或不显示)。
- `CreatedDate = getDate()` (这也可选,用于输入创建日期)。
在此演示应用程序中,我们已经拥有了用户点击菜单时要显示的所有必需的控制器和视图。
步骤 2 - 创建您的 ASP.NET Core
安装 Visual Studio 2017 后,点击开始,然后选择程序,再选择 Visual Studio 2017 - 点击 Visual Studio 2017。点击新建,然后点击项目,选择 Web,然后选择 ASP.NET Core Web Application。输入您的项目名称,然后点击。
选择 Web Application (Model-View-Controller) 并点击 Change Authentication。
选择 Individual User Accounts 并点击 OK 来创建您的项目。
更新 appsettings.json
在 `appsettings.json` 文件中,我们可以找到 `DefaultConnection` 连接字符串。在这里,在连接字符串中,更改您的 SQL Server 名称、UID 和 PWD 以便在一个数据库中创建和存储所有用户详细信息。
"ConnectionStrings": {
"DefaultConnection": "Server= YOURSERVERNAME;Database=InventoryDB;
user id= YOURSQLUSERID;password=YOURSQLPASSWORD;Trusted_Connection=True;
MultipleActiveResultSets=true"
},
步骤 3 - 在 Startup.cs 文件中添加 Identity 服务
默认情况下,在您的 ASP.NET Core 应用程序中,Identity 服务将添加在 `Startup.cs` 文件的 `ConfigureServices` 方法中。您还可以通过使用以下代码,额外添加用户注册时的密码强度,并设置默认登录/登出页面以及 `AccessDeniedPath`。
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
//Password Strength Setting
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 6;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.AllowedForNewUsers = true;
// User settings
options.User.RequireUniqueEmail = true;
});
//Setting the Account Login page
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
options.LoginPath = "/Account/Login"; // If the LoginPath is not set here,
// ASP.NET Core will default to /Account/Login
options.LogoutPath = "/Account/Logout"; // If the LogoutPath is not set here,
// ASP.NET Core will default to /Account/Logout
options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath
// is not set here, ASP.NET Core will default to /Account/AccessDenied
options.SlidingExpiration = true;
});
步骤 4:注册和创建用户
现在,我们的 ASP.NET Core Web 应用程序已准备就绪,用户可以注册我们的网站,用户也可以在注册后登录我们的系统。我们将在下一步通过为用户添加角色来进行授权。构建并运行您的应用程序以注册您的第一个默认管理员用户。
在这里,我们将注册两个用户,一个作为 `Admin`,另一个作为 `Manager`。我们将使用这些用户来添加角色。我们将创建两个用户:syedshanumcain@gmail.com 和 afraz@gmail.com。**注意**:您可以根据需要创建用户,并在启动代码中更改用户详细信息以添加角色。
刷新数据库
当我们刷新数据库时,我们可以看到所有 `Identity` 表都已创建。
步骤 5:创建角色并分配用户给角色
我们使用以下方法创建一个名为“`Admin`”和“`Manager`”的新角色。我们将为我们的网站分配最近注册的用户为“`Admin`”和“`Manager`”。打开 `Startup.cs` 文件并将此方法添加到您的 `Startup.cs` 文件中。
private async Task CreateUserRoles(IServiceProvider serviceProvider)
{
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
IdentityResult roleResult;
//Adding Addmin Role
var roleCheck = await RoleManager.RoleExistsAsync("Admin");
if (!roleCheck)
{
//create the roles and seed them to the database
roleResult = await RoleManager.CreateAsync(new IdentityRole("Admin"));
}
roleCheck = await RoleManager.RoleExistsAsync("Manager");
if (!roleCheck)
{
//create the roles and seed them to the database
roleResult = await RoleManager.CreateAsync(new IdentityRole("Manager"));
}
//Assign Admin role to the main User here we have given our
//newly loregistered login id for Admin management
ApplicationUser user = await UserManager.FindByEmailAsync("syedshanumcain@gmail.com");
var User = new ApplicationUser();
await UserManager.AddToRoleAsync(user, "Admin");
user = await UserManager.FindByEmailAsync("Afraz@gmail.com");
await UserManager.AddToRoleAsync(user, "Manager");
}
在 `Startup.cs` 文件中,我们可以找到 `Configure` 方法。从 `Configure` 方法中调用我们的 `CreateUserRoles` 方法。当我们构建并运行我们的应用程序时,我们可以在 `ASPNetRole` 表中看到新创建的“`Admin`”和“`Manager`”角色。
步骤 6:创建管理员/经理页面并设置授权
现在我们已经为我们的 ASP.NET Core Web 应用程序拥有了管理员/经理用户,下一步,让我们创建控制器和视图来根据用户登录进行显示。在我们之前的示例中,我们已经看到了如何在每个页面上为角色设置授权,利用这一点,我们将创建所有必需的控制器和视图。在随附的示例演示应用程序中,您可以找到我们创建的所有控制器和视图,并根据您的需要创建您自己的。
步骤 7:使用依赖注入来显示菜单
创建模型类
首先,我们将创建一个类放在我们的 `Model` 文件夹中。我们将类名命名为 `MenuMaster`,与我们数据库中的表名相同。在 `MenuMaster` 类中,我们需要创建与我们 `Table` 字段相同的属性,如下所示。
public class MenuMaster
{
[Key]
public int MenuIdentity { get; set; }
public string MenuID { get; set; }
public string MenuName { get; set; }
public string Parent_MenuID { get; set; }
public string User_Roll { get; set; }
public string MenuFileName { get; set; }
public string MenuURL { get; set; }
public string USE_YN { get; set; }
public DateTime CreatedDate { get; set; }
}
创建接口类
现在,是时候创建一个 `interface` 了,其中包含名为 `GetMenuMaster()`、`GetMenuMaster(String UserRole)` 的方法,我们将在我们的 `Service` 中实现这个 `interface` 来从表中获取所有 `Menu` 详细信息,以及另一个根据用户角色获取菜单的方法。要创建 `Interface`,请向您的 `model` 文件夹添加一个新类,并将类命名为“`IMenuMasterService`”。
我们将类更改为 `interface`,因为我们将创建一个 `interface` 来在我们的服务中实现。
public interface IMenuMasterService
{
IEnumerable<MenuMaster> GetMenuMaster();
IEnumerable<MenuMaster> GetMenuMaster(String UserRole);
}
创建服务
现在,让我们在 `Services` 文件夹中添加一个新类,并将类命名为“`MenuMasterService`”。在这个类中,我们将实现我们的 `interface IMenuMasterService`。我们知道,如果实现 `interface`,那么我们必须在我们的类中声明 `interface` 方法。在这个服务中,我们使用 `interface` 方法,并返回带有 `Menu` 详细信息的列表,以及根据用户角色返回 `Menu` 详细信息。我们将直接将此注入到我们的 View 页面。
public class MenuMasterService:IMenuMasterService
{
private readonly ApplicationDbContext _dbContext;
public MenuMasterService(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public IEnumerable<MenuMaster> GetMenuMaster()
{
return _dbContext.MenuMaster.AsEnumerable();
}
public IEnumerable<MenuMaster> GetMenuMaster(string UserRole)
{
var result = _dbContext.MenuMaster.Where(m => m.User_Roll == UserRole).ToList();
return result;
}
}
注册服务
我们需要将我们创建的服务注册到容器中。打开项目中的 `Startup.cs` 文件,将服务添加到容器中。
在 `Startup.cs` 类中,找到名为 `ConfigureServices` 的方法,像下面一样添加您的服务“`MenuMasterService`”。
services.AddTransient<MenuMasterService, MenuMasterService>();
在 _Layout.cshtml 页面中注入服务
现在,这要简单容易得多,因为我们可以直接在我们的 View 页面中注入服务,并将所有结果绑定到我们的 View 页面。要在我们的 View 中注入服务,我们将使用现有的 `_Layout.cshtml` 页面。由于我们将在网站顶部显示菜单并在所有页面中使用它,因此我们在此使用了 `_Layout.cshtml` 页面来绑定菜单结果,以便菜单根据登录用户而定。
在这里,我们首先检查用户是否已向我们的网站进行身份验证,然后如果用户已登录,则获取登录用户的角色详细信息,并根据用户角色绑定菜单。在这里,我们绑定了 2 级菜单:主菜单和子菜单。在我们的表结果中,我们检查所有 `Parent_MenuID=” *”`,因为我们将使用 `parent_MenuID` 为“`*`”来显示主菜单,然后在下一个内部循环中,我们显示适合主菜单的子菜单。
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
@if (User.Identity.IsAuthenticated)
{
var UserRoles = "";
if (@User.IsInRole("Admin"))
{
UserRoles = "Admin";
}
else
{
UserRoles = "Manager";
}
@if (menus.GetMenuMaster(@UserRoles).Any())
{
@if (menus.GetMenuMaster(@UserRoles).Any())
{
@foreach (var menuNames in menus.GetMenuMaster(@UserRoles).Where
(n => n.Parent_MenuID == "*"))
{
<li>
<a asp-area="" asp-controller=@menuNames.MenuURL
asp-action=@menuNames.MenuFileName>@menuNames.MenuName</a>
<ul class="sub-menu">
@foreach (var subMenu in menus.GetMenuMaster(@UserRoles).Where
(n => n.Parent_MenuID == @menuNames.MenuID))
{
<li>
<a asp-area="" asp-controller=@subMenu.MenuURL
asp-action=@subMenu.MenuFileName>@subMenu.MenuName</a>
</li>
}
</ul>
</li>
}
}
}
}
</ul>
关注点
首先,在您的 SQL Server 中创建一个名为 `AttendanceDB` 的示例数据库,并运行脚本来创建 `MenuMaster` 表并插入示例记录。在 `appsettings.json` 文件中,更改 `DefaultConnection` 连接字符串以匹配您的 SQL Server 连接。在 `Startup.cs` 文件中,添加本文中讨论的所有代码。这是一个简单的演示应用程序,我们已将其固定为 `Admin` 和 `Manager` 角色,您可以根据您的需求进行更改,并且菜单和子菜单的 CSS 设计不适用于移动设备,您可以添加自己的 bootstrap 设计来实现您的菜单样式。希望大家喜欢这篇文章,很快我们将看到另一篇带有更多实际示例的文章。
历史
ASPNETCORERoleManagement
- 2018-04-03