如何在C#中修复此StoredProcedure的空值?

时间:2019-05-10 21:20:08

标签: c# sql-server stored-procedures

我为用户创建了一个存储过程以登录应用程序,但是无论我尝试了什么,并且观看了许多存储过程指南,但都没有设法取回值。

我也尝试使用输出参数来获取值,也尝试使用DatarReader但未分配值。出于某种原因,调试会忽略对象值。

在SQL Server中,我尝试存储的某些DECLARE方法似乎可以正常工作,但在C#中我没有任何值。

这是第一个存储过程:

ALTER PROCEDURE spAddUser
@pLogin NVARCHAR(50), 
@pPassword NVARCHAR(50),
@pRole nvarchar(20)
AS
BEGIN
INSERT INTO [UsersDetails] (LoginName, PasswordHash, UserRole)
VALUES(@pLogin, HASHBYTES('SHA2_512', @pPassword), @pRole)
END;
CREATE PROCEDURE [dbo].[spLogin]
    @uname NVARCHAR(50),  
    @pass VARCHAR(50)
AS
BEGIN
    SELECT  LoginName,[PasswordHash],UserRole
    FROM UsersDetails
    WHERE LoginName=@uname AND [PasswordHash]=@pass
END;
GO
Console.WriteLine("Enter Username and Password to Login");
string userLogin = Console.ReadLine();
string passwordLogin = Console.ReadLine();

SqlCommand cmdLogin = new SqlCommand();
cmdLogin.Connection = sqlcon;
cmdLogin.CommandType = CommandType.StoredProcedure;
cmdLogin.CommandText = "spLogin";
cmdLogin.Parameters.Add(new SqlParameter("@uname", SqlDbType.NVarChar)).Value = userLogin;
cmdLogin.Parameters.Add(new SqlParameter("@pass", SqlDbType.NVarChar)).Value = passwordLogin;
cmdLogin.Parameters["@uname"].Direction = ParameterDirection.ReturnValue;                        

SqlDataReader loginReader = cmdLogin.ExecuteReader();
while (loginReader.Read())
{
    User user = new User
    {
        ID = loginReader.GetInt32(0),
        LoginName = loginReader.GetString(1),
        PasswordHash = loginReader.GetString(2)
    };
    Console.Write(user);
}
loginReader.Close();

1 个答案:

答案 0 :(得分:0)

您以纯文本形式捕获了用户密码。另一方面,密码以varbinary的形式存储在数据库中。您无法将nvarchar与varbinary进行比较。您可以选择在客户端对用户密码进行哈希处理。这也是一种有效的方法。在那种情况下,您应该更改您的SP以接收varbinary作为参数,并且您的逻辑会很好。意思是“ AND [PasswrodHash] = @ pass。

尝试插入下面的代码段所示的记录,然后更改存储过程。注意,用户名为“ darko”,密码为“ MyTestPas”

CREATE TABLE UsersDetails
(id           INTEGER IDENTITY PRIMARY KEY CLUSTERED , 
 LoginName    NVARCHAR(50) NOT NULL, 
 PasswordHash VARBINARY(4000) NOT NULL, 
 UserRole     NVARCHAR(50) NOT NULL
);

    INSERT INTO UsersDetails
    (loginname, 
     passwordhash, 
     userrole
    )
           SELECT 'darko', 
                  HASHBYTES('SHA2_512', 'MyTestPas'), 
                  'admin';
    --Check the result 
    SELECT *
    FROM UsersDetails;

    CREATE PROCEDURE [dbo].[spLogin] @uname NVARCHAR(50), 
                                     @pass  VARCHAR(50)
    AS
        BEGIN
            SELECT ID, 
                   LoginName, 
                   [PasswordHash], 
                   UserRole
            FROM UsersDetails
            WHERE LoginName = @uname
                  AND [PasswordHash] = HASHBYTES('SHA2_512', @pass);
        END;
    GO

使用以下代码段更改.NET代码。注意,为简单起见,我用常量代替读取用户名和密码。第二个注意事项是,您必须更改连接字符串。

using System;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleApp21
{
    class Program
    {
        static void Main()
        {
            // these are read from the command line as the plain text
            const string userLogin = "darko";
            const string passwordLogin = "MyTestPas";

            // Change to match your connection string
            var sqlcon = new SqlConnection("Integrated Security = true; Initial Catalog = your database; Server = your server");
            sqlcon.Open();
            var cmdLogin = new SqlCommand
            {
                Connection = sqlcon, CommandType = CommandType.StoredProcedure, CommandText = "spLogin"
            };
            cmdLogin.Parameters.Add(new SqlParameter("@uname", SqlDbType.NVarChar)).Value = userLogin;
            cmdLogin.Parameters.Add(new SqlParameter("@pass", SqlDbType.NVarChar)).Value = passwordLogin;


        var loginReader = cmdLogin.ExecuteReader();
        while (loginReader.Read())
        {
            var user = new User
            {

                LoginName = (string)loginReader["LoginName"],

                UserRole = (string)loginReader["UserRole"]
            };
            Console.Write($"{user.LoginName}({user.UserRole})");

        }
        loginReader.Close();
        Console.ReadLine();
        }
    }

    public class User
    {
        public string UserRole { get; set; }
        public string LoginName { get; set; }
        public Byte PasswordHash { get; set; }


        public int Id { get; set; }


    }
}