• ABP 权限拦截 第二篇


      由于访问人数过多,我今天从新整理一下ABP权限认证机制,帮助大家更容易读懂

    1、Abp 的权限拦截主要通过过滤器,    public class AbpAuthorizationFilter : IAsyncAuthorizationFilter, ITransientDependency 实现的,他的代码如下

        public class AbpAuthorizationFilter : IAsyncAuthorizationFilter, ITransientDependency
        {
            public ILogger Logger { get; set; }
    
            private readonly IAuthorizationHelper _authorizationHelper;
            private readonly IErrorInfoBuilder _errorInfoBuilder;
            private readonly IEventBus _eventBus;
    
            public AbpAuthorizationFilter(
                IAuthorizationHelper authorizationHelper,
                IErrorInfoBuilder errorInfoBuilder,
                IEventBus eventBus)
            {
                _authorizationHelper = authorizationHelper;
                _errorInfoBuilder = errorInfoBuilder;
                _eventBus = eventBus;
                Logger = NullLogger.Instance;
            }
    
            public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
            {
                // Allow Anonymous skips all authorization
                if (context.Filters.Any(item => item is IAllowAnonymousFilter))
                {
                    return;
                }
    
                if (!context.ActionDescriptor.IsControllerAction())
                {
                    return;
                }
    
                //TODO: Avoid using try/catch, use conditional checking
                try
                {
                    await _authorizationHelper.AuthorizeAsync(
                        context.ActionDescriptor.GetMethodInfo(),
                        context.ActionDescriptor.GetMethodInfo().DeclaringType
                    );
                }
                catch (AbpAuthorizationException ex)
                {
                    Logger.Warn(ex.ToString(), ex);
    
                    _eventBus.Trigger(this, new AbpHandledExceptionData(ex));
    
                    if (ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType))
                    {
                        context.Result = new ObjectResult(new AjaxResponse(_errorInfoBuilder.BuildForException(ex), true))
                        {
                            StatusCode = context.HttpContext.User.Identity.IsAuthenticated
                                ? (int) System.Net.HttpStatusCode.Forbidden
                                : (int) System.Net.HttpStatusCode.Unauthorized
                        };
                    }
                    else
                    {
                        context.Result = new ChallengeResult();
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.ToString(), ex);
    
                    _eventBus.Trigger(this, new AbpHandledExceptionData(ex));
    
                    if (ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType))
                    {
                        context.Result = new ObjectResult(new AjaxResponse(_errorInfoBuilder.BuildForException(ex)))
                        {
                            StatusCode = (int) System.Net.HttpStatusCode.InternalServerError
                        };
                    }
                    else
                    {
                        //TODO: How to return Error page?
                        context.Result = new StatusCodeResult((int)System.Net.HttpStatusCode.InternalServerError);
                    }
                }
            }
        }

    他的核心代码:

      await _authorizationHelper.AuthorizeAsync(
                        context.ActionDescriptor.GetMethodInfo(),
                        context.ActionDescriptor.GetMethodInfo().DeclaringType
                    );

    要拦截异常处理,前提是类或者方法上面有AbpAuthorization 特性,我们来看看AbpAuthorization

       /// <summary>
        /// This attribute is used on a method of an Application Service (A class that implements <see cref="IApplicationService"/>)
        /// to make that method usable only by authorized users.
        /// </summary>
        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
        public class AbpAuthorizeAttribute : Attribute, IAbpAuthorizeAttribute
        {
    
    
            /// <summary>
            /// A list of permissions to authorize.
            /// </summary>
            public string[] Permissions { get; }
    
            /// <summary>
            /// If this property is set to true, all of the <see cref="Permissions"/> must be granted.
            /// If it's false, at least one of the <see cref="Permissions"/> must be granted.
            /// Default: false.
            /// </summary>
            public bool RequireAllPermissions { get; set; }
    
            /// <summary>
            /// Creates a new instance of <see cref="AbpAuthorizeAttribute"/> class.
            /// </summary>
            /// <param name="permissions">A list of permissions to authorize</param>
            public AbpAuthorizeAttribute(params string[] permissions)
            {
                Permissions = permissions;
            }
        }

    权限检查帮助类:AuthorizationHelper

        public class AuthorizationHelper : IAuthorizationHelper, ITransientDependency
        {
            public IAbpSession AbpSession { get; set; }
            public IPermissionChecker PermissionChecker { get; set; }
            public IFeatureChecker FeatureChecker { get; set; }
            public ILocalizationManager LocalizationManager { get; set; }
    
            private readonly IFeatureChecker _featureChecker;
            private readonly IAuthorizationConfiguration _authConfiguration;
    
            public AuthorizationHelper(IFeatureChecker featureChecker, IAuthorizationConfiguration authConfiguration)
            {
                _featureChecker = featureChecker;
                _authConfiguration = authConfiguration;
                AbpSession = NullAbpSession.Instance;
                PermissionChecker = NullPermissionChecker.Instance;
                LocalizationManager = NullLocalizationManager.Instance;
            }
    
            //验证权限
            public virtual async Task AuthorizeAsync(IEnumerable<IAbpAuthorizeAttribute> authorizeAttributes)
            {
                if (!_authConfiguration.IsEnabled)
                {
                    return;
                }
                //判断当前用户是否登录
                if (!AbpSession.UserId.HasValue)
                {
                    //交给异常程序处理
                    throw new AbpAuthorizationException(
                        LocalizationManager.GetString(AbpConsts.LocalizationSourceName, "CurrentUserDidNotLoginToTheApplication")
                        );
                }
    
                //检查所有权限
                foreach (var authorizeAttribute in authorizeAttributes)
                {
                    await PermissionChecker.AuthorizeAsync(authorizeAttribute.RequireAllPermissions, authorizeAttribute.Permissions);
                }
            }
    
            public virtual async Task AuthorizeAsync(MethodInfo methodInfo, Type type)
            {
                await CheckFeatures(methodInfo, type);
                await CheckPermissions(methodInfo, type);
            }
    
            protected virtual async Task CheckFeatures(MethodInfo methodInfo, Type type)
            {
                //检查必要特性
                var featureAttributes = ReflectionHelper.GetAttributesOfMemberAndType<RequiresFeatureAttribute>(methodInfo, type);
    
                if (featureAttributes.Count <= 0)
                {
                    return;
                }
    
                foreach (var featureAttribute in featureAttributes)
                {
                    await _featureChecker.CheckEnabledAsync(featureAttribute.RequiresAll, featureAttribute.Features);
                }
            }
    
            protected virtual async Task CheckPermissions(MethodInfo methodInfo, Type type)
            {
                //判断是否开启验证
                if (!_authConfiguration.IsEnabled)
                {
                    return;
                }
    
                //是否有AllowAnonymous标记
                if (AllowAnonymous(methodInfo, type))
                {
                    return;
                }
    
                //判断方法上面是否有AbpAuthorizeAttribute属性,没有就跳过 
                var authorizeAttributes =
                    ReflectionHelper
                        .GetAttributesOfMemberAndType(methodInfo, type)
                        .OfType<IAbpAuthorizeAttribute>()
                        .ToArray();
               if (!authorizeAttributes.Any())
                {
                    return;
                }
                //验证权限
                await AuthorizeAsync(authorizeAttributes);
            }
    
            private static bool AllowAnonymous(MemberInfo memberInfo, Type type)
            {
                return ReflectionHelper
                    .GetAttributesOfMemberAndType(memberInfo, type)
                    .OfType<IAbpAllowAnonymousAttribute>()
                    .Any();
            }
        }

    权限检查主要通过这个类实现的,PermissionCheckerExtensions,他的核心方法        public static async Task AuthorizeAsync(this IPermissionChecker permissionChecker, bool requireAll, params string[] permissionNames)

    PermissionCheckerExtensions 类的实现如下:

        public static class PermissionCheckerExtensions
        {
            /// <summary>
            /// Checks if current user is granted for a permission.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="permissionName">Name of the permission</param>
            public static bool IsGranted(this IPermissionChecker permissionChecker, string permissionName)
            {
                return AsyncHelper.RunSync(() => permissionChecker.IsGrantedAsync(permissionName));
            }
    
            /// <summary>
            /// Checks if a user is granted for a permission.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="user">User to check</param>
            /// <param name="permissionName">Name of the permission</param>
            public static bool IsGranted(this IPermissionChecker permissionChecker, UserIdentifier user, string permissionName)
            {
                return AsyncHelper.RunSync(() => permissionChecker.IsGrantedAsync(user, permissionName));
            }
    
            /// <summary>
            /// Checks if given user is granted for given permission.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="user">User</param>
            /// <param name="requiresAll">True, to require all given permissions are granted. False, to require one or more.</param>
            /// <param name="permissionNames">Name of the permissions</param>
            public static bool IsGranted(this IPermissionChecker permissionChecker, UserIdentifier user, bool requiresAll, params string[] permissionNames)
            {
                return AsyncHelper.RunSync(() => IsGrantedAsync(permissionChecker, user, requiresAll, permissionNames));
            }
    
            /// <summary>
            /// Checks if given user is granted for given permission.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="user">User</param>
            /// <param name="requiresAll">True, to require all given permissions are granted. False, to require one or more.</param>
            /// <param name="permissionNames">Name of the permissions</param>
            public static async Task<bool> IsGrantedAsync(this IPermissionChecker permissionChecker, UserIdentifier user, bool requiresAll, params string[] permissionNames)
            {
                if (permissionNames.IsNullOrEmpty())
                {
                    return true;
                }
    
                if (requiresAll)
                {
                    foreach (var permissionName in permissionNames)
                    {
                        if (!(await permissionChecker.IsGrantedAsync(user, permissionName)))
                        {
                            return false;
                        }
                    }
    
                    return true;
                }
                else
                {
                    foreach (var permissionName in permissionNames)
                    {
                        if (await permissionChecker.IsGrantedAsync(user, permissionName))
                        {
                            return true;
                        }
                    }
    
                    return false;
                }
            }
    
            /// <summary>
            /// Checks if current user is granted for given permission.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="requiresAll">True, to require all given permissions are granted. False, to require one or more.</param>
            /// <param name="permissionNames">Name of the permissions</param>
            public static bool IsGranted(this IPermissionChecker permissionChecker, bool requiresAll, params string[] permissionNames)
            {
                return AsyncHelper.RunSync(() => IsGrantedAsync(permissionChecker, requiresAll, permissionNames));
            }
    
            /// <summary>
            /// Checks if current user is granted for given permission.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="requiresAll">True, to require all given permissions are granted. False, to require one or more.</param>
            /// <param name="permissionNames">Name of the permissions</param>
            public static async Task<bool> IsGrantedAsync(this IPermissionChecker permissionChecker, bool requiresAll, params string[] permissionNames)
            {
    
                //权限为空
                if (permissionNames.IsNullOrEmpty())
                {
                    return true;
                }
    
               //检查所有权限
                if (requiresAll)
                {
                    foreach (var permissionName in permissionNames)
                    {
                        //检查权限
                        if (!(await permissionChecker.IsGrantedAsync(permissionName)))
                        {
                            return false;
                        }
                    }
    
                    return true;
                }
                else
                {
                    foreach (var permissionName in permissionNames)
                    {
                        if (await permissionChecker.IsGrantedAsync(permissionName))
                        {
                            return true;
                        }
                    }
    
                    return false;
                }
            }
    
            /// <summary>
            /// Authorizes current user for given permission or permissions,
            /// throws <see cref="AbpAuthorizationException"/> if not authorized.
            /// User it authorized if any of the <see cref="permissionNames"/> are granted.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="permissionNames">Name of the permissions to authorize</param>
            /// <exception cref="AbpAuthorizationException">Throws authorization exception if</exception>
            public static void Authorize(this IPermissionChecker permissionChecker, params string[] permissionNames)
            {
                Authorize(permissionChecker, false, permissionNames);
            }
    
            /// <summary>
            /// Authorizes current user for given permission or permissions,
            /// throws <see cref="AbpAuthorizationException"/> if not authorized.
            /// User it authorized if any of the <see cref="permissionNames"/> are granted.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="requireAll">
            /// If this is set to true, all of the <see cref="permissionNames"/> must be granted.
            /// If it's false, at least one of the <see cref="permissionNames"/> must be granted.
            /// </param>
            /// <param name="permissionNames">Name of the permissions to authorize</param>
            /// <exception cref="AbpAuthorizationException">Throws authorization exception if</exception>
            public static void Authorize(this IPermissionChecker permissionChecker, bool requireAll, params string[] permissionNames)
            {
                AsyncHelper.RunSync(() => AuthorizeAsync(permissionChecker, requireAll, permissionNames));
            }
    
            /// <summary>
            /// Authorizes current user for given permission or permissions,
            /// throws <see cref="AbpAuthorizationException"/> if not authorized.
            /// User it authorized if any of the <see cref="permissionNames"/> are granted.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="permissionNames">Name of the permissions to authorize</param>
            /// <exception cref="AbpAuthorizationException">Throws authorization exception if</exception>
            public static Task AuthorizeAsync(this IPermissionChecker permissionChecker, params string[] permissionNames)
            {
                return AuthorizeAsync(permissionChecker, false, permissionNames);
            }
    
            /// <summary>
            /// Authorizes current user for given permission or permissions,
            /// throws <see cref="AbpAuthorizationException"/> if not authorized.
            /// </summary>
            /// <param name="permissionChecker">Permission checker</param>
            /// <param name="requireAll">
            /// If this is set to true, all of the <see cref="permissionNames"/> must be granted.
            /// If it's false, at least one of the <see cref="permissionNames"/> must be granted.
            /// </param>
            /// <param name="permissionNames">Name of the permissions to authorize</param>
            /// <exception cref="AbpAuthorizationException">Throws authorization exception if</exception>
            public static async Task AuthorizeAsync(this IPermissionChecker permissionChecker, bool requireAll, params string[] permissionNames)
            {
                if (await IsGrantedAsync(permissionChecker, requireAll, permissionNames))
                {
                    return;
                }
    
                var localizedPermissionNames = LocalizePermissionNames(permissionChecker, permissionNames);
    
                if (requireAll)
                {
                    throw new AbpAuthorizationException(
                        string.Format(
                            L(
                                permissionChecker,
                                "AllOfThesePermissionsMustBeGranted",
                                "Required permissions are not granted. All of these permissions must be granted: {0}"
                            ),
                            string.Join(", ", localizedPermissionNames)
                        )
                    );
                }
                else
                {
                    throw new AbpAuthorizationException(
                        string.Format(
                            L(
                                permissionChecker,
                                "AtLeastOneOfThesePermissionsMustBeGranted",
                                "Required permissions are not granted. At least one of these permissions must be granted: {0}"
                            ),
                            string.Join(", ", localizedPermissionNames)
                        )
                    );
                }
            }
    
            public static string L(IPermissionChecker permissionChecker, string name, string defaultValue)
            {
                if (!(permissionChecker is IIocManagerAccessor))
                {
                    return defaultValue;
                }
    
                var iocManager = (permissionChecker as IIocManagerAccessor).IocManager;
                using (var localizationManager = iocManager.ResolveAsDisposable<ILocalizationManager>())
                {
                    return localizationManager.Object.GetString(AbpConsts.LocalizationSourceName, name);
                }
            }
    
            public static string[] LocalizePermissionNames(IPermissionChecker permissionChecker, string[] permissionNames)
            {
                if (!(permissionChecker is IIocManagerAccessor))
                {
                    return permissionNames;
                }
    
                var iocManager = (permissionChecker as IIocManagerAccessor).IocManager;
                using (var localizationContext = iocManager.ResolveAsDisposable<ILocalizationContext>())
                {
                    using (var permissionManager = iocManager.ResolveAsDisposable<IPermissionManager>())
                    {
                        return permissionNames.Select(permissionName =>
                        {
                            var permission = permissionManager.Object.GetPermissionOrNull(permissionName);
                            return permission?.DisplayName == null
                                ? permissionName
                                : permission.DisplayName.Localize(localizationContext.Object);
                        }).ToArray();
                    }
                }
            }
        }

    以上大家会发现核心代码是  await _userManager.IsGrantedAsync(userId, permissionName);,这个类是在AbpUserManager,而这个类是用户管理的类,里面涉及的东西很多,比如Identity Server 4,我们只需要理解大概意思

        public class AbpUserManager<TRole, TUser> : UserManager<TUser>, IDomainService
            where TRole : AbpRole<TUser>, new()
            where TUser : AbpUser<TUser>
        {
            protected IUserPermissionStore<TUser> UserPermissionStore
            {
                get
                {
                    if (!(Store is IUserPermissionStore<TUser>))
                    {
                        throw new AbpException("Store is not IUserPermissionStore");
                    }
    
                    return Store as IUserPermissionStore<TUser>;
                }
            }
    
            public ILocalizationManager LocalizationManager { get; set; }
    
            protected string LocalizationSourceName { get; set; }
    
            public IAbpSession AbpSession { get; set; }
    
            public FeatureDependencyContext FeatureDependencyContext { get; set; }
    
            protected AbpRoleManager<TRole, TUser> RoleManager { get; }
    
            protected AbpUserStore<TRole, TUser> AbpUserStore { get; }
    
            public IMultiTenancyConfig MultiTenancy { get; set; }
    
            private readonly IPermissionManager _permissionManager;
            private readonly IUnitOfWorkManager _unitOfWorkManager;
            private readonly ICacheManager _cacheManager;
            private readonly IRepository<OrganizationUnit, long> _organizationUnitRepository;
            private readonly IRepository<UserOrganizationUnit, long> _userOrganizationUnitRepository;
            private readonly IOrganizationUnitSettings _organizationUnitSettings;
            private readonly ISettingManager _settingManager;
            private readonly IOptions<IdentityOptions> _optionsAccessor;
    
            public AbpUserManager(
                AbpRoleManager<TRole, TUser> roleManager,
                AbpUserStore<TRole, TUser> userStore,
                IOptions<IdentityOptions> optionsAccessor,
                IPasswordHasher<TUser> passwordHasher,
                IEnumerable<IUserValidator<TUser>> userValidators,
                IEnumerable<IPasswordValidator<TUser>> passwordValidators,
                ILookupNormalizer keyNormalizer,
                IdentityErrorDescriber errors,
                IServiceProvider services,
                ILogger<UserManager<TUser>> logger,
                IPermissionManager permissionManager,
                IUnitOfWorkManager unitOfWorkManager,
                ICacheManager cacheManager,
                IRepository<OrganizationUnit, long> organizationUnitRepository,
                IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
                IOrganizationUnitSettings organizationUnitSettings,
                ISettingManager settingManager)
                : base(
                    userStore,
                    optionsAccessor,
                    passwordHasher,
                    userValidators,
                    passwordValidators,
                    keyNormalizer,
                    errors,
                    services,
                    logger)
            {
                _permissionManager = permissionManager;
                _unitOfWorkManager = unitOfWorkManager;
                _cacheManager = cacheManager;
                _organizationUnitRepository = organizationUnitRepository;
                _userOrganizationUnitRepository = userOrganizationUnitRepository;
                _organizationUnitSettings = organizationUnitSettings;
                _settingManager = settingManager;
                _optionsAccessor = optionsAccessor;
    
                AbpUserStore = userStore;
                RoleManager = roleManager;
                LocalizationManager = NullLocalizationManager.Instance;
                LocalizationSourceName = AbpZeroConsts.LocalizationSourceName;
            }
    
            public override async Task<IdentityResult> CreateAsync(TUser user)
            {
                var result = await CheckDuplicateUsernameOrEmailAddressAsync(user.Id, user.UserName, user.EmailAddress);
                if (!result.Succeeded)
                {
                    return result;
                }
    
                var tenantId = GetCurrentTenantId();
                if (tenantId.HasValue && !user.TenantId.HasValue)
                {
                    user.TenantId = tenantId.Value;
                }
    
                var isLockoutEnabled = user.IsLockoutEnabled;
    
                var identityResult = await base.CreateAsync(user);
                if (identityResult.Succeeded)
                {
                    await SetLockoutEnabledAsync(user, isLockoutEnabled);
                }
    
                return identityResult;
            }
    
            /// <summary>
            /// Check whether a user is granted for a permission.
            /// </summary>
            /// <param name="userId">User id</param>
            /// <param name="permissionName">Permission name</param>
            public virtual async Task<bool> IsGrantedAsync(long userId, string permissionName)
            {
                return await IsGrantedAsync(
                    userId,
                    _permissionManager.GetPermission(permissionName)
                    );
            }
    
            /// <summary>
            /// Check whether a user is granted for a permission.
            /// </summary>
            /// <param name="user">User</param>
            /// <param name="permission">Permission</param>
            public virtual Task<bool> IsGrantedAsync(TUser user, Permission permission)
            {
                return IsGrantedAsync(user.Id, permission);
            }
    
            /// <summary>
            /// Check whether a user is granted for a permission.
            /// </summary>
            /// <param name="userId">User id</param>
            /// <param name="permission">Permission</param>
            public virtual async Task<bool> IsGrantedAsync(long userId, Permission permission)
            {
                //Check for multi-tenancy side,检查权限是否标记了多租户
                if (!permission.MultiTenancySides.HasFlag(GetCurrentMultiTenancySide()))
                {
                    return false;
                }
    
                //Check for depended features
                if (permission.FeatureDependency != null && GetCurrentMultiTenancySide() == MultiTenancySides.Tenant)
                {
                    FeatureDependencyContext.TenantId = GetCurrentTenantId();
    
                    if (!await permission.FeatureDependency.IsSatisfiedAsync(FeatureDependencyContext))
                    {
                        return false;
                    }
                }
    
                //Get cached user permissions
                var cacheItem = await GetUserPermissionCacheItemAsync(userId);
                if (cacheItem == null)
                {
                    return false;
                }
    
                //Check for user-specific value
                if (cacheItem.GrantedPermissions.Contains(permission.Name))
                {
                    return true;
                }
    
                if (cacheItem.ProhibitedPermissions.Contains(permission.Name))
                {
                    return false;
                }
    
                //Check for roles
                foreach (var roleId in cacheItem.RoleIds)
                {
                    if (await RoleManager.IsGrantedAsync(roleId, permission))
                    {
                        return true;
                    }
                }
    
                return false;
            }
    
            /// <summary>
            /// Gets granted permissions for a user.
            /// </summary>
            /// <param name="user">Role</param>
            /// <returns>List of granted permissions</returns>
            public virtual async Task<IReadOnlyList<Permission>> GetGrantedPermissionsAsync(TUser user)
            {
                var permissionList = new List<Permission>();
    
                foreach (var permission in _permissionManager.GetAllPermissions())
                {
                    if (await IsGrantedAsync(user.Id, permission))
                    {
                        permissionList.Add(permission);
                    }
                }
    
                return permissionList;
            }
    
            /// <summary>
            /// Sets all granted permissions of a user at once.
            /// Prohibits all other permissions.
            /// </summary>
            /// <param name="user">The user</param>
            /// <param name="permissions">Permissions</param>
            public virtual async Task SetGrantedPermissionsAsync(TUser user, IEnumerable<Permission> permissions)
            {
                var oldPermissions = await GetGrantedPermissionsAsync(user);
                var newPermissions = permissions.ToArray();
    
                foreach (var permission in oldPermissions.Where(p => !newPermissions.Contains(p)))
                {
                    await ProhibitPermissionAsync(user, permission);
                }
    
                foreach (var permission in newPermissions.Where(p => !oldPermissions.Contains(p)))
                {
                    await GrantPermissionAsync(user, permission);
                }
            }
    
            /// <summary>
            /// Prohibits all permissions for a user.
            /// </summary>
            /// <param name="user">User</param>
            public async Task ProhibitAllPermissionsAsync(TUser user)
            {
                foreach (var permission in _permissionManager.GetAllPermissions())
                {
                    await ProhibitPermissionAsync(user, permission);
                }
            }
    
            /// <summary>
            /// Resets all permission settings for a user.
            /// It removes all permission settings for the user.
            /// User will have permissions according to his roles.
            /// This method does not prohibit all permissions.
            /// For that, use <see cref="ProhibitAllPermissionsAsync"/>.
            /// </summary>
            /// <param name="user">User</param>
            public async Task ResetAllPermissionsAsync(TUser user)
            {
                await UserPermissionStore.RemoveAllPermissionSettingsAsync(user);
            }
    
            /// <summary>
            /// Grants a permission for a user if not already granted.
            /// </summary>
            /// <param name="user">User</param>
            /// <param name="permission">Permission</param>
            public virtual async Task GrantPermissionAsync(TUser user, Permission permission)
            {
                await UserPermissionStore.RemovePermissionAsync(user, new PermissionGrantInfo(permission.Name, false));
    
                if (await IsGrantedAsync(user.Id, permission))
                {
                    return;
                }
    
                await UserPermissionStore.AddPermissionAsync(user, new PermissionGrantInfo(permission.Name, true));
            }
    
            /// <summary>
            /// Prohibits a permission for a user if it's granted.
            /// </summary>
            /// <param name="user">User</param>
            /// <param name="permission">Permission</param>
            public virtual async Task ProhibitPermissionAsync(TUser user, Permission permission)
            {
                await UserPermissionStore.RemovePermissionAsync(user, new PermissionGrantInfo(permission.Name, true));
    
                if (!await IsGrantedAsync(user.Id, permission))
                {
                    return;
                }
    
                await UserPermissionStore.AddPermissionAsync(user, new PermissionGrantInfo(permission.Name, false));
            }
    
            public virtual Task<TUser> FindByNameOrEmailAsync(string userNameOrEmailAddress)
            {
                return AbpUserStore.FindByNameOrEmailAsync(userNameOrEmailAddress);
            }
    
            public virtual Task<List<TUser>> FindAllAsync(UserLoginInfo login)
            {
                return AbpUserStore.FindAllAsync(login);
            }
    
            public virtual Task<TUser> FindAsync(int? tenantId, UserLoginInfo login)
            {
                return AbpUserStore.FindAsync(tenantId, login);
            }
    
            public virtual Task<TUser> FindByNameOrEmailAsync(int? tenantId, string userNameOrEmailAddress)
            {
                return AbpUserStore.FindByNameOrEmailAsync(tenantId, userNameOrEmailAddress);
            }
    
            /// <summary>
            /// Gets a user by given id.
            /// Throws exception if no user found with given id.
            /// </summary>
            /// <param name="userId">User id</param>
            /// <returns>User</returns>
            /// <exception cref="AbpException">Throws exception if no user found with given id</exception>
            public virtual async Task<TUser> GetUserByIdAsync(long userId)
            {
                var user = await FindByIdAsync(userId.ToString());
                if (user == null)
                {
                    throw new AbpException("There is no user with id: " + userId);
                }
    
                return user;
            }
    
            public override async Task<IdentityResult> UpdateAsync(TUser user)
            {
                var result = await CheckDuplicateUsernameOrEmailAddressAsync(user.Id, user.UserName, user.EmailAddress);
                if (!result.Succeeded)
                {
                    return result;
                }
    
                //Admin user's username can not be changed!
                if (user.UserName != AbpUserBase.AdminUserName)
                {
                    if ((await GetOldUserNameAsync(user.Id)) == AbpUserBase.AdminUserName)
                    {
                        throw new UserFriendlyException(string.Format(L("CanNotRenameAdminUser"), AbpUserBase.AdminUserName));
                    }
                }
    
                return await base.UpdateAsync(user);
            }
    
            public override async Task<IdentityResult> DeleteAsync(TUser user)
            {
                if (user.UserName == AbpUserBase.AdminUserName)
                {
                    throw new UserFriendlyException(string.Format(L("CanNotDeleteAdminUser"), AbpUserBase.AdminUserName));
                }
    
                return await base.DeleteAsync(user);
            }
    
            public virtual async Task<IdentityResult> ChangePasswordAsync(TUser user, string newPassword)
            {
                var errors = new List<IdentityError>();
    
                foreach (var validator in PasswordValidators)
                {
                    var validationResult = await validator.ValidateAsync(this, user, newPassword);
                    if (!validationResult.Succeeded)
                    {
                        errors.AddRange(validationResult.Errors);
                    }
                }
    
                if (errors.Any())
                {
                    return IdentityResult.Failed(errors.ToArray());
                }
    
                await AbpUserStore.SetPasswordHashAsync(user, PasswordHasher.HashPassword(user, newPassword));
                return IdentityResult.Success;
            }
    
            public virtual async Task<IdentityResult> CheckDuplicateUsernameOrEmailAddressAsync(long? expectedUserId, string userName, string emailAddress)
            {
                var user = (await FindByNameAsync(userName));
                if (user != null && user.Id != expectedUserId)
                {
                    throw new UserFriendlyException(string.Format(L("Identity.DuplicateUserName"), userName));
                }
    
                user = (await FindByEmailAsync(emailAddress));
                if (user != null && user.Id != expectedUserId)
                {
                    throw new UserFriendlyException(string.Format(L("Identity.DuplicateEmail"), emailAddress));
                }
    
                return IdentityResult.Success;
            }
    
            public virtual async Task<IdentityResult> SetRoles(TUser user, string[] roleNames)
            {
                await AbpUserStore.UserRepository.EnsureCollectionLoadedAsync(user, u => u.Roles);
    
                //Remove from removed roles
                foreach (var userRole in user.Roles.ToList())
                {
                    var role = await RoleManager.FindByIdAsync(userRole.RoleId.ToString());
                    if (roleNames.All(roleName => role.Name != roleName))
                    {
                        var result = await RemoveFromRoleAsync(user, role.Name);
                        if (!result.Succeeded)
                        {
                            return result;
                        }
                    }
                }
    
                //Add to added roles
                foreach (var roleName in roleNames)
                {
                    var role = await RoleManager.GetRoleByNameAsync(roleName);
                    if (user.Roles.All(ur => ur.RoleId != role.Id))
                    {
                        var result = await AddToRoleAsync(user, roleName);
                        if (!result.Succeeded)
                        {
                            return result;
                        }
                    }
                }
    
                return IdentityResult.Success;
            }
    
            public virtual async Task<bool> IsInOrganizationUnitAsync(long userId, long ouId)
            {
                return await IsInOrganizationUnitAsync(
                    await GetUserByIdAsync(userId),
                    await _organizationUnitRepository.GetAsync(ouId)
                    );
            }
    
            public virtual async Task<bool> IsInOrganizationUnitAsync(TUser user, OrganizationUnit ou)
            {
                return await _userOrganizationUnitRepository.CountAsync(uou =>
                    uou.UserId == user.Id && uou.OrganizationUnitId == ou.Id
                    ) > 0;
            }
    
            public virtual async Task AddToOrganizationUnitAsync(long userId, long ouId)
            {
                await AddToOrganizationUnitAsync(
                    await GetUserByIdAsync(userId),
                    await _organizationUnitRepository.GetAsync(ouId)
                    );
            }
    
            public virtual async Task AddToOrganizationUnitAsync(TUser user, OrganizationUnit ou)
            {
                var currentOus = await GetOrganizationUnitsAsync(user);
    
                if (currentOus.Any(cou => cou.Id == ou.Id))
                {
                    return;
                }
    
                await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, currentOus.Count + 1);
    
                await _userOrganizationUnitRepository.InsertAsync(new UserOrganizationUnit(user.TenantId, user.Id, ou.Id));
            }
    
            public virtual async Task RemoveFromOrganizationUnitAsync(long userId, long ouId)
            {
                await RemoveFromOrganizationUnitAsync(
                    await GetUserByIdAsync(userId),
                    await _organizationUnitRepository.GetAsync(ouId)
                    );
            }
    
            public virtual async Task RemoveFromOrganizationUnitAsync(TUser user, OrganizationUnit ou)
            {
                await _userOrganizationUnitRepository.DeleteAsync(uou => uou.UserId == user.Id && uou.OrganizationUnitId == ou.Id);
            }
    
            public virtual async Task SetOrganizationUnitsAsync(long userId, params long[] organizationUnitIds)
            {
                await SetOrganizationUnitsAsync(
                    await GetUserByIdAsync(userId),
                    organizationUnitIds
                    );
            }
    
            private async Task CheckMaxUserOrganizationUnitMembershipCountAsync(int? tenantId, int requestedCount)
            {
                var maxCount = await _organizationUnitSettings.GetMaxUserMembershipCountAsync(tenantId);
                if (requestedCount > maxCount)
                {
                    throw new AbpException($"Can not set more than {maxCount} organization unit for a user!");
                }
            }
    
            public virtual async Task SetOrganizationUnitsAsync(TUser user, params long[] organizationUnitIds)
            {
                if (organizationUnitIds == null)
                {
                    organizationUnitIds = new long[0];
                }
    
                await CheckMaxUserOrganizationUnitMembershipCountAsync(user.TenantId, organizationUnitIds.Length);
    
                var currentOus = await GetOrganizationUnitsAsync(user);
    
                //Remove from removed OUs
                foreach (var currentOu in currentOus)
                {
                    if (!organizationUnitIds.Contains(currentOu.Id))
                    {
                        await RemoveFromOrganizationUnitAsync(user, currentOu);
                    }
                }
    
                //Add to added OUs
                foreach (var organizationUnitId in organizationUnitIds)
                {
                    if (currentOus.All(ou => ou.Id != organizationUnitId))
                    {
                        await AddToOrganizationUnitAsync(
                            user,
                            await _organizationUnitRepository.GetAsync(organizationUnitId)
                            );
                    }
                }
            }
    
            [UnitOfWork]
            public virtual Task<List<OrganizationUnit>> GetOrganizationUnitsAsync(TUser user)
            {
                var query = from uou in _userOrganizationUnitRepository.GetAll()
                            join ou in _organizationUnitRepository.GetAll() on uou.OrganizationUnitId equals ou.Id
                            where uou.UserId == user.Id
                            select ou;
    
                return Task.FromResult(query.ToList());
            }
    
            [UnitOfWork]
            public virtual Task<List<TUser>> GetUsersInOrganizationUnit(OrganizationUnit organizationUnit, bool includeChildren = false)
            {
                if (!includeChildren)
                {
                    var query = from uou in _userOrganizationUnitRepository.GetAll()
                                join user in Users on uou.UserId equals user.Id
                                where uou.OrganizationUnitId == organizationUnit.Id
                                select user;
    
                    return Task.FromResult(query.ToList());
                }
                else
                {
                    var query = from uou in _userOrganizationUnitRepository.GetAll()
                                join user in Users on uou.UserId equals user.Id
                                join ou in _organizationUnitRepository.GetAll() on uou.OrganizationUnitId equals ou.Id
                                where ou.Code.StartsWith(organizationUnit.Code)
                                select user;
    
                    return Task.FromResult(query.ToList());
                }
            }
    
            public virtual async Task InitializeOptionsAsync(int? tenantId)
            {
                Options = JsonConvert.DeserializeObject<IdentityOptions>(_optionsAccessor.Value.ToJsonString());
    
                //Lockout
                Options.Lockout.AllowedForNewUsers = await IsTrueAsync(AbpZeroSettingNames.UserManagement.UserLockOut.IsEnabled, tenantId);
                Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(await GetSettingValueAsync<int>(AbpZeroSettingNames.UserManagement.UserLockOut.DefaultAccountLockoutSeconds, tenantId));
                Options.Lockout.MaxFailedAccessAttempts = await GetSettingValueAsync<int>(AbpZeroSettingNames.UserManagement.UserLockOut.MaxFailedAccessAttemptsBeforeLockout, tenantId);
    
                //Password complexity
                Options.Password.RequireDigit = await GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.PasswordComplexity.RequireDigit, tenantId);
                Options.Password.RequireLowercase = await GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.PasswordComplexity.RequireLowercase, tenantId);
                Options.Password.RequireNonAlphanumeric = await GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.PasswordComplexity.RequireNonAlphanumeric, tenantId);
                Options.Password.RequireUppercase = await GetSettingValueAsync<bool>(AbpZeroSettingNames.UserManagement.PasswordComplexity.RequireUppercase, tenantId);
                Options.Password.RequiredLength = await GetSettingValueAsync<int>(AbpZeroSettingNames.UserManagement.PasswordComplexity.RequiredLength, tenantId);
            }
    
            protected virtual Task<string> GetOldUserNameAsync(long userId)
            {
                return AbpUserStore.GetUserNameFromDatabaseAsync(userId);
            }
    
            private async Task<UserPermissionCacheItem> GetUserPermissionCacheItemAsync(long userId)
            {
                var cacheKey = userId + "@" + (GetCurrentTenantId() ?? 0);
                return await _cacheManager.GetUserPermissionCache().GetAsync(cacheKey, async () =>
                {
                    var user = await FindByIdAsync(userId.ToString());
                    if (user == null)
                    {
                        return null;
                    }
    
                    var newCacheItem = new UserPermissionCacheItem(userId);
    
                    foreach (var roleName in await GetRolesAsync(user))
                    {
                        newCacheItem.RoleIds.Add((await RoleManager.GetRoleByNameAsync(roleName)).Id);
                    }
    
                    foreach (var permissionInfo in await UserPermissionStore.GetPermissionsAsync(userId))
                    {
                        if (permissionInfo.IsGranted)
                        {
                            newCacheItem.GrantedPermissions.Add(permissionInfo.Name);
                        }
                        else
                        {
                            newCacheItem.ProhibitedPermissions.Add(permissionInfo.Name);
                        }
                    }
    
                    return newCacheItem;
                });
            }
    
            public override async Task<IList<string>> GetValidTwoFactorProvidersAsync(TUser user)
            {
                var providers = new List<string>();
    
                foreach (var provider in await base.GetValidTwoFactorProvidersAsync(user))
                {
                    if (provider == "Email" &&
                        !await IsTrueAsync(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsEmailProviderEnabled, user.TenantId))
                    {
                        continue;
                    }
    
                    if (provider == "Phone" &&
                        !await IsTrueAsync(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsSmsProviderEnabled, user.TenantId))
                    {
                        continue;
                    }
    
                    providers.Add(provider);
                }
    
                return providers;
            }
    
            private bool IsTrue(string settingName, int? tenantId)
            {
                return GetSettingValue<bool>(settingName, tenantId);
            }
    
            private Task<bool> IsTrueAsync(string settingName, int? tenantId)
            {
                return GetSettingValueAsync<bool>(settingName, tenantId);
            }
    
            private T GetSettingValue<T>(string settingName, int? tenantId) where T : struct
            {
                return tenantId == null
                    ? _settingManager.GetSettingValueForApplication<T>(settingName)
                    : _settingManager.GetSettingValueForTenant<T>(settingName, tenantId.Value);
            }
    
            private Task<T> GetSettingValueAsync<T>(string settingName, int? tenantId) where T : struct
            {
                return tenantId == null
                    ? _settingManager.GetSettingValueForApplicationAsync<T>(settingName)
                    : _settingManager.GetSettingValueForTenantAsync<T>(settingName, tenantId.Value);
            }
    
            protected virtual string L(string name)
            {
                return LocalizationManager.GetString(LocalizationSourceName, name);
            }
    
            protected virtual string L(string name, CultureInfo cultureInfo)
            {
                return LocalizationManager.GetString(LocalizationSourceName, name, cultureInfo);
            }
    
            private int? GetCurrentTenantId()
            {
                if (_unitOfWorkManager.Current != null)
                {
                    return _unitOfWorkManager.Current.GetTenantId();
                }
    
                return AbpSession.TenantId;
            }
    
            private MultiTenancySides GetCurrentMultiTenancySide()
            {
                if (_unitOfWorkManager.Current != null)
                {
                    return MultiTenancy.IsEnabled && !_unitOfWorkManager.Current.GetTenantId().HasValue
                        ? MultiTenancySides.Host
                        : MultiTenancySides.Tenant;
                }
    
                return AbpSession.MultiTenancySide;
            }
    
            public virtual async Task AddTokenValidityKeyAsync(
                TUser user,
                string tokenValidityKey,
                DateTime expireDate,
                CancellationToken cancellationToken = default(CancellationToken))
            {
                await AbpUserStore.AddTokenValidityKeyAsync(user, tokenValidityKey, expireDate, cancellationToken);
            }
    
            public virtual async Task<bool> IsTokenValidityKeyValidAsync(
                TUser user,
                string tokenValidityKey,
                CancellationToken cancellationToken = default(CancellationToken))
            {
                return await AbpUserStore.IsTokenValidityKeyValidAsync(user, tokenValidityKey, cancellationToken);
            }
    
            public virtual async Task RemoveTokenValidityKeyAsync(
                TUser user,
                string tokenValidityKey,
                CancellationToken cancellationToken = default(CancellationToken))
            {
                await AbpUserStore.RemoveTokenValidityKeyAsync(user, tokenValidityKey, cancellationToken);
            }
        }
  • 相关阅读:
    dracut-initqueue timeout
    Request.Url
    ipv4 ipv6数据库存储
    DataRow To DataTable
    AS ShortCut
    linq on 多链接条件
    SQL逻辑查询语句执行顺序
    ckeditor 使用几点
    SqlDataAdapter 更新插入 与 InsertBulkCopy
    HTTP协议改HTTPS
  • 原文地址:https://www.cnblogs.com/topguntopgun/p/9583586.html
Copyright © 2020-2023  润新知