【问题标题】:Authenticate user in stored procedure在存储过程中对用户进行身份验证
【发布时间】:2016-05-18 19:29:03
【问题描述】:

我是 sql 新手,我不确定我的存储过程有什么问题。

用户输入用户名和密码,这是我的输入参数,如果正确则返回“登录成功”,如果 UN 不正确则返回“不正确 UN”,或者如果 PW 不正确则返回“不正确 PW”。在存储过程中,我有一个 IF Else 语句,它只命中第一个 IF 语句而不是其他语句。

请看一下我的存储过程:

CREATE PROCEDURE [dbo].[AuthenticateUser]
@UserName varchar(15),
@Password varchar(15),
@Role varchar(25) OUTPUT
AS
    SET NOCOUNT ON
BEGIN
    DECLARE @UN VARCHAR(25)
    DECLARE @PW VARCHAR(25)
    SELECT @UN = UserName, @PW = Password FROM LogIn 
        IF (@UN != @UserName COLLATE SQL_Latin1_General_CP1_CS_AS)
            BEGIN
                SET @Role = 'Incorrect User Name'
            END
        ELSE
            BEGIN
                IF (@PW != @Password COLLATE SQL_Latin1_General_CP1_CS_AS)
                    BEGIN
                        SET @Role = 'Incorrect Password'
                    END
                ELSE
                    BEGIN
                        SET @Role = 'Logged in Successfully'
                    END
            END
    SELECT @Role
END

感谢您的帮助

【问题讨论】:

  • 那么,您是从表LogIn 中选择一些随机行,然后将其与传递的值进行比较,对吧?
  • 您的代码对我来说很好用。你确定你传入的参数正确吗?
  • 嗨 Lashane,感谢您的及时回复,请看我下面的代码 SqlCommand comm = new SqlCommand("AuthenticateUser", MyConnection.MyConn("Open")); comm.CommandType = CommandType.StoredProcedure; comm.Parameters.Add("@UserName", SqlDbType.VarChar).Value = userName.Text; comm.Parameters.Add("@Password", SqlDbType.VarChar).Value = Password.Text; comm.Parameters.Add("@Role", SqlDbType.VarChar, 25); comm.Parameters["@Role"].Direction = ParameterDirection.Output; comm.ExecuteNonQuery(); employee.UserRole = (comm.Parameters["@Role"].Value).ToString();
  • 顺便说一句,我会避免在数据库中存储任何应用程序的纯文本密码。我建议至少实施 SQL 级别的加密。 Simple talk 和 Database Journal 有关于如何实现这一点的文章。 databasejournal.com/features/mssql/article.php/3922881/…simple-talk.com/sql/t-sql-programming/…

标签: sql-server stored-procedures


【解决方案1】:

你正在这样做:

SELECT @UN = UserName, @PW = Password FROM LogIn 
    IF (@UN != @UserName COLLATE SQL_Latin1_General_CP1_CS_AS)

这些比较@UN = UserName@PW = Password 应在WHERE 子句中进行,以帮助正确过滤行。

这里是重写的代码(你可以改成使用自己的表名)

Drop Table TestLogin 
GO
Create Table TestLogin 
(
UserName VarChar (20),
Password VarChar(20)
)
Insert TestLogin Values ('One', 'Two')
GO




Drop PROCEDURE AuthenticateUser
GO
CREATE PROCEDURE AuthenticateUser
    @UserName varchar(15),
    @Password varchar(15),
    @Role varchar(25) OUTPUT
AS

    If ((SELECT Count (*) From TestLogin Where UserName COLLATE SQL_Latin1_General_CP1_CS_AS = @Username And Password COLLATE SQL_Latin1_General_CP1_CS_AS = @Password) = 0)
    Begin
        If ((SELECT Count (*) From TestLogin Where UserName COLLATE SQL_Latin1_General_CP1_CS_AS = @Username) = 0)
        Begin
            Select @Role = 'Incorrect User Name'
        End
        Else
        Begin
             Select @Role = 'Incorrect Password'
        End
    End
    Else
    Begin
        Select @Role = 'Logged in Successfully'
    End
GO
Declare @Role VarChar (100)
Exec AuthenticateUser 'One', 'Two', @Role Output
Print @Role

Exec AuthenticateUser 'One', 'TwoX', @Role Output
Print @Role

Exec AuthenticateUser 'OneX', 'Two', @Role Output
Print @Role

最后提供的三个示例向您展示了当您给它一个良好的登录或任何一个参数不正确时该过程的行为。

【讨论】:

    【解决方案2】:

    将其更改为 SELECT COUNT(1) FROM userLogin....,然后在 SqlDataReader 对象上使用 ExecuteScalar()。

    附带说明一下,将密码以纯文本形式存储在数据库中并不是一个好主意,而是对它们进行哈希处理,最好使用盐值。

    【讨论】:

    • 问题不在此代码的标量部分。它在密码的实际验证中
    【解决方案3】:

    试试这个:

    Create PROCEDURE [dbo].[AuthenticateUser]
    @UserName varchar(15),
    @Password varchar(15),
    @Role varchar(25) OUTPUT
    AS
        SET NOCOUNT ON
    BEGIN
    
        If Not Exists (Select 1 From LogIn Where UserName = @UserName) Set @Role = 'Incorrect UserName'
        Else If Not Exists (Select 1 From LogIn Where Password = @Password) Set @Role = 'Incorrect Password'
        Else Set @Role = 'Logged in Successfully' 
    
        Select @Role
    
    END
    

    【讨论】:

      【解决方案4】:

      一般来说,给攻击者一个提示“名字没问题,现在猜密码”不是一个好主意。另外,密码至少应该区分大小写。为此:

      select @un=username from LogIn 
      where username=@username 
      and cast(password as varbinary(max)) = cast(@password as varbinary(max))
      
      if @un is null
         set @role = 'UN or PWD is incorrect'
      else
         set @role = 'Success'
      

      如果你想给出提示:

      select @un=username from LogIn 
      where username=@username 
      
      if @un is null
         set @role = 'UN not found'
      else
      begin
         select @un=username from LogIn 
         where username=@username 
         and cast(password as varbinary(max)) = cast(@password as varbinary(max))
         if @un is null
            set @role = 'password incorrect'
         else
            set @role = 'Success'
      end
      

      P.S.:我希望用户名在您的表中是唯一的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-06
        • 2017-07-28
        • 2013-03-11
        • 1970-01-01
        • 2017-07-03
        • 2021-06-11
        • 1970-01-01
        相关资源
        最近更新 更多