SQL查询,返回表或表行?

时间:2010-01-04 04:04:51

标签: sql-server

在我的Web应用程序中,我编写了一个查询来检查用户标识和密码。如果用户标识失败,我写的查询显示用户ID错误,如果密码错误则显示密码错误。我写的查询只返回int,但我想返回表或数据行,你可以给我一个解决方案吗?

这是我的疑问:

用户表包括用户名,emailid,手机,国家等,

create procedure [dbo].[sp_users_login] (
  @username varchar(30),
  @password varchar(30),
  @ret int output)
as
 if exists (select username from users where username=@username)
   if exists (select [password], username 
                from users 
                where [password]=@password 
                  and username=@username)
     set @ret =1
   else 
     set @ret=2 
 else 
   set @ret=3

我的查询只返回一个int,但我也需要用户详细信息。例如:user,emailid等。我想要特定用户的总详细信息 - 这个查询是否可以?

4 个答案:

答案 0 :(得分:2)

我正在考虑使用HAVING将结果强制为单行,并使用子查询来检查事物,但这不是必需的。

尝试在SELECT子句中使用聚合,以便准确地返回一行。然后,您可以使用CASE获取所需的信息。

SELECT 
  CASE 
    WHEN COUNT(*) = 0 THEN 'No username' 
    WHEN MAX(password) = @password THEN 'Logged in' 
    ELSE 'Bad password'
  END as LoginStatus,
  MAX(emailaddress) as Email
FROM dbo.Users u
WHERE username = @username
;

对您需要的所有其他字段重复MAX(emailaddress)。如果用户名是唯一的(并且你应该设置一个约束来确保它是),那么这没关系。如果没有匹配的用户,这些行将返回空白。但是如果他们只是输错了密码,那么这些字段将被返回,所以请检查你的LoginStatus,看看你是否应该注意它。

答案 1 :(得分:2)

select [password], username, email, ...
from users 
where username=@username;

您应该只使用用户名选择感兴趣的字段。您不可能有两个不同的用户使用相同的用户名和不同的密码。如果一个人决定更改密码并且新密码恰好与其他用户的密码相匹配怎么办?如果一个用户因输入错误而输入其他用户的密码(比如他们已经关闭)并突然登录到另一个用户帐户,该怎么办?你打算如何识别用户?

如果用户错过了用户名和密码或只是密码,您也应该返回相同的错误“用户名和密码不正确”。返回不同的错误消息是信息泄露,你只是通过披露他们随机尝试的用户是否存在来为黑客提供服务。

答案 2 :(得分:1)

您可以从SQL存储过程返回0到多个记录集,以及输出参数。

在tsql中,记录集类似于表或数据行。

因此,采用您的示例程序,您可以执行以下操作:

create procedure [dbo].[sp_users_login] ( 
  @username varchar(30), 
  @password varchar(30), 
  @ret int output) 
as 
 if exists (select username from users where username=@username) 
 begin
   if exists (select [password], username  
                from users  
                where [password]=@password  
                  and username=@username) 
     set @ret =1 
   else  
     begin
         set @ret=2
     end  
   -- The select below is just an example - modify it to your needs
   select * from users 
   where username = @username
 end
 else  
   set @ret=3 

现在你有一个记录集,其中包含userdtails,以及你的int输出值。

虽然有这个答案的三个警告:

  • 我提供的sql可以根据使用情况和实际数据进行改进,它只是为了显示select到记录集中
  • 访问记录集和输出参数的方式取决于您的数据访问技术。
  • 按照您的方式在数据库中存储密码可能是一个坏主意。

答案 3 :(得分:0)

  • 不要将密码存储在数据库中 - 存储salted hash(另请注意,默认不区分大小写的排序规则表示用户名和密码都不区分大小写 - 通常密码区分大小写)可以使用T-SQL hashbytes函数和适当的salted数据以及适当的hash函数选择
  • 如果用户名有效但密码无效,则不要向用户表明任何差异,反之亦然,此信息也可用于协助攻击
  • 让客户端代码检查结果集中是否存在行并进行相应操作,没有行表示无法继续登录 - you cannot get the output parameters until you've consumed all the rows IIRC anyway

这是我推荐的代码(我没有输出输出参数,并假设密码没有存储,但哈希是 - 并且密码只是用用户名来创建哈希(不总是最好的选择,尤其是如果您允许更改用户名并且没有正确地重新获取密码以重新存储新哈希,那么用户名通常不区分大小写)):

create procedure [dbo].[sp_users_login] (
  @username varchar(30),
  @password varchar(30)
)
as
    select username -- , addition users.columns 
    from users 
    where pwhash = HashBytes('SHA1', UPPER(@username) + @password) 
        and username = @username)

您还应该看看这些问题:

Is it okay to store salts with hashes?

Crypto, hashes and password questions, total noob?

Salt Generation and open source software

Secure hash and salt for PHP passwords