I'm trying to switch to .NET Identity from an old custom membership provider in an existing MVC application, and maintain dapper as the ORM, not EntityFramework which comes out of the box.
I'm stuck at trying to implement my own EXISTS
, as I need the existing credentials to work. In public function logout() {
$user = $this->user();
// If we have an event dispatcher instance, we can fire off the logout event
// so any further processing can be done. This allows the developer to be
// listening for anytime a user signs out of this application manually.
$this->clearUserDataFromStorage();
if ( ! is_null($this->user))
{
$this->refreshRememberToken($user);
}
if (isset($this->events))
{
$this->events->fire('auth.logout', [$user]);
}
// Once we have fired the logout event we will clear the users out of memory
// so they are no longer available as the user is no longer considered as
// being signed into this application and should not be available here.
$this->user = null;
$this->loggedOut = true;
}
I want to return a SHA-computed hash of the cleartext input combined with a user-specific salt, but the method only receives the clear text value, and no reference to the user for which a login is attempted.
Where can I get this salt? Or am I going at this in the wrong way?
答案 0 :(得分:2)
我必须为迁移做同样的事情。推荐的migration article为您的问题提供了解决方案。
您需要将旧密码哈希与salt合并到一个Password
字段中,并用特殊符号分隔(在文章中为|
,但您可以选择自己的分隔符。)
然后PasswordHasher
应该检查该特殊符号的密码,如果它与密码存在单独的盐并应用散列。
以下是上述链接文章中的代码段,但我已删除了一些用于检查纯文本密码存储的噪音。这假设您的哈希以SH1hash|salt
public class SQLPasswordHasher : PasswordHasher
{
public override string HashPassword(string password)
{
return base.HashPassword(password);
}
public override PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{
string[] passwordProperties = hashedPassword.Split('|');
if (passwordProperties.Length != 2)
{
// use default Identity implementation
return base.VerifyHashedPassword(hashedPassword, providedPassword);
}
else
{
string passwordHash = passwordProperties[0];
string salt = passwordProperties[1];
if (String.Equals(EncryptPassword(providedPassword, salt), passwordHash, StringComparison.CurrentCultureIgnoreCase))
{
return PasswordVerificationResult.SuccessRehashNeeded;
}
else
{
return PasswordVerificationResult.Failed;
}
}
}
//This is copied from the existing SQL provider
private string EncryptPassword(string pass, string salt)
{
byte[] bIn = Encoding.Unicode.GetBytes(pass);
byte[] bSalt = Convert.FromBase64String(salt);
byte[] bRet = null;
HashAlgorithm hm = HashAlgorithm.Create("SHA1");
if (hm is KeyedHashAlgorithm)
{
KeyedHashAlgorithm kha = (KeyedHashAlgorithm)hm;
if (kha.Key.Length == bSalt.Length)
{
kha.Key = bSalt;
}
else if (kha.Key.Length < bSalt.Length)
{
byte[] bKey = new byte[kha.Key.Length];
Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length);
kha.Key = bKey;
}
else
{
byte[] bKey = new byte[kha.Key.Length];
for (int iter = 0; iter < bKey.Length; )
{
int len = Math.Min(bSalt.Length, bKey.Length - iter);
Buffer.BlockCopy(bSalt, 0, bKey, iter, len);
iter += len;
}
kha.Key = bKey;
}
bRet = kha.ComputeHash(bIn);
}
else
{
byte[] bAll = new byte[bSalt.Length + bIn.Length];
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
bRet = hm.ComputeHash(bAll);
}
return Convert.ToBase64String(bRet);
}
}