mirror of https://github.com/abpframework/abp.git
csharpabpc-sharpframeworkblazoraspnet-coredotnet-coreaspnetcorearchitecturesaasdomain-driven-designangularmulti-tenancy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
4.8 KiB
183 lines
4.8 KiB
---
|
|
description: "ABP permission system and authorization patterns"
|
|
globs: "**/*Permission*.cs,**/*AppService*.cs,**/*Controller*.cs"
|
|
alwaysApply: false
|
|
---
|
|
|
|
# ABP Authorization
|
|
|
|
> **Docs**: https://abp.io/docs/latest/framework/fundamentals/authorization
|
|
|
|
## Permission Definition
|
|
Define permissions in `*.Application.Contracts` project:
|
|
|
|
```csharp
|
|
public static class BookStorePermissions
|
|
{
|
|
public const string GroupName = "BookStore";
|
|
|
|
public static class Books
|
|
{
|
|
public const string Default = GroupName + ".Books";
|
|
public const string Create = Default + ".Create";
|
|
public const string Edit = Default + ".Edit";
|
|
public const string Delete = Default + ".Delete";
|
|
}
|
|
}
|
|
```
|
|
|
|
Register in provider:
|
|
```csharp
|
|
public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
|
|
{
|
|
public override void Define(IPermissionDefinitionContext context)
|
|
{
|
|
var bookStoreGroup = context.AddGroup(BookStorePermissions.GroupName, L("Permission:BookStore"));
|
|
|
|
var booksPermission = bookStoreGroup.AddPermission(
|
|
BookStorePermissions.Books.Default,
|
|
L("Permission:Books"));
|
|
|
|
booksPermission.AddChild(
|
|
BookStorePermissions.Books.Create,
|
|
L("Permission:Books.Create"));
|
|
|
|
booksPermission.AddChild(
|
|
BookStorePermissions.Books.Edit,
|
|
L("Permission:Books.Edit"));
|
|
|
|
booksPermission.AddChild(
|
|
BookStorePermissions.Books.Delete,
|
|
L("Permission:Books.Delete"));
|
|
}
|
|
|
|
private static LocalizableString L(string name)
|
|
{
|
|
return LocalizableString.Create<BookStoreResource>(name);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Using Permissions
|
|
|
|
### Declarative (Attribute)
|
|
```csharp
|
|
[Authorize(BookStorePermissions.Books.Create)]
|
|
public virtual async Task<BookDto> CreateAsync(CreateBookDto input)
|
|
{
|
|
// Only users with Books.Create permission can execute
|
|
}
|
|
```
|
|
|
|
### Programmatic Check
|
|
```csharp
|
|
public class BookAppService : ApplicationService
|
|
{
|
|
public async Task DoSomethingAsync()
|
|
{
|
|
// Check and throw if not granted
|
|
await CheckPolicyAsync(BookStorePermissions.Books.Edit);
|
|
|
|
// Or check without throwing
|
|
if (await IsGrantedAsync(BookStorePermissions.Books.Delete))
|
|
{
|
|
// Has permission
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Allow Anonymous Access
|
|
```csharp
|
|
[AllowAnonymous]
|
|
public virtual async Task<BookDto> GetPublicBookAsync(Guid id)
|
|
{
|
|
// No authentication required
|
|
}
|
|
```
|
|
|
|
## Current User
|
|
Access authenticated user info via `CurrentUser` property (available in base classes like `ApplicationService`, `DomainService`, `AbpController`):
|
|
|
|
```csharp
|
|
public class BookAppService : ApplicationService
|
|
{
|
|
public async Task DoSomethingAsync()
|
|
{
|
|
// CurrentUser is available from base class - no injection needed
|
|
var userId = CurrentUser.Id;
|
|
var userName = CurrentUser.UserName;
|
|
var email = CurrentUser.Email;
|
|
var isAuthenticated = CurrentUser.IsAuthenticated;
|
|
var roles = CurrentUser.Roles;
|
|
var tenantId = CurrentUser.TenantId;
|
|
}
|
|
}
|
|
|
|
// In other services, inject ICurrentUser
|
|
public class MyService : ITransientDependency
|
|
{
|
|
private readonly ICurrentUser _currentUser;
|
|
public MyService(ICurrentUser currentUser) => _currentUser = currentUser;
|
|
}
|
|
```
|
|
|
|
### Ownership Validation
|
|
```csharp
|
|
public async Task UpdateMyBookAsync(Guid bookId, UpdateBookDto input)
|
|
{
|
|
var book = await _bookRepository.GetAsync(bookId);
|
|
|
|
if (book.CreatorId != CurrentUser.Id)
|
|
{
|
|
throw new AbpAuthorizationException();
|
|
}
|
|
|
|
// Update book...
|
|
}
|
|
```
|
|
|
|
## Multi-Tenancy Permissions
|
|
Control permission availability per tenant side:
|
|
|
|
```csharp
|
|
bookStoreGroup.AddPermission(
|
|
BookStorePermissions.Books.Default,
|
|
L("Permission:Books"),
|
|
multiTenancySide: MultiTenancySides.Tenant // Only for tenants
|
|
);
|
|
```
|
|
|
|
Options: `MultiTenancySides.Host`, `Tenant`, or `Both`
|
|
|
|
## Feature-Dependent Permissions
|
|
```csharp
|
|
booksPermission.RequireFeatures("BookStore.PremiumFeature");
|
|
```
|
|
|
|
## Permission Management
|
|
Grant/revoke permissions programmatically:
|
|
|
|
```csharp
|
|
public class MyService : ITransientDependency
|
|
{
|
|
private readonly IPermissionManager _permissionManager;
|
|
|
|
public async Task GrantPermissionToUserAsync(Guid userId, string permissionName)
|
|
{
|
|
await _permissionManager.SetForUserAsync(userId, permissionName, true);
|
|
}
|
|
|
|
public async Task GrantPermissionToRoleAsync(string roleName, string permissionName)
|
|
{
|
|
await _permissionManager.SetForRoleAsync(roleName, permissionName, true);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Security Best Practices
|
|
- Never trust client input for user identity
|
|
- Use `CurrentUser` property (from base class) or inject `ICurrentUser`
|
|
- Validate ownership in application service methods
|
|
- Filter queries by current user when appropriate
|
|
- Don't expose sensitive fields in DTOs
|
|
|