简体   繁体   English

如何调用HashPassword并将用户密码存储到数据库?

[英]How to Call to HashPassword and to store User password to database?

I'm setting up a HashPassword function using SHA1CryptoServiceProvider().我正在使用 SHA1CryptoServiceProvider() 设置一个 HashPassword 函数。 My requirement includes two methods: generate the salt and initializer which I need help with.我的要求包括两种方法:生成我需要帮助的盐和初始值设定项。

Salt is used with the IV which is used to salt the password before it is hashed, and the password to validate. Salt 与 IV 一起使用,IV 用于在散列之前对密码进行加盐,以及要验证的密码。 The initializer takes the string made by the salt generator it mixes the password and salt into one string and add's any extra characters to the end then hash the blended password and returns the value.初始值设定项采用盐生成器生成的字符串,它将密码和盐混合成一个字符串,并将任何额外的字符添加到末尾,然后散列混合密码并返回值。

Essentially, I need to compare if the value sent from the view differs from the original and if it does then i need to regenerate the hash and initializer on a create(new record).本质上,我需要比较从视图发送的值是否与原始值不同,如果不同,那么我需要在创建(新记录)上重新生成散列和初始值设定项。

This controller action calls the HashPassword functions in the USERController.Helper file.此控制器操作调用 USERController.Helper 文件中的 HashPassword 函数。

    public ActionResult HashPassword(USERSModel UsersModel)
    {
        USERDto dto = new USERDto();

        if (ModelState.IsValid)
        {
            string hashedPassword = UsersModel.PASSWORD;
            UsersModel.PASSWORD = hashedPassword;
            dto.Updated.Add(hashedPassword);
            dto.Updated.Add("NAME");
            dto.Updated.Add("ID");
            dto.Updated.Add("PASSWORD");
            UsersModel.Updated.SaveChanges();

            ViewBag.Message = "User was added successfully!";
            UsersModel = new USERSModel();

        }
        else
            ViewBag.message = "Error in adding User!";


        return View("USERSSettingsPartial", UsersModel);
    }

 /// <summary>
    /// Called to hash a user password to be stored in the DB.
    /// </summary>
    /// <param name="password">The password to validate.</param>
    /// <param name="salt">The IV used to salt the password before it is hashed.</param>
    /// <param name="errorDesc">Returns an error description if an error occurs.</param>
    /// <returns>Returns the hashed password as a HEX string on success, otherwise returns null.</returns>

        private string HashPassword(string password, byte[] salt, ref string errorDesc)
        {
            try
            {
                byte[] newPassword = Encoding.ASCII.GetBytes(password.ToUpper());
                if (salt != null && salt.Length > 0)
                {
                    int count = (salt.Length < newPassword.Length) ? salt.Length : newPassword.Length;
                    byte[] temp = new byte[salt.Length + newPassword.Length];
                    for (int index = 0; index < count; index++)
                    {
                        temp[index * 2] = newPassword[index];
                        temp[index * 2 + 1] = salt[index];
                    }
                    if (count == salt.Length && count < newPassword.Length)
                        Buffer.BlockCopy(newPassword, count, temp, count * 2, newPassword.Length - count);
                    else if (count == newPassword.Length && count < salt.Length)
                        Buffer.BlockCopy(salt, count, temp, count * 2, salt.Length - count);

                    newPassword = temp;
                }
                using (var hash = new System.Security.Cryptography.SHA1CryptoServiceProvider())
                {
                    hash.ComputeHash(newPassword);
                    return this.GetHexStringFromBytes(hash.Hash);
                }
            }
            catch (Exception Ex)
            {
                errorDesc = Ex.Message;
                if (Ex.InnerException != null) errorDesc = string.Format("{0}\r\n{1}", errorDesc, Ex.InnerException.Message);
            }
            return null;
        }

        /// <summary>
        /// called to convert byte data into hexidecimal string were each byte is represented as two hexidecimal characters.
        /// </summary>
        /// <param name="data">Byte data to convert.</param>
        /// <returns>A hexidecimal string version of the data.</returns>
        private string GetHexStringFromBytes(byte[] data)
        {
            if (data == null || data.Length == 0) return string.Empty;

            StringBuilder sbHex = new StringBuilder();
            for (int index = 0; index < data.Length; index++) sbHex.AppendFormat(null, "{0:X2}", data[index]);

            return sbHex.ToString();
        }

        /// <summary>
        /// called to convert hexadecimal string into byte data were two hexadecimal characters are converted into a byte.
        /// </summary>
        /// <param name="hexString">A hexidecimal string to convert</param>
        /// <returns>The converted byte data.</returns>
        private byte[] GetBytesFromHexString(string hexString)
        {
            if (string.IsNullOrEmpty(hexString)) return null;

            byte[] data = new byte[hexString.Length / 2];
            for (int index = 0; index < data.Length; index++)
            {
                data[index] = byte.Parse(hexString.Substring(index * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            return data;
        }  

This is my first go around with a project like this, therefore I don't have any output.这是我第一次进行这样的项目,因此我没有任何输出。 Just need examples to understand better.只需要例子来更好地理解。

Basically needed to have a Controller in a Service where this class will create the salt and be called from a Controller Helper class.基本上需要在服务中有一个控制器,这个类将创建盐并从控制器助手类中调用。 What I did was set the Initializer on the server side where in turn added code to the USERS service controller create IHttpActionResult which sets the salt and password.我所做的是在服务器端设置初始化程序,然后将代码添加到用户服务控制器创建 IHttpActionResult 设置盐和密码。 You never want to store passwords in your database, always want to hash them.您永远不想将密码存储在数据库中,总是想对它们进行哈希处理。
I created a request in the service controller of the USERS passing in DTO which is used to create a new record, returning an object containing the query results if any, otherwise returns not found or internal server error message.我在传入 DTO 的 USERS 的服务控制器中创建了一个请求,该请求用于创建新记录,返回包含查询结果的对象(如果有),否则返回未找到或内部服务器错误消息。 Within this method Salt is being called:在这个方法中,Salt 被调用:

public IHttpActionResult Create([FromBody]USERDto dto)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        try
        {
            byte[] saltValue;
            string error = string.Empty;

            saltValue = GenerateSalt();
            dto.INITIALIZER = GetHexStringFromBytes(saltValue);
            dto.PASSWORD = HashPassword(dto.PASSWORD, saltValue, ref error);

            USERDto created = USERSProcessor.Create(dto);
            if (created == null)
            {
                return NotFound();
            }
            return Ok(created);
        }
        catch (Exception ex)
        {
            LogUtility.LogError(ex);
            return InternalServerError(ex);
        }
    }

Then (to not clutter controller) I created a controller helper class & added this code to implement the hashing salt methods, where the USERSController calls to the hash password to be stored in the database, as well as the dto.INITIALIZER is called to convert byte data into hexadecimal string where each byte is represented as two hexadecimal characters:然后(为了不杂乱控制器)我创建了一个控制器助手类并添加了此代码来实现散列盐方法,其中 USERSController 调用要存储在数据库中的散列密码,以及调用 dto.INITIALIZER 进行转换将字节数据转换为十六进制字符串,其中每个字节表示为两个十六进制字符:

partial class USERSController
{    
    /// <summary>
    /// Called to generate salt byte array.
    /// </summary>
    /// <returns>The generated salt byte array.</returns>
    public static byte[] GenerateSalt()
    {
        byte[] iv;
        using (var alg = new AesCryptoServiceProvider())
        {
            alg.BlockSize = 128; //block size is 8bytes, which is the the size of the IV generated.
            alg.KeySize = 256; //key size is 32bytes
            alg.GenerateIV();
            iv = alg.IV;
        }

        return iv;
    }


    /// <summary>
    /// Called to hash a user password to be stored in DB.
    /// </summary>
    /// <param name="password">The password to validate.</param>
    /// <param name="salt">The IV used to salt the password before it is hashed.</param>
    /// <param name="errorDesc">Returns an error description if an error occurs.</param>
    /// <returns>Returns the hashed password as a HEX string on success, otherwise returns null.</returns>
    private static string HashPassword(string password, byte[] salt, ref string errorDesc)
    {
        try
        {
            byte[] newPassword = Encoding.ASCII.GetBytes(password.ToUpper());
            if (salt != null && salt.Length > 0)
            {
                int count = (salt.Length < newPassword.Length) ? salt.Length : newPassword.Length;
                byte[] temp = new byte[salt.Length + newPassword.Length];
                for (int index = 0; index < count; index++)
                {
                    temp[index * 2] = newPassword[index];
                    temp[index * 2 + 1] = salt[index];
                }
                if (count == salt.Length && count < newPassword.Length)
                    Buffer.BlockCopy(newPassword, count, temp, count * 2, newPassword.Length - count);
                else if (count == newPassword.Length && count < salt.Length)
                    Buffer.BlockCopy(salt, count, temp, count * 2, salt.Length - count);

                newPassword = temp;
            }
            using (var hash = new System.Security.Cryptography.SHA1CryptoServiceProvider())
            {
                hash.ComputeHash(newPassword);
                return GetHexStringFromBytes(hash.Hash);
            }
        }
        catch (Exception Ex)
        {
            errorDesc = Ex.Message;
            if (Ex.InnerException != null) errorDesc = string.Format("{0}\r\n{1}", errorDesc, Ex.InnerException.Message);
        }
        return null;
    }

    /// <summary>
    /// called to convert byte data into hexidecimal string were each byte is represented as two hexidecimal characters.
    /// </summary>
    /// <param name="data">Byte data to convert.</param>
    /// <returns>A hexidecimal string version of the data.</returns>
    private static string GetHexStringFromBytes(byte[] data)
    {
        if (data == null || data.Length == 0) return string.Empty;

        StringBuilder sbHex = new StringBuilder();
        for (int index = 0; index < data.Length; index++) sbHex.AppendFormat(null, "{0:X2}", data[index]);

        return sbHex.ToString();
    }

    /// <summary>
    /// called to convert hexidecimal string into byte data were two hexidecimal characters are converted into a byte.
    /// </summary>
    /// <param name="hexString">A hexidecimal string to convert</param>
    /// <returns>The converted byte data.</returns>
    private static byte[] GetBytesFromHexString(string hexString)
    {
        if (string.IsNullOrEmpty(hexString)) return null;

        byte[] data = new byte[hexString.Length / 2];
        for (int index = 0; index < data.Length; index++)
        {
            data[index] = byte.Parse(hexString.Substring(index * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
        }
        return data;
    }       

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM