Abp-VNext是基於aspnetboilerplate的先行版本,在我看來,具有下面三個特點:
1,一個全面的技術框架:基本上囊括了.Net 技術棧上各種流行的技術應用,並且在集成度上也做得很好。
2,基於領域驅動的分層設計模型:提供了DDD分層設計的最佳實踐,明確了各層的工作職責
3,模塊化的開發模式
參考:aspnetboilerplate,ABP-VNext
Abp-VNext的特點決定了他在.Net 微服上能大展拳腳,下面從微服務的身份認證及授權開始,看看Abp-Vnext能幫我們做些什么。
一,基於Abp-Vnext的微服務架構目錄
參考Abp-Vnext的微服務Demo,先把工作目錄建立起來
先建立一個服務,用於用戶身份認證及授權管理
1,建立解決方案:dotnet new sln --name Kingsun.Liujb
2,建立用於用戶身份認證及授權管理的模塊:
切換目錄到modules,執行Abp命令:abp new Kingsun.Liujb.IDServer --ui-none -t module -csf。創建一個沒有ui的模塊。
3,創建模塊后認識一下Abp-vnext的DDD分層架構
4,按需將模塊添加到根解決方案
二,IdentityServer宿主配置
切換到microsoftservices目錄,
將Modules目錄中的宿主示例中的IdentityServer直接拷過來。切換到shared目錄,新建一個類庫:Kingusn.Liujb.Shared
將Kingsun.Liujb.Shared添加到Kingsun.Liujb.IDServer.IdentityServer項目引用,替換原來的shared項目。
MultiTenancyConsts.cs
public class MultiTenancyConsts { public const bool IsEnabled = true; }
更改數據庫鏈接地址為實際地址:Kingsun.Liujb.IDServer.IdentityServer項目的appsettings.json。
由於目前沒有使用reids緩存,先行在IDServerIdentityServerModule中將redis相關模塊注釋掉。
使用”update-database“命令更新數據到數據庫,運行IdentityServer項目后使用默認的用戶名:admin。密碼:1q2w3E* 登錄
三,添加用戶身份管理、租戶管理模塊
前面我們見識到了使用ABP-Vnext創建項目的實用性,下面將用使用ABP-VNext的模塊化特性快速添加部份管理模塊
先添加身份認證相關的管理模塊,安裝Nuget包:Volo.Abp.Identity.Web 后在IDServerIdentityServerModule.cs中添加依賴:typeof(Volo.Abp.Identity.Web.AbpIdentityWebModule)。
運行程序:
同樣添加租戶管理:Volo.Abp.TenantManagement.Web.AbpTenantManagementWebModule
四,添加日志查看模塊
查看Abp-vnex的日志管理模塊,可以看出社區版本只提供了領域層及基礎設施層,沒有應用服務層和表示層,也就意味着沒有包含日志管理相關接口及頁面:
1,新增查詢日志服務
1),先建立服務約束,包括接口,數據傳輸對象。我這里建立了一個名為IAuditServices的接口,約束服務的使用。AuditDto以及GetAuditlogInput這兩個類用於服務數據的傳輸。
聲明如下:
public interface IAuditServices : IApplicationService { System.Threading.Tasks.Task<PagedResultDto<AuditDto>> GetAuditsByUsernameAsync(GetAuditlogInput input); System.Threading.Tasks.Task<PagedResultDto<AuditDto>> GetListAsync(); } public class AuditDto: EntityDto<Guid> { public string ApplicationName { get; set; } public string UserId { get; set; } public string UserName { get; set; } public string TenantName { get; set; } public DateTime ExecutionTime { get; set; } public int ExecutionDuration { get; set; } public string ClientIpAddress { get; set; } public string ClientName { get; set; } public string BrowserInfo { get; set; } public string HttpMethod { get; set; } public string Url { get; set; } public string Exceptions { get; set; } public int HttpStatusCode { get; set; } } public class GetAuditlogInput: PagedAndSortedResultRequestDto { public string Filter { get; set; } }
2),實現服務
在Kingsun.Liujb.IDServer.Application包中實現具體的服務
[Authorize(IDServerPermissions.Audits.AuditMannage)]
public class AuditServices : IDServerAppService, IAuditServices { private readonly IAuditLogRepository _auditLogRepository; public AuditServices(IAuditLogRepository auditLogRepository) { this._auditLogRepository = auditLogRepository; } public async System.Threading.Tasks.Task<PagedResultDto<AuditDto>> GetAuditsByUsernameAsync(GetAuditlogInput input) { long count = await _auditLogRepository.GetCountAsync(userName: input.Filter); var list = await _auditLogRepository.GetListAsync( skipCount: input.SkipCount, maxResultCount: input.MaxResultCount, userName: input.Filter, sorting: input.Sorting ); return new PagedResultDto<AuditDto>() { TotalCount = count, Items = ObjectMapper.Map<List<AuditLog>, List<AuditDto>>(list) }; } public async Task<PagedResultDto<AuditDto>> GetListAsync() { long count = await _auditLogRepository.GetCountAsync(); var list = await _auditLogRepository.GetListAsync(); return new PagedResultDto<AuditDto>() { TotalCount = count, Items = ObjectMapper.Map<List<AuditLog>, List<AuditDto>>(list) }; } }
暴露API
Kingsun.Liujb.IDServer.HttpApi
[RemoteService] [Route("api/IDServer/Audit")] [Authorize(IDServerPermissions.Audits.AuditMannage)] public class AuditController : IDServerController, IAuditServices { private readonly IAuditServices _iDServerAuditService; public AuditController(IAuditServices _iDServerAuditService) { this._iDServerAuditService = _iDServerAuditService; } [HttpGet] [Route("GetAuditsByUsername")] public async Task<PagedResultDto<AuditDto>> GetAuditsByUsernameAsync(GetAuditlogInput input) { return await _iDServerAuditService.GetAuditsByUsernameAsync(input); } [HttpGet] [Route("GetList")] public async Task<PagedResultDto<AuditDto>> GetListAsync() { return await _iDServerAuditService.GetListAsync(); } }
2,新增訪問權限
對服務訪問進行授權管理。
在Kingsun.Liujb.IDServer.Application.Contracts包的PermissionDefinitionProvider中新建權限,並設置本地化顯示名稱。
public class IDServerPermissionDefinitionProvider : PermissionDefinitionProvider { public override void Define(IPermissionDefinitionContext context) { var auditGroup = context.AddGroup(IDServerPermissions.GroupName, L("Permission:AuditManagement")); auditGroup.AddPermission(IDServerPermissions.Audits.AuditMannage, L("Permission:AuditManagement"), Volo.Abp.MultiTenancy.MultiTenancySides.Host); } private static LocalizableString L(string name) { return LocalizableString.Create<IDServerResource>(name); } } public class IDServerPermissions { public const string GroupName = "IDServer"; public static class Audits { public const string AuditMannage = GroupName + ".Audits"; } public static string[] GetAll() { return ReflectionHelper.GetPublicConstantsRecursively(typeof(IDServerPermissions)); } }
權限名稱本地化:Kingsun.Liujb.IDServer.Domain.Shared中的Localization目錄中修改本地化Json文件
"texts": { "ManageYourProfile": "管理個人資料", "SamplePageMessage": "IDServer模塊的示例頁面", "Menu:AuditManagement": "審核日志", "Audits": "日志", "Permission:AuditManagement": "審核日志" }
打開管理頁面,可以看到新增的權限已經可以被管理
3,新增菜單
Kingsun.Liujb.IDServer.Web的Menu目錄
public class IDServerMenuContributor : IMenuContributor { public async Task ConfigureMenuAsync(MenuConfigurationContext context) { if (context.Menu.Name == StandardMenus.Main) { await ConfigureMainMenu(context); } } private async Task ConfigureMainMenu(MenuConfigurationContext context) { //Add main menu items. var administrationMenu = context.Menu.GetAdministration(); var l = context.GetLocalizer<IDServerResource>(); var AuditlogsMenuItem = new ApplicationMenuItem(IDServerMenus.AuditManagementGroup, l["Menu:AuditManagement"], icon: "fa fa-file-text-o"); administrationMenu.AddItem(AuditlogsMenuItem); if (await context.IsGrantedAsync(IDServerPermissions.Audits.AuditMannage)) { AuditlogsMenuItem.AddItem(new ApplicationMenuItem(IDServerMenus.AuditManagementSelect, l["Audits"], url: "~/Audit")); } } } private const string Prefix = "IDServer"; public const string AuditManagementGroup = "AuditManagement"; public const string AuditManagementSelect = AuditManagementGroup + ".AuditLogs";
菜單名稱本地化參考權限名稱本地化,修改本地化json文件即可。
打開管理頁面,看到管理菜單已經添加了日志目錄
4,新增日志查看頁面
Index.cshtml
@page @using Microsoft.Extensions.Localization @using Kingsun.Liujb.IDServer.Localization @model Kingsun.Liujb.IDServer.Web.Pages.IDServer.IndexModel @inject IStringLocalizer<IDServerResource> L @section scripts{ <abp-script src="/Pages/Audit/Index.js" /> } <abp-card> <abp-card-header> <abp-row> <abp-column size-md="_6"> <abp-card-title>@L["Audits"]</abp-card-title> </abp-column> </abp-row> </abp-card-header> <abp-card-body> <abp-table striped-rows="true" id="AuditsTable"></abp-table> </abp-card-body> </abp-card>
Index.js
(function ($) { var l = abp.localization.getResource('IDServer'); var dataTable = $('#AuditsTable').DataTable( abp.libs.datatables.normalizeConfiguration({ serverSide: true, paging: true, searching: true, scrollX: true, order: [[1, "asc"]], ajax: abp.libs.datatables.createAjax(kingsun.liujb.iDServer.audits.audit.getAuditsByUsername), columnDefs: [ { title:l("UserName"), data:"userName" }, { title: l( "ExecutionTime"), data: "executionTime" }, { title: l("Url"), data: "url" }, { title: l("HttpMethod"), data: "httpMethod" }, { title: l("HttpStatusCode"), data: "httpStatusCode" } ] }) ) })(jQuery);
本地化:參考權限名稱本地化,修改本地化json文件即可
打開頁面
這只是一個比較簡單的管理功能,下一篇將使用模塊化的方式添加一個較為復雜的管理模塊:IdentityServer管理模塊。