使身份核心选项可使用数据库配置
Make Identity core options configurable with database
我是 aspnet 核心的新手。我们正在使用身份核心 2.1。现在制作了一个页面,管理员可以从中设置不同的配置,例如空闲时间锁定时间密码重试。这些设置正在保存到数据库中 table。现在我希望我的身份选项将从这些值设置。我创建了一个存储库以从数据库中获取设置。但我无法从 startup.cs 调用该存储库函数。
可以请指导一下吗?并且还告诉我使身份选项可从数据库配置的最佳方法。
我做了一个服务
public class SecuritySettingService : ISecuritySettingService
{
private readonly ISecuritySettingRepository _securitySettingRepository;
public SecuritySettingService(ISecuritySettingRepository securitySettingRepository)
{
_securitySettingRepository = securitySettingRepository;
}
public SecuritySetting GetSecuritySetting()
{
return _securitySettingRepository.GetSecuritySetting();
}
}
连接数据库的存储库
public class SecuritySettingRepository : ISecuritySettingRepository
{
private readonly IDbRepository _dapperWrapper;
public SecuritySettingRepository(IDbRepository dapperWrapper)
{
_dapperWrapper = dapperWrapper;
}
public SecuritySetting GetSecuritySetting()
{
var response = _dapperWrapper.QuerySingleOrDefault<SecuritySetting>("security_setting_get", null, CommandType.StoredProcedure);
return response;
}
}
进行身份配置 class 以清理 startup.cs
public 静态 class IdentityConfig
{
public static void ConfigureIdentity(IServiceCollection 服务,ISecuritySettingService securitySettingService)
{
var securitySetting = securitySettingService.GetSecuritySetting();
services.AddIdentity<ApplicationUser, ApplicationRole>(options => {
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
}).AddUserManager<CustomUserManager>().AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
// Default User settings.
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = true;
});
services.Configure<DataProtectionTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromDays(30);
});
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(1);
options.LoginPath = "/login";
options.LogoutPath = "/logout";
options.Cookie = new CookieBuilder
{
IsEssential = true // required for auth to work without explicit user consent; adjust to suit your privacy policy
};
});
}
}
startup.cs 文件就像
public class Startup
{
public ISecuritySettingService _securitySettingService;
public Startup(IConfiguration configuration, ISecuritySettingService securitySettingService)
{
Configuration = configuration;
_securitySettingService = securitySettingService;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
IdentityConfig.ConfigureIdentity(services, _securitySettingService);
services.AddOptions();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
services.AddHttpContextAccessor();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
}
}
in startup.cs 当我调用 IdentityConfig.ConfigureIdentity(services, _securitySettingService);对象 _securitySettingService 不存在,所以我的代码抛出异常无效操作
对于您当前的错误,您是否注册了 ISecuritySettingService
并在 Startup
中使用了它。引用ISecuritySettingService
,需要先注册。
对于services.Configure<IdentityOptions>
,在更改数据库时不会自动更改。您需要自行更新 IdentityOptions
。
按照以下步骤并根据需要进行修改。
ISecuritySettingRepository
public interface ISecuritySettingRepository
{
LockoutOption GetSecuritySetting();
LockoutOption UpdateSecuritySetting(LockoutOption lockoutOption);
}
SecuritySettingRepository
public class SecuritySettingRepository : ISecuritySettingRepository
{
private readonly DbConnection _dapperWrapper;
private readonly IConfiguration _configuration;
public SecuritySettingRepository(DbConnection dapperWrapper
, IConfiguration configuration)
{
_dapperWrapper = dapperWrapper;
_configuration = configuration;
}
public LockoutOption GetSecuritySetting()
{
using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
{
string sQuery = "SELECT top 1 * From LockoutOption Where Id = 1";
var response = connection.QueryFirstOrDefault<LockoutOption>(sQuery);
return response;
}
}
public LockoutOption UpdateSecuritySetting(LockoutOption lockoutOption)
{
using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
{
string sQuery = $"Update LockoutOption Set MaxFailedAccessAttempts = {lockoutOption.MaxFailedAccessAttempts} Where Id = {lockoutOption.Id}";
var result = connection.Execute(sQuery);
string sQuery1 = "SELECT top 1 * From LockoutOption Where Id = 1";
var response = connection.QueryFirstOrDefault<LockoutOption>(sQuery1);
return response;
}
}
}
ISecuritySettingService
public interface ISecuritySettingService
{
LockoutOption GetSecuritySetting();
LockoutOption UpdateSecuritySetting(LockoutOption lockoutOption);
}
SecuritySettingService
public class SecuritySettingService : ISecuritySettingService
{
private readonly ISecuritySettingRepository _securitySettingRepository;
private readonly IdentityOptions _identityOptions;
public SecuritySettingService(ISecuritySettingRepository securitySettingRepository
, IOptions<IdentityOptions> identityOptions)
{
_securitySettingRepository = securitySettingRepository;
_identityOptions = identityOptions.Value;
}
public LockoutOption GetSecuritySetting()
{
return _securitySettingRepository.GetSecuritySetting();
}
public LockoutOption UpdateSecuritySetting(LockoutOption lockoutOption)
{
var option = _securitySettingRepository.UpdateSecuritySetting(lockoutOption);
//update identity options
_identityOptions.Lockout.MaxFailedAccessAttempts = option.MaxFailedAccessAttempts;
return option;
}
}
在Startup
中注册
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<DbConnection>(serviceProvider => new DbConnection(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
// your rest configure services
services.AddTransient<ISecuritySettingService, SecuritySettingService>();
services.AddTransient<ISecuritySettingRepository, SecuritySettingRepository>();
var _ecuritySettingService = services.BuildServiceProvider().GetRequiredService<ISecuritySettingService>();
services.Configure<IdentityOptions>(options =>
{
options.Lockout.MaxFailedAccessAttempts = _ecuritySettingService.GetSecuritySetting()?.MaxFailedAccessAttempts ?? 3;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//your configure
}
}
用法
namespace DapperPro.Controllers
{
public class LockoutOptionsController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IdentityOptions _identityOptions;
private readonly ISecuritySettingService _securitySettingService;
public LockoutOptionsController(ApplicationDbContext context
, IOptions<IdentityOptions> identityOptions
, ISecuritySettingService securitySettingService)
{
_context = context;
_identityOptions = identityOptions.Value;
_securitySettingService = securitySettingService;
}
// POST: LockoutOptions/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,AllowedForNewUsers,MaxFailedAccessAttempts,DefaultLockoutTimeSpan")] LockoutOption lockoutOption)
{
_securitySettingService.UpdateSecuritySetting(lockoutOption);
return View(lockoutOption);
}
}
}
我是 aspnet 核心的新手。我们正在使用身份核心 2.1。现在制作了一个页面,管理员可以从中设置不同的配置,例如空闲时间锁定时间密码重试。这些设置正在保存到数据库中 table。现在我希望我的身份选项将从这些值设置。我创建了一个存储库以从数据库中获取设置。但我无法从 startup.cs 调用该存储库函数。
可以请指导一下吗?并且还告诉我使身份选项可从数据库配置的最佳方法。
我做了一个服务
public class SecuritySettingService : ISecuritySettingService
{
private readonly ISecuritySettingRepository _securitySettingRepository;
public SecuritySettingService(ISecuritySettingRepository securitySettingRepository)
{
_securitySettingRepository = securitySettingRepository;
}
public SecuritySetting GetSecuritySetting()
{
return _securitySettingRepository.GetSecuritySetting();
}
}
连接数据库的存储库
public class SecuritySettingRepository : ISecuritySettingRepository
{
private readonly IDbRepository _dapperWrapper;
public SecuritySettingRepository(IDbRepository dapperWrapper)
{
_dapperWrapper = dapperWrapper;
}
public SecuritySetting GetSecuritySetting()
{
var response = _dapperWrapper.QuerySingleOrDefault<SecuritySetting>("security_setting_get", null, CommandType.StoredProcedure);
return response;
}
}
进行身份配置 class 以清理 startup.cs
public 静态 class IdentityConfig { public static void ConfigureIdentity(IServiceCollection 服务,ISecuritySettingService securitySettingService) {
var securitySetting = securitySettingService.GetSecuritySetting();
services.AddIdentity<ApplicationUser, ApplicationRole>(options => {
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
}).AddUserManager<CustomUserManager>().AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
// Default User settings.
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = true;
});
services.Configure<DataProtectionTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromDays(30);
});
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(1);
options.LoginPath = "/login";
options.LogoutPath = "/logout";
options.Cookie = new CookieBuilder
{
IsEssential = true // required for auth to work without explicit user consent; adjust to suit your privacy policy
};
});
}
}
startup.cs 文件就像
public class Startup
{
public ISecuritySettingService _securitySettingService;
public Startup(IConfiguration configuration, ISecuritySettingService securitySettingService)
{
Configuration = configuration;
_securitySettingService = securitySettingService;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
IdentityConfig.ConfigureIdentity(services, _securitySettingService);
services.AddOptions();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
services.AddHttpContextAccessor();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
}
}
in startup.cs 当我调用 IdentityConfig.ConfigureIdentity(services, _securitySettingService);对象 _securitySettingService 不存在,所以我的代码抛出异常无效操作
对于您当前的错误,您是否注册了 ISecuritySettingService
并在 Startup
中使用了它。引用ISecuritySettingService
,需要先注册。
对于services.Configure<IdentityOptions>
,在更改数据库时不会自动更改。您需要自行更新 IdentityOptions
。
按照以下步骤并根据需要进行修改。
ISecuritySettingRepository
public interface ISecuritySettingRepository { LockoutOption GetSecuritySetting(); LockoutOption UpdateSecuritySetting(LockoutOption lockoutOption); }
SecuritySettingRepository
public class SecuritySettingRepository : ISecuritySettingRepository { private readonly DbConnection _dapperWrapper; private readonly IConfiguration _configuration; public SecuritySettingRepository(DbConnection dapperWrapper , IConfiguration configuration) { _dapperWrapper = dapperWrapper; _configuration = configuration; } public LockoutOption GetSecuritySetting() { using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection"))) { string sQuery = "SELECT top 1 * From LockoutOption Where Id = 1"; var response = connection.QueryFirstOrDefault<LockoutOption>(sQuery); return response; } } public LockoutOption UpdateSecuritySetting(LockoutOption lockoutOption) { using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection"))) { string sQuery = $"Update LockoutOption Set MaxFailedAccessAttempts = {lockoutOption.MaxFailedAccessAttempts} Where Id = {lockoutOption.Id}"; var result = connection.Execute(sQuery); string sQuery1 = "SELECT top 1 * From LockoutOption Where Id = 1"; var response = connection.QueryFirstOrDefault<LockoutOption>(sQuery1); return response; } } }
ISecuritySettingService
public interface ISecuritySettingService { LockoutOption GetSecuritySetting(); LockoutOption UpdateSecuritySetting(LockoutOption lockoutOption); }
SecuritySettingService
public class SecuritySettingService : ISecuritySettingService { private readonly ISecuritySettingRepository _securitySettingRepository; private readonly IdentityOptions _identityOptions; public SecuritySettingService(ISecuritySettingRepository securitySettingRepository , IOptions<IdentityOptions> identityOptions) { _securitySettingRepository = securitySettingRepository; _identityOptions = identityOptions.Value; } public LockoutOption GetSecuritySetting() { return _securitySettingRepository.GetSecuritySetting(); } public LockoutOption UpdateSecuritySetting(LockoutOption lockoutOption) { var option = _securitySettingRepository.UpdateSecuritySetting(lockoutOption); //update identity options _identityOptions.Lockout.MaxFailedAccessAttempts = option.MaxFailedAccessAttempts; return option; } }
在
Startup
中注册public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddTransient<DbConnection>(serviceProvider => new DbConnection(Configuration.GetConnectionString("DefaultConnection"))); services.AddMvc(); // your rest configure services services.AddTransient<ISecuritySettingService, SecuritySettingService>(); services.AddTransient<ISecuritySettingRepository, SecuritySettingRepository>(); var _ecuritySettingService = services.BuildServiceProvider().GetRequiredService<ISecuritySettingService>(); services.Configure<IdentityOptions>(options => { options.Lockout.MaxFailedAccessAttempts = _ecuritySettingService.GetSecuritySetting()?.MaxFailedAccessAttempts ?? 3; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { //your configure } }
用法
namespace DapperPro.Controllers { public class LockoutOptionsController : Controller { private readonly ApplicationDbContext _context; private readonly IdentityOptions _identityOptions; private readonly ISecuritySettingService _securitySettingService; public LockoutOptionsController(ApplicationDbContext context , IOptions<IdentityOptions> identityOptions , ISecuritySettingService securitySettingService) { _context = context; _identityOptions = identityOptions.Value; _securitySettingService = securitySettingService; } // POST: LockoutOptions/Edit/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(int id, [Bind("Id,AllowedForNewUsers,MaxFailedAccessAttempts,DefaultLockoutTimeSpan")] LockoutOption lockoutOption) { _securitySettingService.UpdateSecuritySetting(lockoutOption); return View(lockoutOption); } } }