abp-authorization
ABP Framework v10.x (10.4/10.5) authorization: defining permissions (PermissionDefinitionProvider), [Authorize], CheckPolicyAsync/IsGrantedAsync, CurrentUser, IPermissionManager, resource-based auth, multi-tenancy permissions. Use when you need permission, role or access checks in ABP.
适合你,如果你在开发基于 ABP 框架的应用并需要实现授权机制。
npx oh-my-skill add burakdmir/abp-skills/abp-authorizationcurl -fsSL https://oh-my-skill.com/install.sh | bash -s -- burakdmir/abp-skills/abp-authorizationnpx oh-my-skill verify burakdmir/abp-skills/abp-authorization怎么用
商店整理自技能原文 · 版本 ce71259 · 表述以原文为准安装后,Claude能指导你在ABP项目中定义权限、进行授权检查、获取当前用户信息等。
当用户询问关于权限、授权、角色、策略、资源授权或ABP访问控制时触发。
技能原文 SKILL.md
ABP Authorization Skill
Trigger
User asks about permissions, authorization, roles, policies, permission groups, resource-based authorization, or access control in ABP Framework.
Core Concepts
ABP extends ASP.NET Core Authorization with a Permission System that auto-registers permissions as policies. Two permission types exist:
- Standard (Global) Permissions — Apply globally (e.g., "can create documents")
- Resource-Based Permissions — Target specific instances (e.g., "can edit Document #123")
Permission System
Defining Permissions
Create a class inheriting PermissionDefinitionProvider:
using Volo.Abp.Authorization.Permissions;
namespace Acme.BookStore.Permissions
{
public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var myGroup = context.AddGroup(
"BookStore",
LocalizableString.Create<BookStoreResource>("BookStore")
);
myGroup.AddPermission(
"BookStore_Author_Create",
LocalizableString.Create<BookStoreResource>("Permission:BookStore_Author_Create")
);
}
}
}
- ABP auto-discovers this class — no registration needed
- Typically placed in
Application.Contractsproject - Permission name becomes usable as an ASP.NET Core policy name
Permission Groups
context.AddGroup("GroupName")creates a new group- Groups appear as tabs in the UI permission dialog
- Use
LocalizableString.Create<TResource>("Key")for localized display names
Permission Options
myGroup.AddPermission(
"BookStore_Books_Manage",
LocalizableString.Create<BookStoreResource>("Permission:ManageBooks"),
multiTenancySide: MultiTenancySides.Tenant // Host, Tenant, or Both (default)
);
Multi-tenancy side options:
MultiTenancySides.Host— Available only on host sideMultiTenancySides.Tenant— Available only on tenant sideMultiTenancySides.Both(default) — Available on both
Child Permissions
Permissions can have parent-child relationships for hierarchical UI display:
var booksPermission = myGroup.AddPermission("BookStore_Books_Manage");
booksPermission.AddChild("BookStore_Books_Create");
booksPermission.AddChild("BookStore_Books_Edit");
booksPermission.AddChild("BookStore_Books_Delete");
Enable/Disable Permissions
myGroup.AddPermission("BookStore_Feature", isEnabled: false); // Disabled by default
Permission Depending on a Condition
// Depending on Features
myGroup.AddPermission("BookStore_Advanced")
.WithFeatureDependency("AdvancedFeature");
// Depending on Global Features
myGroup.AddPermission("BookStore_Preview")
.WithGlobalFeatureDependency("PreviewModule");
// Custom condition
myGroup.AddPermission("BookStore_Special")
.WithStateChecker(() => MyStaticChecker.IsSpecialEnabled);
Overriding Permissions with Custom Policies
myGroup.AddPermission("BookStore_Special")
.WithPolicyDependency(new MyCustomPolicyRequirement());
Changing Permission Definitions of Dependent Modules
[DependsOn(typeof(AbpIdentityModule))]
public class MyModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<PermissionDefinitionContext>(options =>
{
// Modify identity module permissions before they're finalized
});
}
}
Using Permissions
In Controllers / Page Models
[Authorize("BookStore_Author_Create")]
public async Task<IActionResult> CreateAsync(CreateAuthorDto input)
{
// ...
}
In Application Services
public class AuthorAppService : ApplicationService, IAuthorAppService
{
public async Task<AuthorDto> CreateAsync(CreateAuthorDto input)
{
await AuthorizationService.CheckAsync("BookStore_Author_Create");
// or
if (!await AuthorizationService.IsGrantedAsync("BookStore_Author_Create"))
{
throw new AbpAuthorizationException("...");
}
// ...
}
}
Using IAuthorizationService
public class MyService : ITransientDependency
{
private readonly IAuthorizationService _authorizationService;
public MyService(IAuthorizationService authorizationService)
{
_authorizationService = authorizationService;
}
public async Task DoWorkAsync()
{
await _authorizationService.CheckAsync("BookStore_Author_Create");
}
}
Shortcut methods in base classes:await CheckPolicyAsync("...")(throws an exception if not granted) andawait IsGrantedAsync("...")(returns a bool, does not throw).
Current User
Authenticated user information is accessed via the CurrentUser property — it is available out of the box in base classes (ApplicationService, DomainService, AbpController) and requires no injection:
public class BookAppService : ApplicationService
{
public async Task DoSomethingAsync()
{
var userId = CurrentUser.Id; // Guid?
var userName = CurrentUser.UserName;
var email = CurrentUser.Email;
var isAuth = CurrentUser.IsAuthenticated;
var roles = CurrentUser.Roles;
var tenantId = CurrentUser.TenantId;
}
}
// Inject ICurrentUser in services that don't derive from a base class
public class MyService : ITransientDependency
{
private readonly ICurrentUser _currentUser;
public MyService(ICurrentUser currentUser) => _currentUser = currentUser;
}
Ownership Verification
public async Task UpdateMyBookAsync(Guid bookId, UpdateBookDto input)
{
var book = await _bookRepository.GetAsync(bookId);
if (book.CreatorId != CurrentUser.Id)
{
throw new AbpAuthorizationException();
}
// update...
}
Security: never trust client input for the user identity — always use CurrentUser and verify ownership inside the application service.
Resource-Based Authorization
For fine-grained, per-instance permissions:
// Define a resource permission
var booksGroup = context.AddGroup("BookStore_Books");
var bookPermission = booksGroup.AddResourcePermission(
"BookStore_Books_Edit",
typeof(Book),
LocalizableString.Create<BookStoreResource>("Permission:EditBook")
);
Resource-based permissions are managed through the Resource Permission Management Dialog on individual resource instances (not the global permissions dialog).
See: Resource-Based Authorization
Multi-Tenancy Integration
- Permissions can be scoped to Host, Tenant, or Both
- When setting permissions for users/roles, use
ISettingManageror the Identity module UI - Tenant-specific permissions are stored per-tenant in the database
UI Integration
- Permissions dialog available with Identity module pre-installed
- Permission groups shown as tabs
- Standard permissions shown in global dialog
- Resource-based permissions managed per-resource instance
Best Practices
- Naming convention:
ModuleName_Entity_Action(e.g.,BookStore_Books_Create) - Always localize permission display names using
LocalizableString.Create<TResource>() - Group logically — one group per module or feature area
- Use child permissions for hierarchical UI (Manage > Create/Edit/Delete)
- Set multi-tenancy side explicitly if your app is multi-tenant
- Use resource-based permissions for instance-level access control
- Check permissions early in application service methods to fail fast
Common Patterns
CRUD Permissions
var books = myGroup.AddPermission("BookStore_Books_Manage");
books.AddChild("BookStore_Books_Create");
books.AddChild("BookStore_Books_Edit");
books.AddChild("BookStore_Books_Delete");
books.AddChild("BookStore_Books_ViewList");
Permission Check in App Service Base Class
public abstract class BookStoreAppService : ApplicationService
{
protected BookStoreAppService()
{
LocalizationResource = typeof(BookStoreResource);
}
protected virtual async Task CheckPolicyAsync(string policyName)
{
await AuthorizationService.CheckAsync(policyName);
}
}
What's New in v10.5
Single-Active Identity Token Providers (v10.5+)
ABP replaces ASP.NET Core Identity's default DataProtectorTokenProvider with AbpDefaultTokenProvider, and LinkUserTokenProvider uses the same single-active infrastructure. Tokens are now single-active per user/purpose: generating a new token invalidates the previous one. Default lifetime is 10 minutes:
Configure<AbpDefaultTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromMinutes(10);
});
Configure<AbpLinkUserTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromMinutes(10);
});
After upgrading to 10.5, re-test login, two-factor, forced/periodic password change, and link-user flows. If a flow sends multiple tokens for the same purpose and expects older ones to stay valid, switch it to use only the latest token.
OpenIddict Default Scope Fallback (v10.5+, opt-in)
For client_credentials, password, and token-exchange grants, ABP can fall back to the client application's registered scopes when the request omits the scope parameter. Disabled by default:
Configure<AbpOpenIddictAspNetCoreOptions>(options =>
{
options.UseDefaultScopesForClientCredentials = true;
options.UseDefaultScopesForPassword = true;
options.UseDefaultScopesForTokenExchange = true;
});
After enabling, re-test token issuance for the affected grant types and confirm the resulting scopes/resources match authorization expectations.
Related Modules
- Identity Module — User and role management, permission UI
- Permission Management Module — Resource permission management dialog
- Setting Management Module — Feature-based permission toggling
Related
- [Settings & Features](../abp-settings-features/SKILL.md) — feature-dependent permissions, IFeatureChecker
- [Multi-Tenancy](../abp-multitenancy/SKILL.md) — per-tenant permissions (MultiTenancySides)
- [Exception Handling](../abp-exception-handling/SKILL.md) — AbpAuthorizationException
- [UI](../abp-ui/SKILL.md) — permission checks in the UI (IsGrantedAsync, Authorize)
- ABP Docs: https://abp.io/docs/latest/framework/fundamentals/authorization