【问题标题】:SQL Return values in Delphi via ADODelphi中的SQL通过ADO返回值
【发布时间】:2009-07-14 08:59:16
【问题描述】:

我有这个功能来确定用户是否存在于数据库中

DM 是我的数据模块

AQ_LOGIN 一个 ADOQuery

BENU 是我的表格,里面有用户和他们的密码

代码来了:

function UserCheckExist(Login, pw: string): boolean;
begin
    with DM do
    begin
        AQ_LOGIN.Close;
        AQ_LOGIN.SQL.Clear;
        AQ_LOGIN.SQL.Add('select BLOGIN from BENU where BLOGIN = ''Login'' AND BPW = ''pw''');
        AQ_LOGIN.Open;
    end;
end;

我现在的问题是: 如何使函数返回真或假天气是否存在具有相应密码的用户?

提前致谢。

【问题讨论】:

    标签: sql delphi ado


    【解决方案1】:

    我会选择 smok1 的答案(我只是发布类似的内容),但我会参数化您的输入,因此;

    AQ_LOGIN.SQL.Add('select count(*) from BENU where BLOGIN=:login and BPW=:pw'); AQ_LOGIN.Parameters.ParamByName('login').AsString:=login; AQ_LOGIN.Parameters.ParamByName('pw').AsString:=pw;

    然后与 smok1 一样 - 打开数据集并查看返回的计数值。

    注意 - 手边没有 ADO delphi 组件,但 99.9% 的人确定这是语法 :-)

    edit:使用这样的参数的优点之一是您不必清理输入字符串(对于引号之类的内容) - 组件知道如何处理您的字符串。您不会期望用户名中包含单引号,但您可能有一个密码。 :-)

    【讨论】:

    • +1 使用参数也更安全。将用户输入的数据直接注入 SQL 语句会导致滥用。如果允许,那么老练的用户可能会改变查询的行为,超出预期。例如,使用此示例,可以通过在密码字段“'或 bpw > '”中键入以下内容来绕过登录。按照建议使用参数现在可以让这种情况发生。
    【解决方案2】:
    function UserCheckExist(Login, pw: string): boolean;
    begin
        with DM do
        begin
            AQ_LOGIN.Close;
            AQ_LOGIN.SQL.Clear;
            AQ_LOGIN.SQL.Add('select BLOGIN from BENU where BLOGIN = ''Login'' AND BPW = ''pw''');
            AQ_LOGIN.Open;
            Result := (AQ_LOGIN.RecordCount > 0);
            AQ_LOGIN.Close;
        end;
    end;
    

    【讨论】:

      【解决方案3】:

      用途:

      function UserCheckExist(Login, pw: string): boolean;
      begin
        with DM do
        begin
          AQ_LOGIN.Close;
          AQ_LOGIN.SQL.Clear;
          {Use COUNT in select to determine if user exists}
          AQ_LOGIN.SQL.Add('select count(BLOGIN) from BENU where BLOGIN = ''Login'' AND BPW 'pw''');
          AQ_LOGIN.Open;
          Result:= (AQ_LOGIN.Fields[0].AsInteger = 1);
          AQ_LOGIN.Close;
       end;
      

      结束;

      两个变化:首先,不要选择用户名,你应该计算值 - COUNT 总是返回一些东西,如果没有用户存在 - 它会为零。 第二:如果计数(字段[0],因为不存在更多字段)等于一,则使用比较计算结果。如果此类记录的计数与 1 不同,则此函数将返回 false。

      【讨论】:

      • +1 来自我,因为您发布的内容几乎与我将要发布的内容一样。但是,我会使用参数而不是连接字符串输入 - 而且,正如发布的代码所代表的那样(在问题和其他答案中) - 它实际上不会工作,肯定吗? :-)
      • @smok1 - 确实 - 我认为他的代码只是让他感到困惑,因为他似乎仍在努力让测试正常工作。 :-(
      【解决方案4】:

      您可以检查 Eof。

      function UserCheckExist(Login, pw: string): boolean;
      begin    
        with DM do    
        begin        
          AQ_LOGIN.Close;        
          AQ_LOGIN.SQL.Clear;        
          AQ_LOGIN.SQL.Add('select BLOGIN from BENU where BLOGIN = ' + QuotedStr(Login) + ' AND BPW = ' + QuotedStr(pw));        
          AQ_LOGIN.Open;        
          Result := (not AQ_Login.Eof);
          AQ_LOGIN.Close;    
        end;
      end;
      

      【讨论】:

      • 那有什么作用呢? Eof = 文件结束?
      • @pr0wl - 来自帮助:测试 Eof(文件结尾)以确定数据集中的活动记录是否是最后一条记录。如果 Eof 为真,则当前记录无疑是数据集中的最后一行。当应用程序打开一个空数据集时,Eof 为真。 (...)
      • 是的,EOF = 文件结束。在这种情况下,如果用户存在,您希望返回 True,因此当 EOF 为 false 时,返回记录并且用户存在。如果 EOF 为 True,则用户不存在。
      【解决方案5】:

      我又添加了一项检查,天气用户处于活动状态。但它不能正常工作。

      function UserCheck(Login, pw: string): boolean;
        begin
          with DM do
          begin
              AQ_LOGIN.Close;
              AQ_LOGIN.SQL.Clear;
              AQ_LOGIN.SQL.Add('select COUNT(*) from BENU where BLOGIN = ''Login'' AND BPW = ''pw'' AND AKTIV = 1');
              AQ_LOGIN.Open;
              Result := (AQ_LOGIN.RecordCount > 0);
              AQ_LOGIN.Close;
          end;
      end;
      

      这是我使用函数的地方:

      procedure TBenu_Login_Form.btnLoginClick(Sender: TObject);
        var pwhashed: string;
        begin
        pwhashed := MD5Print(MD5String(edtBPass.Text));
          if UserCheck(meBLogin.Text, pwhashed) then
            ShowMessage('User exists, Password is fine and active!')
          else
            ShowMessage('User does not exist, Password is wrong or not active!');
        end;
      

      想知道为什么这不起作用。当我输入一个不存在的用户名时,它总是返回 UserCheck 真,从不假。

      【讨论】:

      • 因为 select COUNT(*) 将始终返回一条记录 - 一条记录与数据表中的记录数。使用我的或 gath 的解决方案,不要混合它们。
      • Recordcount 在该查询中将始终返回 1 - 您应该测试结果的值,而不是返回的行数。将您的测试更改为 Result:=(AQ_LOGIN.Fields[0].AsInteger>0);你应该没事。并对这些字符串做点什么——有一天你会被抓住,只是像这样将你的输入连接到 SQL 中! :-)
      • 我现在使用 AQ_LOGIN.SQL.Add('select count(BLOGIN) from BENU where BLOGIN = ''Login'' AND BPW = ''pw''');仍然,这不起作用
      • 在 SQL 中使用 COUNT = 与结果比较:=(AQ_LOGIN.Fields[0].AsInteger>0);在 SQL 中不使用 COUNT = 与结果比较 := (AQ_LOGIN.RecordCount > 0);
      • 现在按预期工作了 :> 谢谢 smok1 和 robsoft 以及 gath
      【解决方案6】:

      由于您使用的是没有连接的 adoquery 组件,我假设数据库都在系统或链接网络上。一个 adotable 组件同样安全,尽管人们总是认为只有 sql 可以工作....使用 adotable.locate 函数或 adoquery.locate 虽然必须先检索表字段,然后才能使其不安全。定位函数已经通过其参数阻止了注入,并且仅根据是否找到它返回一个布尔值。有些人可能会说,我不知道你的应用程序可能不安全,但它的速度要快得多。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-28
        • 1970-01-01
        • 2014-05-25
        • 1970-01-01
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多