我们的接口不是任何人都可以访问的,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
在ABP框架的=权限管理基本上是围绕数据库中的AbpPermissions表进行的,它明确表示了那个角色/租户用有什么权限。
那么我们怎么利用这个数据库表进行权限控制呢?显然并不是进行简单的权限的增删查改。
在Core层(领域层)找到PermissionNames类。把权限名字配置到这个类中
我们可以看到他有三个默认的权限,我们再在给他添加一个Task权限
public const string Pages_Task = "Taske";
public override void SetPermissions(IPermissionDefinitionContext context)
{
context.CreatePermission(PermissionNames.Pages_Users, L("Users"));
context.CreatePermission(PermissionNames.Pages_Roles, L("Roles"));
context.CreatePermission(PermissionNames.Pages_Tenants, L("Tenants"), multiTenancySides: MultiTenancySides.Host);
context.CreatePermission(PermissionNames.Pages_Task, L("Task"));
}
这是为什么呢?我们第三步再回答。
你不能单凭一个数据库说有这个权限就有呀,必须验证一下
那我们找一个接口来测试一下
[AbpAuthorize(PermissionNames.Pages_Task)]
public string Test()
{
return "Hello World";
}
我们登录非 角色Id为1,和角色Id为2 的 用户,这些非权限用户,调用这个接口是,会显示权限不足的
如果是角色Id为1 或 角色Id为2 的用户,如 Admin。是显示成功的
这种方式当没有权限时,将直接抛出异常。
public string Test()
{
try
{
PermissionChecker.Authorize(PermissionNames.Pages_Task);
return "Hello World";
}
catch {
return "这用户没权限";
}
}
前言说到,权限控制和核心是哪个数据库表,那么我们手动在数据库添加权限信息,就可以获得对应权限了吗?
那么我们手动为:Id为4的用户加个权限吧(这个Id为4的用户我是没有任何角色的)
登录Id 为4的用户后, 结果显示:接口是成功的,说明,Id为4的用户获得了Taske权限
理论上,我们的权限配置。编写数据库语句对AbpPermissions表进行操作就可以了,当然这也是可行的。
这是因为在EF层(基础设施层)的HostRoleAndUserCreator类中有这么一段代码
// Grant all permissions to admin role for host
var grantedPermissions = _context.Permissions.IgnoreQueryFilters()
.OfType()
.Where(p => p.TenantId == null && p.RoleId == adminRoleForHost.Id)
.Select(p => p.Name)
.ToList();
var permissions = PermissionFinder
.GetAllPermissions(new AbpDemoAuthorizationProvider())
.Where(p => p.MultiTenancySides.HasFlag(MultiTenancySides.Host) &&
!grantedPermissions.Contains(p.Name))
.ToList();
if (permissions.Any())
{
_context.Permissions.AddRange(
permissions.Select(permission => new RolePermissionSetting
{
TenantId = null,
Name = permission.Name,
IsGranted = true,
RoleId = adminRoleForHost.Id
})
);
_context.SaveChanges();
}
具体分析一下这段代码,我们可以知道,
grantedPermissions:是找到,权限表中所有 租户为null 并且 角色Id为默认角色Id的权限名
permissions:是查找在全部权限中,grantedPermissions中没有的权限。
然后就遍历permissions,为默认角色添加权限。
这就介绍了为什么,我们一运行,角色Id 1 与 2拥有默认的全部权限
我们也可以仿照他的方法为我们的,角色添加权限
我们可以看到,ABP框架的 角色创建接口,是有一个permissions权限数组的。在里面输入一串的权限名。创建角色就会有对应的权限
我们找到他的接口代码,来分析一下
public override async Task Create(CreateRoleDto input)
{
CheckCreatePermission();
//创建角色
var role = ObjectMapper.Map(input);
role.SetNormalizedName();
CheckErrors(await _roleManager.CreateAsync(role));
//赋予权限
var grantedPermissions = PermissionManager
.GetAllPermissions()
.Where(p => input.Permissions.Contains(p.Name))
.ToList();
await _roleManager.SetGrantedPermissionsAsync(role, grantedPermissions);
return MapToEntityDto(role);
}
grantedPermissions:是从权限表中,查找出在Permissions数组中判断是否有p.Name指定的权限
然后利用:await _roleManager.SetGrantedPermissionsAsync(role, grantedPermissions);为权限表添加信息。
public override async Task Update(RoleDto input)
{
CheckUpdatePermission();
//修改角色信息
var role = await _roleManager.GetRoleByIdAsync(input.Id);
ObjectMapper.Map(input, role);
CheckErrors(await _roleManager.UpdateAsync(role));
//修改权限
var grantedPermissions = PermissionManager
.GetAllPermissions()
.Where(p => input.Permissions.Contains(p.Name))
.ToList();
await _roleManager.SetGrantedPermissionsAsync(role, grantedPermissions);
return MapToEntityDto(role);
}
修改角色权限,和创建角色权限,居然是一样的
原来SetGrantedPermissionsAsync方法,同时有设置角色的所有授予权限,和禁止所有其他权限的功能。
换句话说,我们只需要考虑给他什么权限就可以了。其他数据库操作SetGrantedPermissionsAsync方法已经帮我们封装好了,传个权限数组给他就完成了。(当然自己编写数据库语句也是可以完成的)
var allPermissions = PermissionManager.GetAllPermissions()