【问题标题】:Keep getting System.Data.SqlClient.SqlException: 'Incorrect syntax near ';'.'不断收到 System.Data.SqlClient.SqlException:'';' 附近的语法不正确。'
【发布时间】:2022-01-13 15:43:33
【问题描述】:

我已经阅读了这个论坛中提供的关于这个问题的许多问题和答案,应用了许多不同的方法并多次更改我的代码,我什至不记得原来的了。

我在以下行中不断收到此错误:

SqlDataReader dr;

错误是

System.Data.SqlClient.SqlException: '';' 附近的语法不正确。'

我在这方面完全是个菜鸟,我是自学的,所以我道歉。

这是在 App.Config 中

<connectionStrings>
    <add name="ConnectionString" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;Initial Catalog=SolAquaMasterDdata;Integrated Security=True"
        providerName="System.Data.SqlClient" />
</connectionStrings>

我在主窗体上的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.SqlClient;
using System.Data;
using System.Configuration;

namespace SolTry
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        SqlConnection conn = new SqlConnection();
        SqlCommand cmd = new SqlCommand();
        
        public MainWindow()
        {
            InitializeComponent();
            conn.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString.ToString();
        }

        private void BtnLogin_Click(object sender, RoutedEventArgs e)
        {
            string User = txtUsername.Text;
            string Pass = txtPassword.Password;

            string str1 = "Please enter a valid Username and Password.";
            string str2 = "The credentials entered do not match any registed users.";
            string str3 = "These login credentials are correct.";

            conn.Open();
            cmd.Connection = conn;
            SqlDataReader dr;
            cmd.CommandText = ("SELECT Status, UserName, Password FROM tblUsers WHERE UserName = @Username and Password = @Password;");
            using (conn)
            {
                //help add parameterization - missing 
                dr = cmd.ExecuteReader();

                if ((string.IsNullOrEmpty(User)) && (string.IsNullOrEmpty(Pass)))
                {
                    MessageBox.Show(str1, "NO CREDENTIALS ENTERED", MessageBoxButton.OK, MessageBoxImage.Error);
                }

                if ((string.IsNullOrEmpty(User)) == false && (string.IsNullOrEmpty(Pass)) == false)
                {
                    if (dr.HasRows.Equals(true))
                    {
                        MessageBox.Show(str3, "LOGIN SUCCESSFUL", MessageBoxButton.OK, MessageBoxImage.Information);
                    }

                    else if (dr.HasRows == false)
                    {
                        MessageBox.Show(str2, "INVALID CREDENTIALS", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
            }
            conn.Close();
        }

        private void ExitApp(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            DragMove();
        }
    }
}

无论我尝试过什么,我总是失败。

我要做的就是在点击登录表单按钮时验证 tblUsers 中的用户名和密码是否正确,然后检查状态是否为“true”或 1

请告诉我如何参数化 sql

【问题讨论】:

  • 不,SqlDataReader dr; 可能不是您收到此特定错误的行。
  • WHERE 缺少右括号。应该是:txt.Password);");
  • 查询还应将txt.Password和txt.Username的文本值放入参数并将这些参数添加到命令中。
  • 您想要传递txt.Password 的值这一事实强烈表明您正在存储纯文本密码。这是一个巨大的安全漏洞。 始终对您的密码进行加盐和哈希处理。
  • @jdweng 我建议它不是缺少一个,它有一个无关紧要的; WHERE 根本不需要用括号括起来。

标签: c# sql-server visual-studio


【解决方案1】:

这行代码在引用的查询文本中的括号不匹配。

cmd.CommandText = ("SELECT Status, UserName, Password 
                    FROM tblUsers WHERE(UserName = txt.Username 
                                        and Password = txt.Password;");

WHERE 后面有一个左括号,引用的文本中没有右括号。这就是您收到 SQL 异常的原因。您可以删除左括号,也可以添加右括号。

另外,您需要使用参数来传递用户名和密码值。字符串 txt.Username 和 txt.Password 对 SQL 服务器没有任何意义。

【讨论】:

    【解决方案2】:

    您现有的代码存在很多问题。

    • 首先,您尝试从 SQL 中引用 C# 对象。您不能这样做,因为服务器根本看不到您的客户端代码。而是使用适当的参数化。
    • 您缺少/多余的括号
    • 您需要在使用点创建和使用using 块处理您的连接、命令和读取器对象。然后您不需要显式关闭,using 会为您关闭它。
    • 连接打开时不要用消息框阻塞线程
    • 实际上没有必要使用阅读器,因为您只想检查单行是否存在。只需SELECT 1 并使用cmd.ExecuteScalar()
    • 不要存储或传递纯文本密码。在客户端对密码进行哈希,并将哈希传递给服务器进行检查。
    if ((string.IsNullOrEmpty(User)) && (string.IsNullOrEmpty(Pass)))
    {
        MessageBox.Show(str1, "NO CREDENTIALS ENTERED", MessageBoxButton.OK, MessageBoxImage.Error);
        return;
    }
    
    bool isMatch;
    
    const string query = @"
    SELECT 1
    FROM tblUsers u
    WHERE u.UserName = @Username
      and u.PasswordHash = @PasswordHash;
    ";
    using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString.ToString()))
    using (var cmd = new SqlCommand(query, conn))
    {
        cmd.Parameters.Add("@UserName", SqlDbType.NVarchar, 250).Value = txt.Username;
        cmd.Parameters.Add("@PasswordHash", SqlDbType.Binary, 32).Value = YourPasswordHashFunctionHere(txt.Password);
        conn.Open();
        isMatch = ((int?)cmd.ExecuteScalar()) == 1;
    }
    
    if (isMatch)
    {
        MessageBox.Show(str3, "LOGIN SUCCESSFUL", MessageBoxButton.OK, MessageBoxImage.Information);
    }
    else
    {
        MessageBox.Show(str2, "INVALID CREDENTIALS", MessageBoxButton.OK, MessageBoxImage.Error);
    }
    

    【讨论】:

    • 大家好,非常感谢你们,我很抱歉,不得不与像我这样的菜鸟打交道一定很令人沮丧,但老实说你们帮了很多忙,@Charlieface 感谢你们更改我的代码.我使用它并输入它,但出现错误,所以只是更改并添加了一两件事,幸运的是它工作了哈哈哈。我不知道如何在 SQL Server 中散列/加密密码或使用盐,所以我不得不接受表单阻止密码的事实。我将尝试在该主题上找到一些东西并学习它。非常感谢大家。
    【解决方案3】:

    您没有向命令发送任何参数。参数化您的查询,然后 sql 将起作用

       cmd.CommandType = System.Data.CommandType.StoredProcedure;
       cmd.CommandText = ("SELECT Status, UserName, Password FROM tblUsers WHERE UserName = @Username and Password = @Password;");
    
       cmd.Parameters.Add("@UserName", SqlDbType.Varchar, 255).Value = txt.Username;
        cmd.Parameters.Add("@Password", SqlDbType.Varchar, 255).Value = txt.Password;
    
        dr = cmd.ExecuteReader();
    

    使用hashbyte对数据库中的密码进行加解密。然后客户端只使用文本。不要在客户端进行散列。保持简单。

      See. https://www.mssqltips.com/sqlservertip/4037/storing-passwords-in-a-secure-way-in-a-sql-server-database/
    
      Hashbytes
    

    【讨论】:

    • 这也可以保护您的应用程序免受 sql 注入。所以即使它不满足你的需要,你也应该这样做。 @TravO
    猜你喜欢
    • 1970-01-01
    • 2021-03-31
    • 2019-07-17
    • 2017-12-08
    • 2014-05-09
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多