在Abp(aspnet boilerplate)中,授权AbpAuthorizeAttribute可以标记在类和方法中,其默认的规则为并集处理,即满足 (类中的权限 && 方法中的权限)
但有时候,我们往往需要的是方法的权限覆盖类的权限.
打个比方:
在默认样本工程中的UserAppService.cs文件中.开头的定义如下
[AbpAuthorize(PermissionNames.Pages_Users)]
public class UserAppService : AsyncCrudAppService<User, UserDto, long, PagedUserResultRequestDto, CreateUserDto, UserDto>, IUserAppService
{
...//此处省略代码
public async Task<bool> ChangePassword(ChangePasswordDto input)
{
}
...//此处省略代码
}
该接口是用来维护所有用户的接口,但是其修改密码的接口,是需要面向全部用户的.
这里我们就需要 在方法的上面添加注释,来覆盖类中原有的注释.因为不可能所有的用户都有[Users]的权限
接下来我们就需要改写授权规则.
在Application层新建一个cs文件,命名随意,我这命名MyAuthorizationHelper,继承AuthorizationHelper类,完整代码如下;
public class MyAuthorizationHelper : AuthorizationHelper
{
private IAuthorizationConfiguration _authConfiguration;
public MyAuthorizationHelper(IFeatureChecker featureChecker, IAuthorizationConfiguration authConfiguration) : base(featureChecker, authConfiguration)
{
_authConfiguration = authConfiguration;
}
[UnitOfWork]
public override async Task AuthorizeAsync(IEnumerable<IAbpAuthorizeAttribute> authorizeAttributes)
{
if (!_authConfiguration.IsEnabled)
{
return;
}
if (!AbpSession.UserId.HasValue)
{
throw new AbpAuthorizationException(
LocalizationManager.GetString(AbpConsts.LocalizationSourceName, "CurrentUserDidNotLoginToTheApplication")
);
}
if (authorizeAttributes!=null && authorizeAttributes.Any())
{
var authorizeAttribute = authorizeAttributes.First();
await PermissionChecker.AuthorizeAsync(authorizeAttribute.RequireAllPermissions, authorizeAttribute.Permissions);
}
//foreach (var authorizeAttribute in authorizeAttributes)
//{
// await PermissionChecker.AuthorizeAsync(authorizeAttribute.RequireAllPermissions, authorizeAttribute.Permissions);
//}
}
public override void Authorize(IEnumerable<IAbpAuthorizeAttribute> authorizeAttributes)
{
if (!_authConfiguration.IsEnabled)
{
return;
}
if (!AbpSession.UserId.HasValue)
{
throw new AbpAuthorizationException(
LocalizationManager.GetString(AbpConsts.LocalizationSourceName, "CurrentUserDidNotLoginToTheApplication")
);
}
if (authorizeAttributes != null && authorizeAttributes.Any())
{
var authorizeAttribute = authorizeAttributes.First();
PermissionChecker.Authorize(authorizeAttribute.RequireAllPermissions, authorizeAttribute.Permissions);
}
//foreach (var authorizeAttribute in authorizeAttributes)
//{
// PermissionChecker.Authorize(authorizeAttribute.RequireAllPermissions, authorizeAttribute.Permissions);
//}
}
}
其中注释掉的部分为原Abp的设计,这里改成了只取最底层属性,即 方法中有Attribute,就拿方法中的去校验,没有则取类中的attribute
这样我们再回到UserAppService中,给ChangePassword方法增加一个属性就可以愉快的贡献出接口啦.
[AbpAuthorize(PermissionNames.Pages_Users)]
public class UserAppService : AsyncCrudAppService<User, UserDto, long, PagedUserResultRequestDto, CreateUserDto, UserDto>, IUserAppService
{
...//此处省略代码
[AbpAuthorize()]//<-----这里
public async Task<bool> ChangePassword(ChangePasswordDto input)
{
}
...//此处省略代码
}
修改完毕后,别忘了去Module中去替换一下
在PreInitialize方法中添加下面的代码替换授权类.
Configuration.ReplaceService<IAuthorizationHelper, MyAuthorizationHelper>();
PS:标题的命名实在不知道该怎么命名,如各位有好的关键字,欢迎留言.谢谢各位看官了