.net core 使用IUserClaimsPrincipalFactory向标识添加其他声明

.net core 使用IUserClaimsPrincipalFactory向标识添加其他声明,.net-core,asp.net-core-webapi,claims-based-identity,asp.net-core-3.1,.net Core,Asp.net Core Webapi,Claims Based Identity,Asp.net Core 3.1,我试图使用IUserClaimsPrincipalFactory为身份添加一些附加声明。我创建了一个新类,该类扩展了接口IUserClaimsPrincipalFactory并重写了CreateAync。我相应地配置了服务。在我的需求处理程序中,我正在寻找那个声明,但它并不存在。这可能是一件非常愚蠢的事情,但我一直无法理解为什么它不起作用。我查看了Microsoft在“将自定义用户数据添加到标识”页面底部提供的功能,但没有任何帮助 AddPermissiontoClaim类 public cla

我试图使用IUserClaimsPrincipalFactory为身份添加一些附加声明。我创建了一个新类,该类扩展了接口IUserClaimsPrincipalFactory并重写了CreateAync。我相应地配置了服务。在我的需求处理程序中,我正在寻找那个声明,但它并不存在。这可能是一件非常愚蠢的事情,但我一直无法理解为什么它不起作用。我查看了Microsoft在“将自定义用户数据添加到标识”页面底部提供的功能,但没有任何帮助

AddPermissiontoClaim类

public class AddPermissiontoClaim : UserClaimsPrincipalFactory<ApiUser, IdentityRole>
{
    public AddPermissiontoClaim(
  UserManager<ApiUser> userManager,
  RoleManager<IdentityRole> roleManager,
  IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
    {
    }

    public async override Task<ClaimsPrincipal> CreateAsync(ApiUser user)
    {
        var principal = await base.CreateAsync(user);
        var identity = (ClaimsIdentity)principal.Identity;

        var claims = new List<Claim>()
        {
            new Claim("Permissions", "Read")
        };
        identity.AddClaims(claims);
        return principal;
    }
}
公共类AddPermissiontoClaim:UserClaimsPrincipalFactory
{
公共添加许可证索赔(
用户管理器用户管理器,
RoleManager RoleManager,
IOOptions Accessor):基本(用户管理器、角色管理器、Options Accessor)
{
}
公共异步覆盖任务CreateAync(ApiUser用户)
{
var principal=await base.CreateAsync(用户);
var identity=(ClaimsIdentity)principal.identity;
var索赔=新列表()
{
新声明(“权限”、“读取”)
};
身份。添加索赔(索赔);
返还本金;
}
}
在启动类中注册类。

   public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddDbContext<ApiUserIdentityDbContext>(opt =>{
            opt.UseSqlServer(Configuration.GetConnectionString("DefaultConStr"));
        });
        
       services.AddAutoMapper(typeof(MappingProfiles));
       services.AddScoped<ICustomer,CustomerRepository>();
       services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
       services.AddScoped<IUnitOfWork, UnitOfWork>();
        services.Configure<ApiBehaviorOptions>(opt => {
            opt.InvalidModelStateResponseFactory = context => {
                var errors = context.ModelState
                .Where(v => v.Value.Errors.Count() > 0)
                .SelectMany(x => x.Value.Errors)
                .Select(v => v.ErrorMessage);
                var error = new ApiValidationError {
                    Errors = errors
                };
                return new BadRequestObjectResult(error);
            };
        });
        services.AddDefaultIdentity<ApiUser>()
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<ApiUserIdentityDbContext>();


        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(opt => {
            opt.TokenValidationParameters = new TokenValidationParameters
            {
              ValidateIssuerSigningKey = true,
              IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Token:Key"])),
              ValidateAudience = true,
              ValidateIssuer = true,
              ValidAudience = Configuration["Token:Audience"],
              ValidIssuer   = Configuration["Token:Issuer"]
            };
        });

        services.AddScoped<ITokenService, TokenService>();

        services.AddScoped<IUserClaimsPrincipalFactory<ApiUser>, AddPermissiontoClaim>();
        services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
    }
