【问题标题】:Invalid Column name while column is there列存在时列名无效
【发布时间】:2016-04-17 08:48:43
【问题描述】:

我正在尝试使用 MDI 创建登录窗口。它连接到 SQL Server 表 test。我已经更改了数据类型并删除并重新创建了数据库。我有 2 列:usrpwd,数据类型为 nvarchar

Dim connetionString As String
Dim cnn As SqlConnection

connetionString = "Data Source=.;Initial Catalog=test;User ID=sa;Password=sasql"
cnn = New SqlConnection(connetionString)

Dim cmd As SqlCommand
Dim myreader As SqlDataReader
Dim query As String

query = "Select usr From users WHERE (usr =" + TextBox1.Text + " and pwd = " + TextBox2.Text + ")"
cmd = New SqlCommand(query, cnn)

cnn.Open()
myreader = cmd.ExecuteReader()

If myreader.Read() Then
Else
    MessageBox.Show("Incorrect username/password !", "LOGIN ERROR", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If

cnn.Close()

非常感谢。

【问题讨论】:

  • 要解决您的特定问题,您需要在 SQL 字符串中围绕来自 db 的值添加引号。但这是你最不担心的。查找参数化和 SQL 注入。在继续之前,现在停止并执行此操作。
  • 谢谢 sasfrog。我是初学者,我这样做是为了好玩。我会深入探讨。
  • 构建字符串的最佳方法是在构建后检查它。您可以不带引号看到为什么从数据库中收到该消息。

标签: sql-server vb.net


【解决方案1】:

如果您使用的是 Tortuga.Chain,代码如下所示:

Dim ds As New SqlServerDataSource(connetionString)

Dim user = ds.From("users", new With {.usr = TextBox1.Text, .pwd = TextBox2.Text}).ToString.Execute();

If user Is Not Nothing Then
Else
    MessageBox.Show("Incorrect username/password !", "LOGIN ERROR", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If

如果您想坚持使用原始 ADO.NET 代码,则需要使用参数化查询。

Dim connetionString As String
Dim cnn As SqlConnection

connetionString = "Data Source=.;Initial Catalog=test;User ID=sa;Password=sasql"
cnn = New SqlConnection(connetionString)

Dim cmd As SqlCommand
Dim myreader As SqlDataReader
Dim query As String

query = "Select usr From users WHERE (usr = @user and pwd = @pwd )"
cmd = New SqlCommand(query, cnn)
cmd.Parameters.AddWithValue( "@usr", TextBox1.Text)
cmd.Parameters.AddWithValue( "@pwd", TextBox2.Text)

cnn.Open()
myreader = cmd.ExecuteReader()

If myreader.Read() Then
Else
    MessageBox.Show("Incorrect username/password !", "LOGIN ERROR", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If

cnn.Close()

【讨论】:

    【解决方案2】:

    connectionString 的值中删除空格。

    您的查询比较文本数据,除非用户在文本框的开头和结尾输入',否则该数据无效。这在语法上是正确的:

    "Select usr From users WHERE (usr ='" + TextBox1.Text + "' and pwd = '" + TextBox2.Text + "')"
    

    但在逻辑上存在缺陷,因为用户可能会尝试将恶意 SQL 注入您的文本框。您的应用程序非常不安全。您必须protect it against SQL injection 并且您还需要encrypt the password 的用户。

    【讨论】:

    • 你知道错了,为什么要提供一个不使用参数化查询的例子呢?
    • @JonathanAllen,谁“提供”了这个例子? “但逻辑上有缺陷”的哪一部分让你感到困惑?我描述了它在语法上是正确的,但在逻辑上是有缺陷的。所以你不同意我的陈述,同意它。恭喜:)
    • 这不仅仅是“逻辑上的缺陷”,它完全不起作用。如果我的用户名是“O'Malley”,即使不尝试 SQL 注入攻击,我也会破坏您的代码。
    • @JonathanAllen,在某些情况下它不会失败。这意味着您的陈述“完全行不通”是错误的。您指出存在失败的情况,这是真的。这就是我们,开发人员所说的错误。这是逻辑缺陷。本文将为您介绍“bug”的概念:en.wikipedia.org/wiki/Software_bug
    • @JonathanAllen,关于您必须使用参数化查询的声明,我必须告诉您,这也是有缺陷的。如果他想在查询中输入参数但正确地转义它们或保证不会有问题(在我的回答中也提到过)。例如,如果 foo 是一个数字,那么我认为“从 id=”+ foo 的买家中选择名称没有问题。我指定应该防止注入攻击,如果它们被防止得好,那么你提到的错误就不会发生。因此,如果您愿意,您需要参数化查询的声明是
    猜你喜欢
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-18
    • 2021-08-02
    相关资源
    最近更新 更多