[英]How to handle static classes running in the same context scope in ASP.Net Core?
在以下示例中,我有一个控制器,该控制器生成密钥串行ID并加密一些敏感信息,例如SSN。 我在静态类中有函数,可以在项目的任何地方调用它们。 这两个类都在相同的上下文中运行并运行SP。 我认为问题就在于此。
startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ARTNetCore")));
services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
config.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.Configure<SMSoptions>(Configuration);
services.AddMvc();
// Configure Identity
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.AllowedForNewUsers = true;
services.AddCookieAuthentication(o =>
{
o.LoginPath = "/Account/LogIn";
o.LogoutPath = "/Account/LogOut";
});
// User settings
options.User.RequireUniqueEmail = true;
});
services.Configure<AuthMessageSenderOptions>(Configuration);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var options = new RewriteOptions()
.AddRedirectToHttps();
app.UseRewriter(options);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
//Comment when migrating or demigrating
//SeedData.Initialize(app.ApplicationServices);
}
控制器是
private readonly ApplicationDbContext _context;
public PatRegController(ApplicationDbContext context)
{
_context = context;
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("FName,MName,LName,Dob,GenrId,StasId,NatyId,MarsId,CouyId,StaeId,CityId,OccnId,Email,SNN,PassNo,MobNo,LLine,MAdds,StrtNo,SDirn,AptNo,Locy,ALevl,PCode,Couy,ProeId")] PatReg patReg)
{
if (ModelState.IsValid)
{
patReg.FileId = DbSerializerHandler.SerializeFileId(_context);
patReg.SNN = DbEncryptionHandler.DynamicEncrypt(patReg.SNN, _context);
_context.Add(patReg);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(patReg);
}
加密静态类为
public static class DbEncryptionHandler
{
public static string DynamicEncrypt(string clearText, ApplicationDbContext _context)
{
try
{
if (!string.IsNullOrWhiteSpace(clearText))
{
List<EncKeys> Keys = new List<EncKeys>();
Keys = _context.EncKeys.FromSql("EncKeysSP").ToList();
string EncryptionKey = Keys[0].DynamicKey;
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
}
else
{
clearText = null;
}
}
catch (Exception ex)
{
throw;
}
return clearText;
}
}
并且Serializer静态类是
public static class DbSerializerHandler
{
public static Int64 SerializeFileId(ApplicationDbContext _context)
{
List<FileIdSeq> NewFileSeq = new List<FileIdSeq>();
NewFileSeq = _context.FileIdSeq.FromSql("FileIdSeqSP").ToList();
var FileID = NewFileSeq[0].LastSequence;
return FileID;
}
}
当我尝试保存数据时,出现此错误
处理请求时发生未处理的异常。
SqlException:不允许新事务,因为会话中正在运行其他线程。 System.Data.SqlClient.SqlConnection.OnError(SqlException异常,bool breakConnection,操作wrapCloseInAction)
错误在此控制器行上返回, await _context.SaveChangesAsync();
我在这里做错了什么?
更新检查后,我一次只能运行这些功能之一,但不能一次运行。
DbEncryptionHandler
和DbSerializerHandler
类不需要依赖于ApplicationDbContext
,而只需依赖它们所需的数据即可。
public static class DbEncryptionHandler
{
public static string DynamicEncrypt(string clearText, IEnumerable<EncKeys> keys)
{
...
}
}
public static class DbSerializerHandler
{
public static Int64 SerializeFileId(IEnumerable<FileIdSeq> seq)
{
...
}
}
在使用静态类之前,您可以在控制器中从上下文中获取数据。
public async Task<IActionResult> Create(PatReg patReg)
{
if (ModelState.IsValid)
{
var seq = await _context.FileIdSeq.FromSql("FileIdSeqSP").ToListAsync();
var keys = await _context.EncKeys.FromSql("EncKeysSP").ToListAsync();
patReg.FileId = DbSerializerHandler.SerializeFileId(seq);
patReg.SNN = DbEncryptionHandler.DynamicEncrypt(patReg.SNN, keys);
_context.Add(patReg);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(patReg);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.