Abp VNext微服务-从身份认证及授权开始(二)
接上篇:Abp VNext微服务-从身份认证及授权开始(一)
上篇新增了一个日志查看模块,这次新增一个用于管理IdentityServer的Client、Api resources、Identity resources、Claims等等
效果:

权限管理

一,切换到modules目录,新增IdentityServer管理模块
\Liujb-AbpVnext-MicServices\modules> abp new Kingsun.Liujb.IDManagement -t module -csf
按需引用:

二,添加声明(Claims)管理功能
1,添加声明管理服务相关接口及Dto

public class ClaimDto: EntityDto<Guid>
{
public string Name { get; set; }
public bool Required { get; set; }
public bool IsStatic { get; set; }
public string Description { get; set; }
public string ConcurrencyStamp { get; set; }
}
public class CreateClaimDto:CreateOrUpdateClaimBaseDto
{
[Required]
[MaxLength(64)]
public string Name { get; set; }
}
public class CreateOrUpdateClaimBaseDto: ExtensibleObject
{
public bool Required { get; set; }
public string Description { get; set; }
}
public class GetClaimsInput : PagedAndSortedResultRequestDto
{
public string Filter { get; set; }
}
public interface IClaimsService:ICrudAppService<ClaimDto,Guid,GetClaimsInput,CreateClaimDto,UpdateClaimDto>,IApplicationService
{
}
public class UpdateClaimDto:CreateOrUpdateClaimBaseDto
{
[Required]
public string ConcurrencyStamp { get; set; }
}
2,实现声明管理服务

[Authorize(Permissions.IDManagementPermissions.Claims.Defalut)]
public class ClaimsService : IDManagementAppService, IClaimsService
{
private readonly IdenityClaimTypeManager _idenityClaimTypeManager;
private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository;
public ClaimsService(IdenityClaimTypeManager idenityClaimTypeManager, IIdentityClaimTypeRepository identityClaimTypeRepository) {
this._idenityClaimTypeManager = idenityClaimTypeManager;
this._identityClaimTypeRepository = identityClaimTypeRepository;
}
[Authorize(Permissions.IDManagementPermissions.Claims.Create)]
public async Task<ClaimDto> CreateAsync(CreateClaimDto input)
{
var claim = new IdentityClaimType(
id: GuidGenerator.Create(),
name: input.Name,
isStatic:false,
description:input.Description
);
var reslut=await _idenityClaimTypeManager.CreateAsync(claim);
return ObjectMapper.Map<IdentityClaimType, ClaimDto>(reslut);
}
[Authorize(Permissions.IDManagementPermissions.Claims.Delete)]
public async Task DeleteAsync(Guid id)
{
var claim = await _identityClaimTypeRepository.GetAsync(id);
if (claim == null)
{
throw new BusinessException(code: ExceptionCodes.ClaimNotFound).WithData("0",id);
}
if (claim.IsStatic)
{
throw new BusinessException(code: ExceptionCodes.CanNotDeleteAStaticClaim);
}
await _identityClaimTypeRepository.DeleteAsync(claim);
}
public async Task<ClaimDto> GetAsync(Guid id)
{
var reslut =await _identityClaimTypeRepository.GetAsync(id);
if(reslut==null)
throw new BusinessException(code: ExceptionCodes.ClaimNotFound).WithData("0",id);
return ObjectMapper.Map<IdentityClaimType, ClaimDto>(reslut);
}
public async Task<PagedResultDto<ClaimDto>> GetListAsync(GetClaimsInput input)
{
long count =await _identityClaimTypeRepository.GetCountAsync();
var list =await _identityClaimTypeRepository.GetPagedListAsync(
skipCount: input.SkipCount,
maxResultCount: input.MaxResultCount,
sorting: input.Sorting
);
var retList= ObjectMapper.Map<List<IdentityClaimType>, List<ClaimDto>>(list);
return new PagedResultDto<ClaimDto>()
{
Items = retList,
TotalCount = count
};
}
[Authorize(Permissions.IDManagementPermissions.Claims.Update)]
public async Task<ClaimDto> UpdateAsync(Guid id, UpdateClaimDto input)
{
var exsit =await _identityClaimTypeRepository.GetAsync(id);
if(exsit==null)
throw new BusinessException(code: ExceptionCodes.ClaimNotFound).WithData("0", id);
exsit.ConcurrencyStamp = input.ConcurrencyStamp;
exsit.Description = input.Description;
exsit.Required = input.Required;
var reslut= await _idenityClaimTypeManager.UpdateAsync(exsit);
return ObjectMapper.Map<IdentityClaimType, ClaimDto>(reslut);
}
}
3,使用webapi暴露服务