public void配置服务(IServiceCollection服务)
{
services.AddControllers();
services.AddDbContext(opt=>{
opt.UseSqlServer(Configuration.GetConnectionString(“DefaultConStr”);
});
AddAutoMapper(类型(映射配置文件));
services.addScope();
服务.addScope(typeof(IGenericRepository)、typeof(genericpository));
services.addScope();
services.Configure(opt=>{
opt.InvalidModelStateResponseFactory=上下文=>{
var errors=context.ModelState
.Where(v=>v.Value.Errors.Count()>0)
.SelectMany(x=>x.Value.Errors)
.选择(v=>v.ErrorMessage);
var error=新的ApiValidationError{
错误=错误
};
返回新的BadRequestObjectResult(错误);
};
});
services.AddDefaultIdentity()
.AddRoles()
.AddEntityFrameworkStores();
services.AddAuthentication(x=>
{
x、 DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;
x、 DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(opt=>{
opt.TokenValidationParameters=新的TokenValidationParameters
{
ValidateSuersigningKey=true,
IssuerSigningKey=new-SymmetricSecurityKey(Encoding.UTF8.GetBytes(配置[“令牌:密钥])),
ValidateAudience=true,
validateisuer=true,
Validudience=配置[“令牌:受众”],
ValidisUser=配置[“令牌:颁发者”]
};
});
services.addScope();
services.addScope();
services.AddSingleton();
}
需求处理程序

public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
        {
            var permissionsClaim = context.User.Claims.SingleOrDefault(c => c.Type == "Permissions");

        if (permissionsClaim == null)
            return Task.CompletedTask;

        //TODO

        if (permissionsClaim.Value.ThisPermissionAllowed(requirement.Name))
            context.Succeed(requirement);

        return Task.CompletedTask;
    }
}
公共类PermissionHandler:AuthorizationHandler { 受保护的覆盖任务HandleRequirementAsync(授权HandlerContext上下文,许可要求) { var permissionsClaim=context.User.Claims.SingleOrDefault(c=>c.Type==“Permissions”); if(permissionsClaim==null) 返回Task.CompletedTask; //待办事项 if(permissionsLaim.Value.ThisPermissionAllowed(requirement.Name)) 成功(要求); 返回Task.CompletedTask; } } 更新:

目标是完成与下面的中间件类似的工作。除了需要访问数据库并获取要添加到声明中的权限列表之外,它与中间件配合良好

public class AddClaimsMiddleware
{
    private readonly RequestDelegate _next;
    public AddClaimsMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        if(httpContext.User.Identity.IsAuthenticated)
        {
            var claims = new List<Claim>
            {
                new Claim(PermissionConstant.PackedPermissionType, "Admin")
            };
            var appIdentity = new ClaimsIdentity(claims);
            httpContext.User.AddIdentity(appIdentity);
            await _next(httpContext);
        }
    }
}
public类addclaimsmiddle软件
{
private readonly RequestDelegate\u next;
公共AddClaimsMiddleware(RequestDelegate下一步)
{
_下一个=下一个;
}
公共异步任务InvokeAsync(HttpContext HttpContext)
{
if(httpContext.User.Identity.IsAuthenticated)
{
var索赔=新列表
{
新声明(PermissionConstant.PackedPermissionType,“Admin”)
};
var appIdentity=新的索赔实体(索赔);
httpContext.User.AddIdentity(appIdentity);
等待下一步(httpContext);
}
}
}

您应该将
AddPermissiontoClaim
ClaimTypes
与需求处理程序中的类型保持一致。检查更多详细信息。@MichaelWang我做了更改。索赔仍然不存在。我在需求中放置了一个断点,并检查其中有哪些声明。它没有权限声明。您似乎从未添加权限声明。跟随检查。@MichaelWang感谢您的帮助。我看到了这些台阶。事实上,我将示例代码复制到项目中,得到了相同的结果。我不得不将ApplicationUser更改为ApiUser,因为它继承自IdentityUser。当我检查索赔时,它有8澳元,iss,nbf,exp,iat,电子邮件地址,出生日期,givenname。管理员不是其中之一。我将创建一个全新的项目,这样我就可以处理这个问题。你应该让你的
AddPermissiontoClaim的
ClaimTypes
与需求处理程序中的类型保持一致。检查更多详细信息。@MichaelWang我做了更改。索赔仍然不存在。我在需求中放置了一个断点,并检查其中有哪些声明。它没有权限声明。您似乎从未添加权限声明。跟随检查。@MichaelWang感谢您的帮助。我看到了这些台阶。事实上,我将示例代码复制到项目中,得到了相同的结果。我不得不去看电影