当 SQLCommand 在单独的类中使用时,请使用参数化的 SQL 查询
本文关键字:参数 请使用 查询 SQL SQLCommand 单独 | 更新日期: 2023-09-27 18:31:59
在我的 ASP.net 应用程序中添加参数化sql查询很有趣。我看过一些关于避免SQL注入的好文章。
string sql = string.Format("INSERT INTO [UserData] (Username, Password, Role, Membership, DateOfReg) VALUES (@Username, @Password, @Role, @Membership, @DateOfReg)");
SqlCommand cmd = new SqlCommand(sql, conn);
try
{
cmd.Parameters.AddWithValue("Username", usernameTB.Text);
cmd.Parameters.AddWithValue("Password", passwordTB.Text);
cmd.Parameters.AddWithValue("Role", roleTB.Text);
cmd.Parameters.AddWithValue("Membership", membershipTB.Text);
cmd.Parameters.AddWithValue("DateOfReg", dorTB.Text);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
查找参考
但是,这种方式对我来说没有用,因为我将数据库连接耦合到单独的类,因为我重用了它。
public class DBconnection{
public int insertQuery(String query) {
int affectedRowCount = 0;
SqlConnection conn = null;
try{
conn = new SqlConnection("Server=localhost;Database=master;UID=sa;PWD=sa;");
SqlCommand cmd = new SqlCommand( query, conn );
cmd.CommandType = CommandType.Text;
conn.Open( );
affectedRowCount = cmd.ExecuteNonQuery( );
conn.Close( );
} catch ( Exception e ){
String error = e.Message;
}
return affectedRowCount;
}
}
因此,我只使用下面的代码部分来调用上面的类并将值插入数据库。
String SQLQuery1 = insert into Article values('" + Txtname.Text + "','" + TxtNo.Text + "','" + Txtdescription.Text + "' ,0)");
DBconnection dbConn = new DBconnection();
SqlDataReader Dr = dbConn.insertQuery(SQLQuery1);
请帮助我使用参数化sqlString来避免我SQL注入。要使用@name、@ 否和@description而不使用文本框输入。
这样做是完全合理的,但是让你的类回调(lambda/delegate)来获取参数。 这是类中的静态方法,由各种重载实例方法调用:
private static int SqlExec(string ConnectionString, string StoredProcName, Action<SqlCommand> AddParameters, Action<SqlCommand> PostExec)
{
int ret;
using (var cn = new SqlConnection(ConnectionString))
using (var cmd = new SqlCommand(StoredProcName, cn))
{
cn.Open();
cmd.CommandType = CommandType.StoredProcedure;
if (AddParameters != null)
{
AddParameters(cmd);
}
ret = cmd.ExecuteNonQuery();
if (PostExec != null)
{
PostExec(cmd);
}
}
return ret;
}
然后,一个用法示例:
public void Save()
{
Data.Connect().Exec("Project_Update", Cm =>
{
Cm.Parameters.AddWithValue("@ProjectID", ID);
Cm.Parameters.AddWithValue("@PrimaryApplicantID", PrimaryApplicant.IdOrDBNull());
Cm.Parameters.AddWithValue("@SecondaryApplicantID", SecondaryApplicant.IdOrDBNull());
Cm.Parameters.AddWithValue("@ProjectName", ProjectName.ToDBValue());
});
}
也可以使用非存储过程调用执行此操作。
在您的情况下,它看起来像:
DBconnection.InsertQuery(
"INSERT INTO [UserData]
(Username, Password, Role, Membership, DateOfReg)
VALUES (@Username, @Password, @Role, @Membership, @DateOfReg)"
,cmd => {
cmd.Parameters.AddWithValue("Username", usernameTB.Text);
cmd.Parameters.AddWithValue("Password", passwordTB.Text);
cmd.Parameters.AddWithValue("Role", roleTB.Text);
cmd.Parameters.AddWithValue("Membership", membershipTB.Text);
cmd.Parameters.AddWithValue("DateOfReg", dorTB.Text);
}
);
它以您想要的方式将所有数据库内容放在一起,并让 DBconnection 保持其内部隔离。
一个通用的 InsertQuery() 方法,而是编写特定的 InsertQuery 方法?
例如:
public void AddNewUser(User u)
{
var query = "insert Users (name, password) values (@0, @1)";
SqlCommand cmd = new SqlCommand(query, conn);
try
{
cmd.Parameters.AddWithValue("@0", u.UserName);
cmd.Parameters.AddWithValue("@1", u.Password);
}
}
这样做的好处是,所有SQL逻辑都在另一个类中,而不是调用类需要知道如何构造查询等。
它还使您的代码更具可读性,因为您将AddUser
或UpdateUser
或ChangePassword
视为方法调用,并且不必在此时读取 SQL 来尝试猜测程序中发生了什么。
但是,如果你要做这样的事情,你应该看看一些MicroORM,我个人最喜欢的是PetaPoco(或NuGet版本)。
PetaPoco和其他像Massive and Dapper这样的人会让你做这样的事情:
database.Insert(u);
其中 u 是映射到数据库表的用户对象。它使用 ADO.NET 并确保使用 SQL 参数。
我建议使用LINQ to SQL,它会自动参数化所有内容。
问。如何保护 LINQ to SQL 免受 SQL 注入攻击?
答.SQL注入对于通过连接用户输入形成的传统SQL查询来说是一个重大风险。LINQ to SQL 通过在查询中使用 SqlParameter 来避免此类注入。用户输入将转换为参数值。此方法可防止从客户输入中使用恶意命令。
可以使用DataContext
以简单的方式在 SQL 数据库中插入、更新和删除(右键单击项目以添加新项并添加LINQ to SQL Classes
模板,然后使用服务器资源管理器向其添加对象)。
我已经有一段时间没有使用它了,但我相信你的代码看起来有点像这样:
UserData user = new UserData();
user.Username = ...;
user.Password = ...;
user.Role = ...;
user.Membership = ...;
user.DateOfReg = ...;
db.UserDatas.InsertOnSubmit(user);
db.SubmitChanges();
调用 SubmitChanges 时,LINQ to SQL 会自动生成并执行将更改传输回数据库所必需的 SQL 命令。
编辑1:
作为补充说明,要从数据库中检索现有项目,您可以执行以下操作:
var user = (from i in db.UserDatas
where i.UserName == "devan"
select i).Single();
哦,正如我在回答有关带有登录信息的数据库的问题时的标准政策一样,为了上帝的爱和所有神圣的事情,我必须恳求您盐和散列用户的密码。