[RemoteService]
[Route("api/IDManagement/Claims")]
public class ClaimsController : IDManagementController, IClaimsService
{
public IClaimsService ClaimService { get; set; }
public ClaimsController(IClaimsService _claimServices)
{
this.ClaimService = _claimServices;
}
[HttpPost]
public Task<ClaimDto> CreateAsync(CreateClaimDto input)
{
return ClaimService.CreateAsync(input);
}
[HttpDelete]
[Route("{id}")]
public Task DeleteAsync(Guid id)
{
return ClaimService.DeleteAsync(id);
}
[HttpGet]
[Route("{id}")]
public Task<ClaimDto> GetAsync(Guid id)
{
return ClaimService.GetAsync(id);
}
[HttpGet]
public Task<PagedResultDto<ClaimDto>> GetListAsync(GetClaimsInput input)
{
return ClaimService.GetListAsync(input);
}
[HttpPut]
[Route("{id}")]
public Task<ClaimDto> UpdateAsync(Guid id, UpdateClaimDto input)
{
return ClaimService.UpdateAsync(id,input);
}
}
查看swagger,验证相关接口

4,添加相关界面

4.1 Claims/Index
管理主页:Index.cshtml
@page
@using Microsoft.Extensions.Localization
@using Kingsun.Liujb.IDManagement.Localization
@using Kingsun.Liujb.IDManagement.Permissions
@using Microsoft.AspNetCore.Authorization
@inject IStringLocalizer<IDManagementResource> L
@inject IAuthorizationService Authorization
@model Kingsun.Liujb.IDManagement.Web.Pages.Claims.IndexModel
@section scripts{
<abp-script src="/Pages/Claims/Index.js" /> }
<abp-card id="ClaimsWrapper">
<abp-card-header>
<abp-row>
<abp-column size-md="_6">
<abp-card-title>@L["Cliams"]</abp-card-title>
</abp-column>
<abp-column size-md="_6" class="text-right">
@if (await Authorization.IsGrantedAsync(IDManagementPermissions.Clients.Create))
{
<abp-button button-type="Primary" name="CreateClaim" text="@L["NewClaim"].Value" icon="plus" />
}
</abp-column>
</abp-row>
</abp-card-header>
<abp-card-body>
<abp-table striped-rows="true" id="CliamsTable"></abp-table>
</abp-card-body>
</abp-card>
index.js
(function ($) { var l = abp.localization.getResource('IDManagement'); var _claimsServices = kingsun.liujb.iDManagement.claims.claims; var _permissionsModal = new abp.ModalManager( abp.appPath + 'AbpPermissionManagement/PermissionManagementModal' ); var _editModal = new abp.ModalManager( abp.appPath + 'Claims/EditModal' ); var _createModal = new abp.ModalManager( abp.appPath + 'Claims/CreateModal' ); var _dataTable = null; abp.ui.extensions.entityActions.get('iDManagement.claims').addContributor( function (actionList) { return actionList.addManyTail( [ { text: l('Edit'), visible: abp.auth.isGranted( 'IDManagement.Claims.Update' ), action: function (data) { _editModal.open({ id: data.record.id, }); }, }, { text: l('Delete'), visible: function (data) { return ( abp.auth.isGranted( 'IDManagement.Claims.Delete' ) ); //TODO: Check permission }, confirmMessage: function (data) { return l( 'ConfirmDeletedClaim', data.record.name ); }, action: function (data) { _claimsServices .delete(data.record.id) .then(function () { _dataTable.ajax.reload(); }); }, } ] ); } ); abp.ui.extensions.tableColumns.get('iDManagement.claims').addContributor( function (columnList) { columnList.addManyTail( [ { title: l("Actions"), rowAction: { items: abp.ui.extensions.entityActions.get('iDManagement.claims').actions.toArray() } }, { title: l('Name'), data: 'name', }, { title: l('Description'), data: 'description', }, { title: l('Staic'), data: 'IsStatic', render: function (data, type, row) { var sdata = "<input type='checkbox' readonly checked disabled/>" if (!row.isStatic) { sdata = "<input type='checkbox' readonly disabled/>" } return sdata; } } ] ); }, 0 //adds as the first contributor ); $(function () { var _$wrapper = $('#ClaimsWrapper'); var _$table = _$wrapper.find('table'); _dataTable = _$table.DataTable( abp.libs.datatables.normalizeConfiguration({ order: [[1, 'asc']], searching: false, processing: true, serverSide: true, scrollX: true, paging: true, ajax: abp.libs.datatables.createAjax( _claimsServices.getList ), columnDefs: abp.ui.extensions.tableColumns.get('iDManagement.claims').columns.toArray() }) ); _createModal.onResult(function () { _dataTable.ajax.reload(); }); _editModal.onResult(function () { _dataTable.ajax.reload(); }); _$wrapper.find('button[name=CreateClaim]').click(function (e) { console.log("create"); e.preventDefault(); _createModal.open(); }); }); })(jQuery);
4.2 创建页
CreateModal.cshtml
@page
@model Kingsun.Liujb.IDManagement.Web.Pages.Claims.CreateModalModel
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Microsoft.Extensions.Localization
@using Kingsun.Liujb.IDManagement;
@using Kingsun.Liujb.IDManagement.Localization;
@using Kingsun.Liujb.IDManagement.Permissions;
@inject IHtmlLocalizer<IDManagementResource> L
@inject IStringLocalizerFactory StringLocalizerFactory
@{
Layout = null;
}
<form asp-page="/Claims/CreateModal" method="post">
<abp-modal>
<abp-modal-header title="@L["NewClaim"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Claim.Name" />
<abp-input asp-for="Claim.Description" />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</form>
public class CreateModalModel : IDManagementPageModel
{
private readonly Kingsun.Liujb.IDManagement.Claims.IClaimsService _claimsService;
public CreateModalModel(IClaimsService claimsService)
{
this._claimsService = claimsService;
}
[BindProperty]
public ClaimInfoModle Claim { get; set; }
public class ClaimInfoModle: ExtensibleObject
{
[Required]
[MaxLength(64)]
[Display(Name ="DisplayName:ClaimName")]
public string Name { get; set; }
[MaxLength(1000)]
[Display(Name = "DisplayName:Description")]
public string Description { get; set; }
}
public virtual Task<IActionResult> OnGetAsync()
{
Claim = new ClaimInfoModle();
return Task.FromResult<IActionResult>(Page());
}
public virtual async Task<IActionResult> OnPostAsync()
{
ValidateModel();
var input = ObjectMapper.Map<ClaimInfoModle, CreateClaimDto>(this.Claim);
await _claimsService.CreateAsync(input);
return NoContent();
}
}
4.3 编辑页
EditModal.cshtml
@page
@model Kingsun.Liujb.IDManagement.Web.Pages.Claims.EditModalModel
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@using Microsoft.Extensions.Localization
@using Kingsun.Liujb.IDManagement;
@using Kingsun.Liujb.IDManagement.Localization;
@using Kingsun.Liujb.IDManagement.Permissions;
@inject IHtmlLocalizer<IDManagementResource> L
@inject IStringLocalizerFactory StringLocalizerFactory
@{
Layout = null;
}
<form asp-page="/Claims/EditModal" method="post">
<abp-modal>
<abp-modal-header title="@L["EditClaim"].Value"></abp-modal-header>
<abp-modal-body>
<input type="hidden" asp-for="ClaimInfo.ConcurrencyStamp" />
<input type="hidden" asp-for="ClaimInfo.Id" />
<abp-input asp-for="ClaimInfo.Name" readonly="true"/>
<abp-input asp-for="ClaimInfo.Description" />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</form>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Kingsun.Liujb.IDManagement.Claims;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Volo.Abp.Application.Dtos;
namespace Kingsun.Liujb.IDManagement.Web.Pages.Claims
{
public class EditModalModel : IDManagementPageModel
{
[BindProperty]
public UpdateClaimInfo ClaimInfo { get; set; }
[BindProperties]
public class UpdateClaimInfo:EntityDto<Guid>
{
[Required]
public string ConcurrencyStamp { get; set; }
public bool Required { get; set; }=false;
public string Description { get; set; }
public string Name { get; set; }
}
private readonly IClaimsService _claimService;
public EditModalModel(IClaimsService claimService)
{
this._claimService = claimService;
}
public async Task<IActionResult> OnGetAsync(Guid id)
{
var claim=await _claimService.GetAsync(id);
this.ClaimInfo = ObjectMapper.Map<ClaimDto, UpdateClaimInfo>(claim);
return Page();
}
public async Task<IActionResult> OnPostAsync() {
ValidateModel();
var input = ObjectMapper.Map<UpdateClaimInfo, UpdateClaimDto>(this.ClaimInfo);
await _claimService.UpdateAsync(this.ClaimInfo.Id, input);
return NoContent();
}
}
}
4.3 效果

三,添加IdentityServer相关管理功能
Volo.Abp.IdentityServer相关模块是基于.netcore app而不是.net standard,所以我们新建一个新的类库,但是目标框架为.net core。可以新建一个console程序,修改输出类型即可。

1,和前面声明管理模块一样,先添加管理服务相关接口及Dto,基本上差不太多

2,实现服务

这里贴一个client的管理服务实现类
[Authorize(Permissions.IDManagementPermissions.Clients.Defalut)]
public class ClientsService : IDManagementIdentityServerAppservice, IClientsService
{
private readonly IClientRepository _clientRepository;
private readonly IIdentityResourceRepository _identityResourceRepository;
private readonly IApiResourceRepository _apiResourceRepository;
public ClientsService(IClientRepository clientRepository ,
IIdentityResourceRepository _identityResourceRepository,
IApiResourceRepository _apiResourceRepository)
{
this._apiResourceRepository = _apiResourceRepository;
this._identityResourceRepository = _identityResourceRepository;
this._clientRepository = clientRepository;
}
[Authorize(Permissions.IDManagementPermissions.Clients.Create)]
public async Task<ClientDto> CreateAsync(CreateClientDto input)
{
var exsit = await _clientRepository.FindByCliendIdAsync(input.ClientName);
if (exsit != null)
throw new BusinessException(ExceptionCodes.ClientAreadyFound).WithData("0",input.ClientName);
var insert = new Client(GuidGenerator.Create(), input.ClientName);
ObjectMapper.Map<CreateClientDto, Client>(input,insert);
insert.ClientName = input.ClientName;
insert = await _clientRepository.InsertAsync(insert, true);
await UpdateClientExaAsync(client: insert, input.AllowedScopes, input.GrantTypes, input.RedirectUris, input.PostLogoutRedirectUris, input.Secret);
return ObjectMapper.Map<Client, ClientDto>(insert);
}
[Authorize(Permissions.IDManagementPermissions.Clients.Delete)]
public async Task DeleteAsync(Guid id)
{
var client = await _clientRepository.FindAsync(id);
if (client != null)
{
await _clientRepository.DeleteAsync(client);
}
else
throw new BusinessException(ExceptionCodes.ClientNotFound).WithData("0", id);
}
public async Task<ClientDto> GetAsync(Guid id)
{
var client = await _clientRepository.FindAsync(id);
if (client == null)
throw new BusinessException(Liujb.Shared.ExceptionCodes.ClientNotFound).WithData("0",id);
return ObjectMapper.Map<Client, ClientDto>(client);
}
public async Task<PagedResultDto<ClientDto>> GetListAsync(GetClientsInputDto input)
{
var count = await _clientRepository.GetCountAsync();
var list = await _clientRepository.GetPagedListAsync(input.SkipCount, input.MaxResultCount,
"CreationTime asc", true);
var retList = ObjectMapper.Map<List<Client>, List<ClientDto>>(list);
PagedResultDto<ClientDto> ret = new PagedResultDto<ClientDto>()
{
Items = retList,
TotalCount = count
};
return ret;
}
public async Task<string[]> GetScopesAsync()
{
var listIdentity = (await _identityResourceRepository.GetListAsync()).Select(r => r.Name).ToList();
var listApi = (await _apiResourceRepository.GetListAsync(true)).Select(r => r.Name).ToList();
listIdentity.AddRange(listApi);
return listIdentity.ToArray();
}
[Authorize(Permissions.IDManagementPermissions.Clients.Update)]
public async Task<ClientDto> UpdateAsync(Guid id, UpdateClientDto input)
{
var client =await _clientRepository.GetAsync(id,true);
if (client == null)
throw new BusinessException(ExceptionCodes.ClientNotFound).WithData("0", id);
ObjectMapper.Map<UpdateClientDto, Client>(input, client);
client.ClientSecrets = new List<ClientSecret>();
client.RemoveAllScopes();
await _clientRepository.UpdateAsync(client, true);
await UpdateClientExaAsync(client: client, input.AllowedScopes, input.GrantTypes, input.RedirectUris, input.PostLogoutRedirectUris, null);
return ObjectMapper.Map<Client, ClientDto>(client);
}
public async Task<bool> UpdatePasswordAsync(Guid id, string secret)
{
var client = await _clientRepository.GetAsync(id,true);
if(client==null)
throw new BusinessException(ExceptionCodes.ClientNotFound).WithData("0", id);
if (string.IsNullOrEmpty(secret))
throw new ArgumentNullException();
client.ClientSecrets = new List<ClientSecret>();
await _clientRepository.UpdateAsync(client,true);
client.AddSecret(secret.Sha256());
await _clientRepository.UpdateAsync(client);
return true;
}
private async Task<Client> UpdateClientExaAsync(
Client client,
IEnumerable<string> scopes,
IEnumerable<string> grantTypes,
IEnumerable<string> redirectUris = null,
IEnumerable<string> postLogoutRedirectUris = null,
string secret = null
)
{
foreach (var scope in scopes)
{
if (client.FindScope(scope) == null)
{
client.AddScope(scope);
}
}
foreach (var grantType in grantTypes)
{
if (client.FindGrantType(grantType) == null)
{
client.AddGrantType(grantType);
}
}
if (!secret.IsNullOrEmpty())
{
if (client.FindSecret(secret) == null)
{
client.AddSecret(secret.Sha256());
}
}
if (redirectUris != null)
{
redirectUris.ToList().ForEach(redirectUri =>
{
if (client.FindRedirectUri(redirectUri) == null)
{
client.AddRedirectUri(redirectUri);
}
});
}
if (postLogoutRedirectUris != null)
{
postLogoutRedirectUris.ToList().ForEach(postLogoutRedirectUri =>
{
if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null)
{
client.AddPostLogoutRedirectUri(postLogoutRedirectUri);
}
});
}
return await _clientRepository.UpdateAsync(client);
}
}
其中用到的Automapper配置类
public IDManagementIdentitysServerAutoMapperProfile()
{
CreateMap<CreateOrUpdateClientBaseDto, Client>(MemberList.Source);
CreateMap<Volo.Abp.IdentityServer.Clients.Client, ClientDto>()
.ForMember(d => d.RedirectUris, opt => opt.MapFrom(src => src.RedirectUris.Select(r => r.RedirectUri)))
.ForMember(d => d.PostLogoutRedirectUris, opt => opt.MapFrom(src => src.PostLogoutRedirectUris.Select(r => r.PostLogoutRedirectUri)))
.ForMember(d => d.AllowedScopes, opt => opt.MapFrom(src => src.AllowedScopes.Select(r => r.Scope)))
.ForMember(d => d.GrantTypes, opt => opt.MapFrom(src => src.AllowedGrantTypes.Select(r => r.GrantType)))
;
CreateMap<Volo.Abp.IdentityServer.ApiResources.ApiResource, ApiResourceDto>().ForMember(src=>src.Claims,
opt=>opt.MapFrom(src=>src.UserClaims.ToList().Select(r=>r.Type).ToList()));
CreateMap<IdentityResource, IdentityResourceDto>().ForMember(src => src.Claims,
opt => opt.MapFrom(src => src.UserClaims.ToList().Select(r => r.Type).ToList()));
}
3,暴露服务接口

4,添加相关页面

五,添加权限

public class IDManagementPermissions
{
public const string GroupName = "IDManagement";
public static class IdentityResource
{
public const string Defalut = GroupName + ".IdentityResource";
public const string Create = Defalut + ".Create";
public const string Update = Defalut + ".Update";
public const string Delete = Defalut + ".Delete";
}
public static class ApiResource
{
public const string Defalut = GroupName + ".ApiResource";
public const string Create = Defalut + ".Create";
public const string Update = Defalut + ".Update";
public const string Delete = Defalut + ".Delete";
}
public static class Clients
{
public const string Defalut = GroupName+".Clients";
public const string Create = Defalut + ".Create";
public const string Update = Defalut + ".Update";
public const string Delete = Defalut + ".Delete";
}
public static class Claims
{
public const string Defalut = GroupName + ".Claims";
public const string Create = Defalut + ".Create";
public const string Update = Defalut + ".Update";
public const string Delete = Defalut + ".Delete";
}
public static string[] GetAll()
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(IDManagementPermissions));
}
}
public override void Define(IPermissionDefinitionContext context)
{
var clientGroup = context.AddGroup(IDManagementPermissions.GroupName, L("Permission:IDManagement"));
var client=clientGroup.AddPermission(IDManagementPermissions.Clients.Defalut, L("Permission:Clients"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
client.AddChild(IDManagementPermissions.Clients.Create, L("Permission:Create"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
client.AddChild(IDManagementPermissions.Clients.Delete, L("Permission:Delete"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
client.AddChild(IDManagementPermissions.Clients.Update, L("Permission:Edit"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
var api = clientGroup.AddPermission(IDManagementPermissions.ApiResource.Defalut, L("Permission:Apis"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
api.AddChild(IDManagementPermissions.ApiResource.Create, L("Permission:Create"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
api.AddChild(IDManagementPermissions.ApiResource.Delete, L("Permission:Delete"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
api.AddChild(IDManagementPermissions.ApiResource.Update, L("Permission:Edit"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
var ids = clientGroup.AddPermission(IDManagementPermissions.IdentityResource.Defalut, L("Permission:Ids"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
ids.AddChild(IDManagementPermissions.IdentityResource.Create, L("Permission:Create"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
ids.AddChild(IDManagementPermissions.IdentityResource.Delete, L("Permission:Delete"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
ids.AddChild(IDManagementPermissions.IdentityResource.Update, L("Permission:Edit"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
var claims = clientGroup.AddPermission(IDManagementPermissions.Claims.Defalut, L("Permission:Claims"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
claims.AddChild(IDManagementPermissions.Claims.Create, L("Permission:Create"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
claims.AddChild(IDManagementPermissions.Claims.Delete, L("Permission:Delete"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
claims.AddChild(IDManagementPermissions.Claims.Update, L("Permission:Edit"), Volo.Abp.MultiTenancy.MultiTenancySides.Host);
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<Kingsun.Liujb.Shared.KingsunLiujbSharedResource>(name);
//LocalizableString.Create<IDManagementResource>(name);
}
}
六,添加菜单

public class IDManagementMenus
{
public const string Prefix = "IDManagement";
//Add your menu items here...
//public const string Home = Prefix + ".MyNewMenuItem";
public const string Claims = Prefix + ".Claims";
public const string Clients = Prefix + ".Clients";
public const string ApiResources = Prefix + ".ApiResources";
public const string IdentityResources = Prefix + ".IdentityResources";
}
private async Task ConfigureMainMenu(MenuConfigurationContext context)
{
//Add main menu items.
bool hasClaimsPermission = await context.IsGrantedAsync(Permissions.IDManagementPermissions.Claims.Defalut);
bool hasClientsPermission = await context.IsGrantedAsync(Permissions.IDManagementPermissions.Clients.Defalut);
bool hasApiResourcesPermission = await context.IsGrantedAsync(Permissions.IDManagementPermissions.ApiResource.Defalut);
bool hasIdentityResourcePermission = await context.IsGrantedAsync(Permissions.IDManagementPermissions.IdentityResource.Defalut);
var adminMenu = context.Menu.GetAdministration();
var L = context.GetLocalizer<Localization.IDManagementResource>();
if (hasClaimsPermission || hasApiResourcesPermission || hasClientsPermission || hasIdentityResourcePermission)
{
var group = new ApplicationMenuItem(IDManagementMenus.Prefix, L["Permission:IDManagement"],
icon: "fa fa-id-card-o");
if (hasClaimsPermission)
{
group.AddItem(new ApplicationMenuItem(IDManagementMenus.Claims,L["Permission:Claims"], icon: "fa fa-id-card-o",url:"~/Claims"));
}
if (hasClientsPermission)
{
group.AddItem(new ApplicationMenuItem(IDManagementMenus.Clients, L["Permission:Clients"], icon: "fa fa-id-card-o", url: "~/Clients"));
}
if (hasApiResourcesPermission)
{
group.AddItem(new ApplicationMenuItem(IDManagementMenus.ApiResources, L["Permission:Apis"], icon: "fa fa-id-card-o", url: "~/Apis"));
}
if (hasIdentityResourcePermission)
{
group.AddItem(new ApplicationMenuItem(IDManagementMenus.IdentityResources, L["Permission:Ids"], icon: "fa fa-id-card-o", url: "~/Ids"));
}
adminMenu.AddItem(group);
}
}
七,统一本地化资源管理

public static class ExceptionCodes
{
public const string ClientNotFound = "Kingsun.Liujb:0001";
public const string ClientAreadyFound = "Kingsun.Liujb:0002";
public const string ApiResourceNotFound = "Kingsun.Liujb:0003";
public const string ApiResourceAreadyFound = "Kingsun.Liujb:0004";
public const string IdentityResourceNotFound = "Kingsun.Liujb:0005";
public const string IdentityResourceAreadyFound = "Kingsun.Liujb:0006";
public const string ClaimNotFound = "Kingsun.Liujb:0007";
public const string ClaimAreadyFound = "Kingsun.Liujb:0008";
public const string CanNotDeleteAStaticClaim = "Kingsun.Liujb:0009";
}
[DependsOn(typeof(AbpLocalizationModule))]
public class KingsunLiujbSharedModule:AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<KingsunLiujbSharedModule>("Kingsun.Liujb.Shared");
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<KingsunLiujbSharedResource>("en")
.AddBaseTypes(typeof(DefaultResource))
.AddVirtualJson("/Localization/KingsunLiujbShared");
});
}
}
在Domain.Share包中Module类中使用统一资源
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<IDManagementResource>("en")
.AddBaseTypes(typeof(AbpValidationResource)
,typeof(Shared.KingsunLiujbSharedResource)
)
.AddVirtualJson("/Localization/IDManagement");
});
Configure<AbpExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace("Kingsun.Liujb.IDManagement", typeof(IDManagementResource));
options.MapCodeNamespace("Kingsun.Liujb", typeof(IDManagementResource));
});
八,验证客户端
1,使用密码模式获取token

2,使用Token随便访问一个api


浙公网安备 33010602011771号