.net core 基于AspNetCore.Identity+Identityserver4用户的权限管理

一般权限控制,是先给角色分配对应权限,然后再给用户分配角色;总权限应该是在代码编写的时候就已经固定了,例如有个用户更新的接口,这里就会诞生一个用户更新的权限,接口在权限就在,没有接口也就没有了这个权限;

所以总权限我是维护在代码中静态常量,在AuthorizeAttribute中设置权限也是要常量;

使用原生AuthorizeAttribute的Policy和用户的Claim(有userClaim和roleClaim),userClaim和roleClaim是AspNetCore.Identity的表,保存用户的声明信息和角色声明信息,也就是可以在roleClaim中保存角色的权限;

用户登录后获取token,token经过ProfileService处理,带有用户的权限Claim,用户请求需要权限的接口时,会检查token中有没有这个权限要求的Claim;

分为两个服务,一个Identityserver4服务,一个UserAPI服务;

Identityserver4服务

ConfigureServices

string mysqlConnectionStrings = $"Data Source={Host};port={Port};Initial Catalog={Database};user id={UserID};password={Password};";
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySql(mysqlConnectionStrings));

services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.Ids)
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients(Configuration))
.AddAspNetIdentity<ApplicationUser>()
//.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
.AddProfileService<ProfileService>();
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
需要注意ProfileService,这里返回token中Claim,去数据库获取用户的Claim
        /// <summary>
        /// This method is called whenever claims about the user are requested (e.g. during token creation or via the userinfo endpoint)
        /// 
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public virtual async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var sub = context.Subject?.GetSubjectId();
            //context.Subject.Claims  为登录设置的Claims,此处直接用数据库中的claims,忽略context.Subject.Claims
            if (sub == null) throw new Exception("No sub claim present");

            var user = await _userServer.FindByIdAsync(sub);
            if (user == null)
            {
                Logger?.LogWarning("No user found matching subject Id: {0}", sub);
            }
            else
            {
          //获取用户的权限
var userPermissions = await _rolePermissionServer.GetUserPermissions(user.Id); List<Claim> claims = new List<Claim>(); claims = userPermissions.Select(a => new Claim("UserPermission", a.NormalizedName)).ToList(); claims.Add(new Claim("username", user.UserName)); claims.Add(new Claim("name", user.Name)); context.IssuedClaims = claims; } }

UserAPI服务

UserApi服务除了正常的配置Identityserver4服务以外,还需要添加认证需要的Policy,因为权限都需要认证,所以我把所有的权限都加进去;

      
        //获取所有的权限列表
        var
permissionsList = PermissionNames.GetPermissionsList(); //设置Authorize的policy,可以添加多个 services.AddAuthorization(options => { foreach (var item in permissionsList) { options.AddPolicy(item.NormalizedName, policyAdmin => { policyAdmin.RequireClaim("UserPermission", item.NormalizedName); }); } });

下面两个中间件也不能忘记

app.UseAuthentication();
app.UseAuthorization();

接下来是Controller部分

        [HttpGet]
        [Route("manage")]
        [Authorize(PermissionNames.UserManage_list)]
        public async Task<PageBase<UserListItemDto>> UserManageList([FromQuery]UserListRequestDto request)
        {
            return await _userServer.UserManageList(request);
        }
        [HttpGet]
        [Route("manage/{id}")]
        [Authorize(PermissionNames.UserManage_detail)]
        public async Task<UserDetailDto> UserManageDetail(int id)
        {
            return await _userServer.UserManageDetail(id);
        }
        [HttpPut]
        [Route("manage")]
        [Authorize(PermissionNames.UserManage_update)]
        public async Task<bool> UserManageUpdate(UserEditDto  userEditDto)
        {
            return await _userServer.UserManageUpdate(UserId, userEditDto);
        }
        [HttpDelete]
        [Route("manage/{id}")]
        [Authorize(PermissionNames.UserManage_delete)]
        public async Task<bool> UserManageDelete(int id)
        {
            return await _userServer.UserManageDelete(UserId, id);
        }

具体代码,还有更多内容学习:https://github.com/zhanghm1/DiuDiuTemplate

原文地址:https://www.cnblogs.com/zhanghm1/p/12894042.html