ASP.NET 零和外部认证
ASP.NET Zero and external authentication
我们将用 Node.js 编写的旧 Web 应用程序迁移到 ASP.NET 零。我们必须保留所有用户及其密码,以便他们仍然能够登录。使用 bcrypt 对密码进行哈希处理。
计划如下:当用户在迁移后首次登录时,我们授权 him/her 反对 brypt 密码,如果密码有效,我们使用
_userManager.PasswordHasher.HashPassword(user, plainPassword)
并将其保存为 his/her 密码。下次该用户想要登录时,将调用标准 ASP.NET 零函数来实现此目的。
第一部分 - bcrypt 工作得很好,但我不知道如何使用标准机制来验证用户。这是我目前所拥有的:
private readonly IRepository<User, long> _userRepository;
private readonly SignInManager<User> _signInManager;
private readonly UserManager _userManager;
public AltAuthSource(IRepository<User, long> userRepository, UserManager userManager, SignInManager<User> signInManager)
{
_userRepository = userRepository;
_userManager = userManager;
_signInManager = signInManager;
}
public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
{
var user = _userRepository.GetAll().FirstOrDefault(x => x.UserName.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase) || x.EmailAddress.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase));
if (user == null)
{
return Task.FromResult(false);
}
else
{
if (string.IsNullOrWhiteSpace(user.Password))
{
var passwordOk = BCrypt.Net.BCrypt.Verify(plainPassword, user.PasswordOrig);
if (passwordOk)
{
_userManager.ResetAccessFailedCountAsync(user);
var newHash = _userManager.PasswordHasher.HashPassword(user, plainPassword);
user.Password = newHash;
return Task.FromResult(true);
}
else
{
_userManager.AccessFailedAsync(user);
return Task.FromResult(false);
}
}
else
{
var passwordOk = _signInManager.PasswordSignInAsync(user, plainPassword, false, false);
if (passwordOk.Result.Succeeded)
{
_userManager.ResetAccessFailedCountAsync(user);
return Task.FromResult(true);
}
else
{
_userManager.AccessFailedAsync(user);
return Task.FromResult(false);
}
}
}
}
如果有人已经解决了这个问题,你能指出正确的方向吗?
在深入研究 Abp 源代码后,我发现如果用户未被外部源验证,Abp 仍会尝试对其数据库进行身份验证。所以这很可能解决了我的问题:
public class AltAuthSource: DefaultExternalAuthenticationSource<Tenant, User>, ITransientDependency
{
private readonly IRepository<User, long> _userRepository;
private readonly UserManager _userManager;
public override string Name => "AltSource";
public AltAuthSource(IRepository<User, long> userRepository, UserManager userManager)
{
_userRepository = userRepository;
_userManager = userManager;
}
public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
{
var user = _userRepository.GetAll().FirstOrDefault(x => x.UserName.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase) || x.EmailAddress.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase));
if (user == null || !string.IsNullOrWhiteSpace(user.Password))
{
return Task.FromResult(false);
}
else
{
var passwordOk = BCrypt.Net.BCrypt.Verify(plainPassword, user.PasswordOrig);
if (passwordOk)
{
_userManager.ResetAccessFailedCountAsync(user);
var newHash = _userManager.PasswordHasher.HashPassword(user, plainPassword);
user.Password = newHash;
return Task.FromResult(true);
}
else
{
_userManager.AccessFailedAsync(user);
return Task.FromResult(false);
}
}
}
}
还是我忽略了什么?
我们将用 Node.js 编写的旧 Web 应用程序迁移到 ASP.NET 零。我们必须保留所有用户及其密码,以便他们仍然能够登录。使用 bcrypt 对密码进行哈希处理。
计划如下:当用户在迁移后首次登录时,我们授权 him/her 反对 brypt 密码,如果密码有效,我们使用
_userManager.PasswordHasher.HashPassword(user, plainPassword)
并将其保存为 his/her 密码。下次该用户想要登录时,将调用标准 ASP.NET 零函数来实现此目的。
第一部分 - bcrypt 工作得很好,但我不知道如何使用标准机制来验证用户。这是我目前所拥有的:
private readonly IRepository<User, long> _userRepository;
private readonly SignInManager<User> _signInManager;
private readonly UserManager _userManager;
public AltAuthSource(IRepository<User, long> userRepository, UserManager userManager, SignInManager<User> signInManager)
{
_userRepository = userRepository;
_userManager = userManager;
_signInManager = signInManager;
}
public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
{
var user = _userRepository.GetAll().FirstOrDefault(x => x.UserName.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase) || x.EmailAddress.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase));
if (user == null)
{
return Task.FromResult(false);
}
else
{
if (string.IsNullOrWhiteSpace(user.Password))
{
var passwordOk = BCrypt.Net.BCrypt.Verify(plainPassword, user.PasswordOrig);
if (passwordOk)
{
_userManager.ResetAccessFailedCountAsync(user);
var newHash = _userManager.PasswordHasher.HashPassword(user, plainPassword);
user.Password = newHash;
return Task.FromResult(true);
}
else
{
_userManager.AccessFailedAsync(user);
return Task.FromResult(false);
}
}
else
{
var passwordOk = _signInManager.PasswordSignInAsync(user, plainPassword, false, false);
if (passwordOk.Result.Succeeded)
{
_userManager.ResetAccessFailedCountAsync(user);
return Task.FromResult(true);
}
else
{
_userManager.AccessFailedAsync(user);
return Task.FromResult(false);
}
}
}
}
如果有人已经解决了这个问题,你能指出正确的方向吗?
在深入研究 Abp 源代码后,我发现如果用户未被外部源验证,Abp 仍会尝试对其数据库进行身份验证。所以这很可能解决了我的问题:
public class AltAuthSource: DefaultExternalAuthenticationSource<Tenant, User>, ITransientDependency
{
private readonly IRepository<User, long> _userRepository;
private readonly UserManager _userManager;
public override string Name => "AltSource";
public AltAuthSource(IRepository<User, long> userRepository, UserManager userManager)
{
_userRepository = userRepository;
_userManager = userManager;
}
public override Task<bool> TryAuthenticateAsync(string userNameOrEmailAddress, string plainPassword, Tenant tenant)
{
var user = _userRepository.GetAll().FirstOrDefault(x => x.UserName.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase) || x.EmailAddress.Equals(userNameOrEmailAddress, StringComparison.InvariantCultureIgnoreCase));
if (user == null || !string.IsNullOrWhiteSpace(user.Password))
{
return Task.FromResult(false);
}
else
{
var passwordOk = BCrypt.Net.BCrypt.Verify(plainPassword, user.PasswordOrig);
if (passwordOk)
{
_userManager.ResetAccessFailedCountAsync(user);
var newHash = _userManager.PasswordHasher.HashPassword(user, plainPassword);
user.Password = newHash;
return Task.FromResult(true);
}
else
{
_userManager.AccessFailedAsync(user);
return Task.FromResult(false);
}
}
}
}
还是我忽略了什么?