[英]Is my password/authentication strategy for a REST API good?
好的,好的是主观的,但标题更合适。 我真正想知道的是,此密码管理/身份验证策略中是否存在任何明显的缺陷。 我也对性能感到好奇。 我正在尝试使用PBKDF2进行身份验证,但我不确定这是否是RESTful Web服务的好主意。 我可以在这里到那里找到该问题的某些部分,但是我从未找到一个完整的自上而下的答案。 这就是我的整个策略。
背景:
首先,后端:
create table [dbo].[User] (
[Name] varchar(50) collate SQL_Latin1_General_CP1_CI_AI not NULL primary key clustered,
[Password] varchar(28) collate SQL_Latin1_General_CP1_CS_AS not NULL,
[Salt] varchar(28) not NULL)
存储过程创建用户:
create procedure [dbo].[User_Create]
@Name varchar(50),
@Salt varchar(50),
@Password varchar(50)
as
insert into [dbo].[User]([Name], [Salt], [Password])
values(@Name, @Salt, @Password)
和存储过程来获取用户:
create procedure [dbo].[User_Get]
@Name varchar(50)
as
select *
from [dbo].[User]
where [Name] = @Name
对于后端,我很好奇,为名称,密码和盐选择的数据类型是否合适。
这是创建新用户并将其持久化到后端的代码。 从安全角度和性能上来说,这可能是我最担心的问题。
public void CreateUser(string username, string password)
{
int hashLength = 20;
int saltLength = 20;
int hashIterations = 1000;
using(SqlConnection connection = new SqlConnection(this._ConnectionString))
using (SqlCommand command = new SqlCommand("[dbo].[User_Create]"))
{
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, saltLength, hashIterations);
string salt = Convert.ToBase64String(pbkdf2.Salt);
string hashPassword = Convert.ToBase64String(pbkdf2.GetBytes(hashLength));
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Name", username);
command.Parameters.AddWithValue("@Salt", salt);
command.Parameters.AddWithValue("@Password", hashPassword);
connection.Open();
command.ExecuteNonQuery();
}
}
这是验证用户身份的代码。 这实际上只是执行存储过程,调用ValidatePassword
执行PBKDF2,然后将User
对象返回给Web API消息处理程序,该处理程序设置Principal(角色尚未实现):
public User AuthenticateUser(string username, string password)
{
using (SqlConnection connection = new SqlConnection(this._ConnectionString))
using (SqlCommand command = new SqlCommand("[dbo].[User_Get]"))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Name", username);
command.Connection = connection;
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read() && this.ValidatePassword(password, reader["Salt"].ToString(), reader["Password"].ToString()))
{
return new User()
{
Name = username,
CustomerId = reader["CustomerId"].ToString()
};
}
else
{
return null;
}
}
}
}
这是ValidatePassword
,上面的代码依靠它来验证密码(以防万一)。 我还想确保我正确了这一点。
private bool ValidatePassword(string password, string salt, string hashedPassword)
{
int hashLength = 20;
int hashIterations = 1000;
byte[] saltBytes = Convert.FromBase64String(salt);
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, saltBytes, hashIterations);
byte[] hashBytes = pbkdf2.GetBytes(hashLength);
string hash = Convert.ToBase64String(hashBytes);
// Security Decisions For String Comparisons
//
// If you are making a security decision (such as whether to allow access to a system resource) based on the
// result of a string comparison or a case change, you should not use the invariant culture. Instead, you
// should perform a case-sensitive or case-insensitive ordinal comparison by calling a method that includes
// a StringComparison parameter and supplying either StringComparison.Ordinal or
// StringComparison.OrdinalIgnoreCase as an argument. Code that performs culture-sensitive string operations
// can cause security vulnerabilities if the current culture is changed or if the culture on the computer
// that is running the code differs from the culture that is used to test the code. In contrast, an ordinal
// comparison depends solely on the binary value of the compared characters.
//
// Source: http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.invariantculture.aspx
return hash.Equals(hashedPassword, StringComparison.Ordinal);
}
高度自以为是的答案。
当有很多现成的实现(如完全免费且经过良好测试的实现)时,为什么要自己做呢?
一定要把它当作练习(这是一个令人着迷的区域imo),但定时攻击只是冰山一角。
安全性的第一条规则是,如果您自己进行涉及加密的任何事情,您可能正在冒险进入一个应该确保很少进行加密的区域。例如,使用owin或开放式身份验证提供程序或活动目录。 但是要远离武器。
不要成为自己动手泄漏大量数据的下一个木偶。
看一下联合安全,saml令牌和sts提供程序
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.