2010-01-04 52 views
3

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

这是我的查询:

用户表包含用户名,EMAILID,移动,国家等,

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

我的查询将仅返回一个int,但我需要用户的详细信息,以及。如:用户,emailid等我想要特定用户的全部详细信息 - 是否有可能在此查询中?

+0

为什么你会返回无效的用户名/密码信息?提供的内容可以匹配大量记录,而不仅仅是一个。 – 2010-01-04 04:12:58

+6

注意:出于显而易见的原因,提供有关它是否是失败的用户名或密码的信息是不安全的做法。 – 2010-01-04 04:20:43

+1

我同意米奇,但他们可能不会将该信息提供给用户,而只是让应用程序考虑它。也许他想发送电子邮件来提醒用户有人试图以他们的身份登录。 – 2010-01-04 04:25:56

回答

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

确定Rob Farley先生 – 2010-01-04 04:08:52

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 [email protected]) 
begin 
    if exists (select [password], username 
       from users 
       where [password][email protected] 
        and [email protected]) 
    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 

现在你有一个的UserDetails记录在那里存在,以及您的INT输出值。

这个答案虽然

三个注意事项:

  • 我提供了可根据使用情况和实际的数据来提高SQL,它只是打算选择显示到记录集
  • 方式您访问记录集并且输出参数将取决于您的数据访问技术。
  • 按照你的方式在数据库中存储密码可能是一个坏主意。
+0

而且正如OMG Ponies所说,您正在尝试做的事情对于返回无效密码用户名对的详细信息可能没有多大意义。 – 2010-01-04 04:21:18

+1

FWIW,只有在消耗完所有返回的行集之后,才能访问输出参数。 – 2010-01-04 04:27:47

+0

@Cade Roux - 谢谢你提及。我很少使用输出参数,因此事实就是我每次记住每次它时都记住的事情之一。 – 2010-01-04 04:35:42

0
  • 不要存放在数据库中的密码 - 存储salted hash(也注意到,默认情况下不区分大小写的排序规则将意味着,无论用户名密码也不是大小写敏感相比 - 通常密码是区分大小写)您可以使用T-SQL hashbytes函数以及适当的盐分数据和适当的散列函数选择
  • 如果用户名有效但密码无效或反之亦然,则不要向用户指出任何区别,此信息也可用于协助攻击
  • 让客户端代码检查结果集中是否存在该行并采取适当的行动,没有行表示没有登录着手 - 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

+0

谢谢Mr.Cade Roux很好的解释我会检查问题谢谢你的回复 – 2010-01-04 05:16:18

2
select [password], username, email, ... 
from users 
where [email protected]; 

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

此外,你应该返回相同的错误'不正确的用户名和密码'irelevant如果用户错过了用户名和密码或只是密码。返回不同的错误信息是信息泄露,你只是通过披露他们随机尝试的用户存在或不存在来做黑客服务。