C# .NET核心自定义授权依赖项注入
我们有一个定制的授权方案,我正试图通过在.NETCore中进行单元测试和使用依赖注入来解决这个方案。让我解释一下设置: 我创建了一个接口IStsHttpClient和类StsHttpClient。此类连接到创建和解码令牌的内部web服务。这正好有一个方法“DecodeToken(string token)”,构造函数非常简单——它接受从DI加载的option对象 然后,我的AuthorizationHandler理论上只使用IStsHttpClient调用和解码令牌。我的问题是,基于在线示例,我不知道如何正确指定/构建授权处理程序(请参见下面的代码) 此处的身份验证代码:C# .NET核心自定义授权依赖项注入,c#,dependency-injection,authorization,asp.net-core-webapi,C#,Dependency Injection,Authorization,Asp.net Core Webapi,我们有一个定制的授权方案,我正试图通过在.NETCore中进行单元测试和使用依赖注入来解决这个方案。让我解释一下设置: 我创建了一个接口IStsHttpClient和类StsHttpClient。此类连接到创建和解码令牌的内部web服务。这正好有一个方法“DecodeToken(string token)”,构造函数非常简单——它接受从DI加载的option对象 然后,我的AuthorizationHandler理论上只使用IStsHttpClient调用和解码令牌。我的问题是,基于在线示例,我
public class MyAuthorizationRequirement : AuthorizationHandler<MyAuthorizationRequirement >, IAuthorizationRequirement
{
const string Bearer = "Bearer ";
readonly IStsHttpClient _client;
public BuzzStsAuthorizationRequirement([FromServices]IStsHttpClient client)
{
_client = client;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, MyStsAuthorizationRequirement requirement)
{
/* remaining code omitted - but this will call IStsHttpClient.Decode() */
公共类MyAuthorizationRequirement:AuthorizationHandler,IAAuthorizationRequirement
{
const string Bearer=“Bearer”;
只读IStsHttpClient\u客户端;
公共BuzzsTSA授权要求([FromServices]ISTSHTPClient客户端)
{
_客户=客户;
}
受保护的重写异步任务HandleRequirementAsync(授权HandlerContext上下文,MySTSAuthorizationRequirementAsync)
{
/*省略其余代码-但这将调用IStsHttpClient.Decode()*/
我的Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<StsHttpOptions>(Configuration.GetSection("StsConfigurationInfo"));
services.AddScoped<IStsHttpClient , StsHttpClient >();
services.AddAuthorization(options =>
{
options.AddPolicy("Authorize", policy =>
{
/* initialize this differently?? */
policy.AddRequirements(new MyStsAuthorizationRequirement( /* somethign is needed here?? */));
});
});
services.AddDbContext<PokeflexContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<PokeflexContext>()
.AddUserManager<UserManager<IdentityUser>>()
.AddDefaultTokenProviders();
public void配置服务(IServiceCollection服务)
{
services.Configure(Configuration.GetSection(“StsConfigurationInfo”);
services.addScope();
services.AddAuthorization(选项=>
{
options.AddPolicy(“授权”,策略=>
{
/*以不同的方式初始化它*/
policy.AddRequirements(新的mystAuthorizationRequirements(/*此处需要一些符号??*/);
});
});
尼古拉斯
您必须在此处分离处理程序和需求。此外,将DI内容保留在处理程序中。需求本身将是DTO或带有标记接口IAuthorizationRequirement的空类
要求:
public class MyAuthorizationRequirement : IAuthorizationRequirement
{
}
处理程序:
public class MyAuthorizationHandler : AuthorizationHandler<MyAuthorizationRequirement>
{
const string Bearer = "Bearer ";
readonly IStsHttpClient _client;
public BuzzStsAuthorizationRequirement([FromServices]IStsHttpClient client)
{
_client = client;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, MyAuthorizationRequirement requirement)
{
...
}
}
公共类MyAuthorizationHandler:AuthorizationHandler
{
const string Bearer=“Bearer”;
只读IStsHttpClient\u客户端;
公共BuzzsTSA授权要求([FromServices]ISTSHTPClient客户端)
{
_客户=客户;
}
受保护的重写异步任务HandleRequirementAsync(AuthorizationHandlerContext上下文,MyAuthorizationRequirementAsync)
{
...
}
}
配置:
services.Configure<StsHttpOptions>(Configuration.GetSection("StsConfigurationInfo"));
services.AddScoped<IStsHttpClient , StsHttpClient >();
services.AddAuthorization(options =>
{
options.AddPolicy("Authorize", policy =>
{
policy.AddRequirements(new MyAuthorizationRequirement());
});
});
services.Configure(Configuration.GetSection(“StsConfigurationInfo”);
services.addScope();
services.AddAuthorization(选项=>
{
options.AddPolicy(“授权”,策略=>
{
policy.AddRequirements(新的MyAuthorizationRequirements());
});
});
对于其他希望在C#9 NetCore5中围绕现有权限处理程序包装授权的人,我找到了以下解决方案,允许我使用stock dependency injection容器将服务注入AuthorizationHandler
对我来说,这需要5个新类和对Startup.cs的一些更改
public void ConfigureServices(IServiceCollection services)
{
services.Configure<StsHttpOptions>(Configuration.GetSection("StsConfigurationInfo"));
services.AddScoped<IStsHttpClient , StsHttpClient >();
services.AddAuthorization(options =>
{
options.AddPolicy("Authorize", policy =>
{
/* initialize this differently?? */
policy.AddRequirements(new MyStsAuthorizationRequirement( /* somethign is needed here?? */));
});
});
services.AddDbContext<PokeflexContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<PokeflexContext>()
.AddUserManager<UserManager<IdentityUser>>()
.AddDefaultTokenProviders();
以下是my PermissionPolicyProvider.cs,这将表示一般权限,而不是策略(稍后我将筛选权限)
使用系统数据;
使用System.Threading.Tasks;
使用App.Models;
使用App.Services.Permissions;
使用Microsoft.AspNetCore.Authorization;
使用Microsoft.AspNetCore.Identity;
名称空间应用程序权限
{
类PermissionAuthorizationHandler:AuthorizationHandler
{
private readonly AppUserManager在这之后的一两天,我终于意识到我可以使用中间件来做我想做的事情。什么是BuzzStsAuthorizationRequirement
?它似乎是一个没有返回类型的方法。不能是构造函数。
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace App.Permissions
{
public class AppUserManager<TUser> : UserManager<TUser> where TUser : class
{
public IServiceProvider Services;
public AppUserManager(IUserStore<TUser> store,
IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<TUser> passwordHasher,
IEnumerable<IUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators,
ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors,
IServiceProvider services, ILogger<UserManager<TUser>> logger)
: base(store, optionsAccessor, passwordHasher, userValidators,
passwordValidators, keyNormalizer, errors, services, logger)
{
Services = services;
}
}
}
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace App.Permissions
{
public class AppUserManager<TUser> : UserManager<TUser> where TUser : class
{
public IServiceProvider Services;
public AppUserManager(IUserStore<TUser> store,
IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<TUser> passwordHasher,
IEnumerable<IUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators,
ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors,
IServiceProvider services, ILogger<UserManager<TUser>> logger)
: base(store, optionsAccessor, passwordHasher, userValidators,
passwordValidators, keyNormalizer, errors, services, logger)
{
Services = services;
}
}
}
services.AddDbContext<PokeflexContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddTransient<PermissionService>();
services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
services.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<PokeflexContext>()
.AddUserManager<AppUserManager<AppUser>>()
.AddDefaultTokenProviders();
services.AddScoped(s => s.GetService<AppUserManager<AppUser>>());
using System.Threading.Tasks;
using App.Data;
using Microsoft.EntityFrameworkCore;
namespace App.Services.Permissions
{
public class PermissionService
{
private PokeflexContext _dbContext;
public PermissionService(PokeflexContext dbContext)
{
_dbContext = dbContext;
}
public virtual async Task<bool> Permitted(string permission)
{
return await _dbContext.AppUsers.AnyAsync();
}
}
}