简体   繁体   English

使用SqlCommand的最佳实践

[英]Best practices for using SqlCommand

I would like to make sure when using SqlCommand that I am using best practices, particularly with regards to security. 我想确保在使用SqlCommand时,我正在使用最佳实践,尤其是在安全性方面。

Considerations that I am not sure about: 我不确定的注意事项:

  1. Is it ok to manually build the string by appending? 可以通过追加来手动构建字符串吗? If not, how should I do it? 如果没有,我该怎么办?
  2. What classes should I be looking at using instead? 我应该使用什么类代替?

If your first question is talking about building SQL by including the values directly, that's almost certainly not okay. 如果您的第一个问题是谈论通过直接包含值来构建SQL,那几乎肯定不是一件好事。 It opens you up to SQL injection attacks, as well as issues with conversions (eg having to get the right date/time format). 它使您容易遭受SQL注入攻击以及转换问题(例如,必须获取正确的日期/时间格式)。

Instead, you should use a parameterized query , and set the values in the parameters. 相反,您应该使用参数化查询 ,并在参数中设置值。 See the docs for SqlCommand.Parameters for an example. 有关示例,请参见SqlCommand.Parameters的文档。

Out of interest, do you have a particular reason for using SQL directly instead of using one of the many ORMs around? 出于兴趣,您是否有直接使用SQL而不是使用众多ORM之一的特殊原因? (LLBL, Entity Framework, NHibernate, LINQ to SQL, SubSonic, Massive, SimpleData, Dapper...) (LLBL,实体框架,NHibernate,LINQ to SQL,SubSonic,Massive,SimpleData,Dapper ...)

I would say use of parameters is one of the most important aspects for security. 我会说参数的使用是安全性最重要的方面之一。 This will prevent SQL Injection into your database. 这样可以防止将SQL注入到数据库中。 The following SQLCommand is an example of how I would construct one (in VB.NET, apologies - no C# knowledge - yet ;)) 下面的SQLCommand是我将如何构造一个示例(在VB.NET中,抱歉,尚不具备C#知识;);)

Dim cmd as New SqlCommand("sp_StoredProcedure", Conn)
cmd.commandType = commandtypes.storedprocedure
cmd.parameters.add("@ID",sqldbtype.int).value = myID
cmd.executenonquery

And an example of an inline SqlCommand: 内联SqlCommand的示例:

Dim cmd as New SqlCommand("SELECT Name, Message FROM [Table] WHERE ID=@ID", Conn)
cmd.commandType = commandtypes.storedprocedure
cmd.parameters.add("@ID",sqldbtype.int).value = myID
cmd.executenonquery

My advice: be lazy. 我的建议:懒惰。 Writing voluminous code is a good way to make brain-dead errors (wrong data type, null checks, missing Dispose(), etc), and it has zero performance advantage over many of the helper tools. 编写大量代码是犯人脑致命错误(错误的数据类型,空检查,缺少的Dispose()等)的好方法,并且与许多辅助工具相比,它的性能优势为零

Personally, I'm a big fan of dapper (but I'm somewhat biased), which makes things easy: 就个人而言,我是小巧的狂热爱好者(但我有些偏见),这使事情变得容易:

int customerId = ...
var orders = connection.Query<Order>(
    @"select * from Customers where CustomerId = @customerId",
    new { customerId });

Which will do parameterisation and materialisation for you without pain, and stupidly fast. 它将为您轻松完成参数化和实现,而不会带来痛苦。

For other scenarios, and in particular when you want to use OO techniques to update the system, an ORM such as EF or L2S will save you work while (and giving you better type-checking via LINQ). 对于其他情况,尤其是当您想使用OO技术来更新系统时,诸如EF或L2S之类的ORM将节省您的工作时间(并通过LINQ为您提供更好的类型检查)。

I think this is the best solution 我认为这是最好的解决方案

    SqlConnection cn = new SqlConnection(strCn);
        try
        {
            using (SqlCommand cmd = new SqlCommand("select * from xxxx", cn))
            {
                cn.Open();

                //do something

                cn.Close();
            }
        }
        catch (Exception exception)
        {
            cn.Close();
            throw exception;
        }

Depending, when I do POC or personnal small projects I normally build my strings manually but when im in a project for work we have a template for DB usage and connection that I must use and can't reveal here obviously. 取决于,当我进行POC或个人小型项目时,我通常会手动构建字符串,但是当我在一个正在工作的项目中时,我们有一个数据库使用和连接模板,我必须使用该模板,而此处显然无法透露。

But I think it's ok to manually build for basic operations in small project or POC. 但是我认为手动构建小型项目或POC中的基本操作是可以的。

  • Edit : Like Jon said though you should always use somehting like SqlCommand.Parameters when building your own command. 编辑:像乔恩所说,尽管在构建自己的命令时应始终使用类似SqlCommand.Parameters的方式。 Sorry if I wasn't clear. 对不起,如果我不清楚。

If you're concerned about security, I recommend create your queries as Stored Procedures inside the SQL Server Database instead (to prevent worrying about SQL injection), and then from the front end code, just generate a SQL Stored Procedure, add the parameters, and do it that way. 如果您担心安全性,建议您在SQL Server数据库内部将查询创建为存储过程(以防止担心SQL注入),然后从前端代码中生成一个SQL存储过程,添加参数,然后那样做

This article should help you out with setting this up. 这个文章应该帮助您与设置此功能。

You should always use the practice of applying the least privileges to database connections by communicating with the database through stored procedures. 您应该始终使用通过存储过程与数据库进行通信的方式,将最小特权应用于数据库连接。

Store Procs 商店程序

using System.Data;
using System.Data.SqlClient;
using (SqlConnection connection = new SqlConnection(connectionString))
{
  DataSet userDataset = new DataSet();
  SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure", connection);
  myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
  myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
  myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
  myCommand.Fill(userDataset);
}
  • The credentials for the connection string to the database: A. Integrated Security for corporate/intranet B. Keep it encrypted in the registry or a file in Hosting Providers. 数据库连接字符串的凭据:A.公司/内联网的集成安全性B.在注册表或主机提供程序中的文件中对其进行加密。

  • Always be on the lookout for hackers trying to upload cross scripting into your forms. 始终注意黑客试图将跨脚本上传到您的表单中。

  • Always check the input for SQL injection. 始终检查输入以进行SQL注入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM