Я использую ABP версии 3.9 для ASP.NET Core. У нас есть существующий экземпляр Identity Server 4, который предоставляет информацию о роли в форме заявок (через OIDC). Я хотел бы, среди прочего, подключиться к системе разрешений ABP для динамического меню. Поскольку я не использую локальную Identity Server 1 реализацию, я не вижу способа преобразовать утверждения в разрешения.
Моя мысль - использовать пользовательское промежуточное программное обеспечение для обработки следующим образом:
public class ClaimsToAbpPermissionsMiddleware
{
private readonly RequestDelegate _next;
public ClaimsToAbpPermissionsMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
// Get user
ClaimsPrincipal user = context.User;
// foreach claim of type "role"
var roleClaims = user.Claims.Where(claim => claim.Type == "role");
foreach (Claim claim in roleClaims)
{
switch (claim.Value)
{
case "TestResults":
// Assign applicable permission
// ...
break;
default:
break;
}
}
// Call the next delegate/middleware in the pipeline
await _next(context);
}
}
Проблема в том, что я не знаю, как применять разрешения. Управление пользователями 2 предлагает использовать UserManager
, который, по-видимому, обладает необходимой функциональностью.
Во-первых, Abp.ZeroCore
не имеет этого класса. Могу ли я использовать Abp.Zero
в приложении ASP.NET Core?
Во-вторых, похоже, что Abp.Authorization.Users.AbpUserManager
имеет аналогичную функциональность. Могу ли я использовать это? Однако я не уверен, как внедрить это в Startup
, так как для этого требуется несколько типов AbpUserManager<TRole, TUser>
, и я не знаю, какие типы использовать.
Любая помощь будет оценена.
Кроме того, то, что я пытаюсь выполнимо? Есть ли лучший подход?
Проблема в том, что я не использую Module Zero Управление пользователями 2 . Все наши пользователи находятся в отдельной реализации Identity Server ASP.NET, и я использую шаблон из ABP, который не включает модели / страницы для user / tenant / role, поэтому у меня нет типы для введения AbpUserManager<TRole, TUser>
.
1 https://aspnetboilerplate.com/Pages/Documents/Zero/Identity-Server
2 https://aspnetboilerplate.com/Pages/Documents/Zero/User-Management
Обновление: Поэтому я реализовал IPermissionChecker согласно ответу ниже:
PermissionChecker (не влюблен в коммутатор, но собираюсь провести рефакторинг, как только он заработает):
public class PermissionChecker : IPermissionChecker, ITransientDependency
{
private readonly IHttpContextAccessor _httpContextAccessor;
public PermissionChecker(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<bool> IsGrantedAsync(string permissionName)
{
bool isGranted = false;
// Get user
var user = _httpContextAccessor.HttpContext.User;
// Get claims of type "role"
var roleClaims = user.Claims.Where(claim => claim.Type == "role");
// Check for applicable permission based on role permissions
foreach (Claim claim in roleClaims)
{
switch (claim.Value)
{
case "TestResults":
// Assign applicable permission
// ...
if(permissionName.ToLowerInvariant() == "TestResults".ToLowerInvariant())
{
isGranted = true;
}
break;
case "About":
// Assign applicable permission
// ...
if (permissionName.ToLowerInvariant() == "AboutView".ToLowerInvariant())
{
isGranted = true;
}
break;
case "Account":
// Assign applicable permission
// ...
if (permissionName.ToLowerInvariant() == "AccountView".ToLowerInvariant())
{
isGranted = true;
}
break;
default:
break;
}
if (isGranted)
{
break;
}
}
//return new Task<bool>
return Task.FromResult(isGranted);
}
public Task<bool> IsGrantedAsync(UserIdentifier user, string permissionName)
{
return IsGrantedAsync(permissionName);
}
}
AuthorizationProvider:
public class MyAuthProvider : AuthorizationProvider
{
public override void SetPermissions(IPermissionDefinitionContext context)
{
var about = context.CreatePermission("AboutView");
var account = context.CreatePermission("AccountView");
var testResults = context.CreatePermission("TestResults");
}
}
Инициализация модуля:
public class CentralPortalCoreModule : AbpModule
{
public override void PreInitialize()
{
Configuration.Auditing.IsEnabledForAnonymousUsers = true;
CentralPortalLocalizationConfigurer.Configure(Configuration.Localization);
IocManager.Register<IPermissionChecker, PermissionChecker>(DependencyLifeStyle.Transient);
Configuration.Authorization.Providers.Add<MyAuthProvider>();
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(CentralPortalCoreModule).GetAssembly());
}
}
Поставщик навигации:
public override void SetNavigation(INavigationProviderContext context)
{
context.Manager.MainMenu
.AddItem(
new MenuItemDefinition(
PageNames.Home,
L("HomePage"),
url: "",
icon: "fa fa-home"
)
).AddItem(
new MenuItemDefinition(
PageNames.About,
L("About"),
url: "Home/About",
icon: "fa fa-info",
requiredPermissionName: "AboutView",
requiresAuthentication: true
)
).AddItem(
new MenuItemDefinition(
"Results",
L("Results"),
url: "Results",
icon: "fa fa-tasks",
requiredPermissionName: "TestResults"
)
)
.AddItem(
new MenuItemDefinition(
PageNames.Account,
L("Account"),
url: "Account",
icon: "fa fa-info",
requiredPermissionName:"AccountView",
requiresAuthentication: true
)
)
.AddItem(
new MenuItemDefinition(
PageNames.Contact,
L("Contact"),
url: "Contact",
icon: "fa fa-info"
)
);
}
Добавление точек останова показывает, что PermissionChecker инициализируется так же, как и AuthProvider. К сожалению, навигация не показывает защищенные элементы, несмотря на то, что я прошел проверку подлинности и имею действительные заявки на роль. Метод IsGrantedAsync никогда не вызывается. Я попытался установить элементы навигации с помощью requireAuthentication = true и false, но ничего не изменилось.
Я что-то упустил?