我使用内置的身份框架进行用户管理,并希望为AspNetUsers表添加一些自定义.到目前为止,我遇到的每个问题的解决方案都会导致另一个问题.
如果我更改用户模型(例如,通过在AspNetUsers表中添加邮政编码属性和匹配字段),然后调用UserManager.UpdateAsync(用户),它会成功,但不会更新数据库中的邮政编码字段.
至少有一个其他的SO问题试图解决这个问题.但建议修复那里打破其他事情:
1)创建UserDbContext的另一个实例并尝试附加用户对象导致实体框架抱怨"实体对象不能被IEntityChangeTracker的多个实例引用"
2)关闭代理创建摆脱了#1中列出的问题,但导致dbcontext不加载子对象(如AspNetUserLogins,这是非常重要的).
另一种解决方案是访问在Controller中创建的上下文.使用MVC(版本5)模板考虑使用新的ASP .NET Web应用程序的默认AccountController的构造函数方法:
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
Run Code Online (Sandbox Code Playgroud)
创建应用程序数据库上下文,但无法通过UserManager访问它(因为UserManager的"存储"私有属性).
这看起来不像是火箭科学,所以我的猜测是我在处理/理解dbcontext生命周期时做了一些基本上错误的事情.
那么:我如何正确访问/使用dbcontext来保存和更新AspNetUsers,关联的自定义属性以及保留子对象(如AspNetUserLogins)?
编辑-------
还有一件事我试过......
我从默认更新了AccountController的构造函数:
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
Run Code Online (Sandbox Code Playgroud)
对此:
public AccountController(UserManager<ApplicationUser> userManager)
{
userDbContext= new UserDbContext();
UserStore<ApplicationUser> store = new UserStore<ApplicationUser>();
UserManager<ApplicationUser> manager = new UserManager<ApplicationUser>(store);
manager.UserValidator = new CustomUserValidator<ApplicationUser>(UserManager);
// UserManager = userManager;
UserManager = manager;
}
Run Code Online (Sandbox Code Playgroud)
试图挂起dbcontext.后来,在公共异步任务方法的主体中,我试图调用:
var updated = await UserManager.UpdateAsync(user);
if …Run Code Online (Sandbox Code Playgroud) 编辑:在评论中的每次讨论中,让我澄清一下,这将发生在SSL后面的服务器端.我不打算将散列密码或散列方案暴露给客户端.
假设我们有一个现有的asp.net身份数据库,其中包含默认表(aspnet_Users,aspnet_Roles等).根据我的理解,密码哈希算法使用sha256并将salt +(哈希密码)存储为base64编码的字符串.编辑:这个假设不正确,请参阅下面的答案.
我想用JavaScript版本复制Microsoft.AspNet.Identity.Crypto类' VerifyHashedPassword函数的功能.
假设密码是welcome1,其asp.net散列密码为 ADOEtXqGCnWCuuc5UOAVIvMVJWjANOA/LoVy0E4XCyUHIfJ7dfSY0Id + uJ20DTtG + A ==
到目前为止,我已经能够重现获取salt和存储的子键的方法部分.
C#实现或多或少地执行此操作:
var salt = new byte[SaltSize];
Buffer.BlockCopy(hashedPasswordBytes, 1, salt, 0, SaltSize);
var storedSubkey = new byte[PBKDF2SubkeyLength];
Buffer.BlockCopy(hashedPasswordBytes, 1 + SaltSize, storedSubkey, 0, PBKDF2SubkeyLength);
Run Code Online (Sandbox Code Playgroud)
我在JavaScript中有以下内容(任何方面都不优雅):
var hashedPwd = "ADOEtXqGCnWCuuc5UOAVIvMVJWjANOA/LoVy0E4XCyUHIfJ7dfSY0Id+uJ20DTtG+A==";
var hashedPasswordBytes = new Buffer(hashedPwd, 'base64');
var saltbytes = [];
var storedSubKeyBytes = [];
for(var i=1;i<hashedPasswordBytes.length;i++)
{
if(i > 0 && i <= 16)
{
saltbytes.push(hashedPasswordBytes[i]);
}
if(i > 0 && i >16) { …Run Code Online (Sandbox Code Playgroud) 考虑来自WinForms应用程序的此代码示例:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
object[] parms = new object[1];
parms[0] = "foo";
DoSomething(parms);
}
public static string DoSomething(object[] parms)
{
Console.WriteLine("Something good happened");
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
它按预期工作,当您单击button1时,它会向控制台输出"Something good occurred".
现在考虑这个代码示例,除了它DoSomething使用反射调用之外是相同的:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
object[] parms = new object[1];
parms[0] = "foo";
System.Reflection.MethodInfo mi …Run Code Online (Sandbox Code Playgroud) 我想使用 Puppeteer 在输入字段中输入一个值。根据文档,这似乎很简单(文档中的示例):
await page.type('#mytextarea', 'Hello'); // Types instantly
await page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
Run Code Online (Sandbox Code Playgroud)
所以我创建了以下测试脚本:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({headless: false}); // devtools: true
const page = await browser.newPage();
await page.goto('https://mycoolsite/index.html');
page.on('console', msg => console.log(new Date().toISOString() + ' ' + msg._text));
const selector = '#barcode';
await page.waitForSelector(selector);
await page.type(selector, "1234");
})();
Run Code Online (Sandbox Code Playgroud)
它一直工作到 page.type() 行。意思是,它启动一个 Chromium 实例,转到正确的 URL,在日志中显示控制台的预期输出。但不在字段中键入值。我在节点输出或浏览器控制台输出中没有看到任何错误。
为了排除静默失败,我将选择器名称更改为不存在的名称(例如“#qwertyuiop”),并按预期失败。
await page.type(selector, "1234");如果我用以下内容替换该行,我找到了解决方法:
const element …Run Code Online (Sandbox Code Playgroud) c# ×3
asp.net-mvc ×1
cryptojs ×1
invoke ×1
javascript ×1
puppeteer ×1
reflection ×1
rfc2898 ×1