目前我的代码很容易受到SQL注入的攻击,因为我只是测试它。
我用来从dbo.Account
中检索记录的方式var condition = String.Format("[Username] = '{0}' AND [Password] = '{1}' AND Active = 1", username, password);
var account = new Data.Account().Select(condition, string.Empty, 0, 0);
public List<Model.Account> Select(string condition, string orderBy, int limit = 0, int offset = 0)
{
var list = new List<Model.Account>();
var query = "SELECT " + TABLE_COLUMN + " FROM [DBO].[ACCOUNT]";
if (condition != string.Empty)
query += " WHERE " + condition;
if (orderBy != string.Empty || limit > 0)
query += " ORDER BY " (orderBy == string.Empty ? "ID DESC" : orderBy);
if (limit > 0)
query += " OFFSET " + offset + " ROWS FETCH NEXT " + limit + " ROWS ONLY";
using (var db = new SqlManager())
{
using (var reader = db.ExecuteReader(query))
{
while (reader.Read())
{
var item = BindData(reader);
list.Add(item);
}
}
}
}
现在我正在尝试使用SqlParameter
创建一个字符串,如下所示:
SqlCommand condition = new SqlCommand("[Username] = @Username AND [Password] = @Password");
condition.Parameters.AddWithValue("@Username", username);
condition.Parameters.AddWithValue("@Password", password);
var account = GetAccountByCondition(condition.CommandText);
如何获得SqlCommand
字符串以及包含的用户名和密码值?
我这样做是因为我的数据访问层是通过程序生成的。条件的String.Format确实是错误的。
我正在使用的SqlManager
课程供您参考:
public class SqlManager : IDisposable
{
private SqlConnection _connection;
public SqlConnection Connection
{
get { return _connection; }
}
private SqlCommand _command;
public SqlCommand Command
{
get { return _command; }
}
private SqlTransaction _transaction;
public SqlTransaction Transaction
{
get { return _transaction; }
}
private List<SqlParameter> _parameters = new List<SqlParameter>();
public List<SqlParameter> Parameters
{
get { return _parameters; }
set { _parameters = value; }
}
public SqlManager()
{
var constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
_connection = new SqlConnection(constr);
_command = new SqlCommand();
_connection.Open();
}
public int ExecuteNonQuery(string commandText)
{
return ExecuteNonQuery(commandText, CommandType.Text);
}
public int ExecuteNonQuery(string commandText, CommandType commandType)
{
_command.Connection = _connection;
_command.Transaction = _transaction;
_command.CommandType = commandType;
_command.CommandText = commandText;
_command.Parameters.Clear();
_command.Parameters.AddRange(_parameters.ToArray());
return _command.ExecuteNonQuery();
}
public object ExecuteScalar(string commandText)
{
return ExecuteScalar(commandText, CommandType.Text);
}
public object ExecuteScalar(string commandText, CommandType commandType)
{
_command.Connection = _connection;
_command.Transaction = _transaction;
_command.CommandType = commandType;
_command.CommandText = commandText;
_command.Parameters.Clear();
_command.Parameters.AddRange(_parameters.ToArray());
return _command.ExecuteScalar();
}
public IDataReader ExecuteReader(string commandText)
{
return ExecuteReader(commandText, CommandType.Text);
}
public IDataReader ExecuteReader(string commandText, CommandType commandType)
{
_command.Connection = _connection;
_command.CommandType = commandType;
_command.CommandText = commandText;
_command.Parameters.Clear();
_command.Parameters.AddRange(_parameters.ToArray());
return _command.ExecuteReader();
}
public XmlReader ExecuteXml(string commandText)
{
return ExecuteXml(commandText, CommandType.Text);
}
public XmlReader ExecuteXml(string commandText, CommandType commandType)
{
_command.Connection = _connection;
_command.CommandType = commandType;
_command.CommandText = commandText;
_command.Parameters.Clear();
_command.Parameters.AddRange(_parameters.ToArray());
return _command.ExecuteXmlReader();
}
public DataTable ExecuteDataTable(string commandText)
{
return ExecuteDataTable(commandText, CommandType.Text);
}
public DataTable ExecuteDataTable(string commandText, CommandType commandType)
{
_command.Connection = _connection;
_command.CommandType = commandType;
_command.CommandText = commandText;
_command.Parameters.Clear();
_command.Parameters.AddRange(_parameters.ToArray());
var dt = new DataTable();
dt.Load(_command.ExecuteReader());
return dt;
}
public void AddParameter(string paraName, object objectValue)
{
AddParameter(paraName, objectValue, ParameterDirection.Input);
}
public void AddParameter(string paraName, object objectValue, ParameterDirection direction)
{
var para = new SqlParameter();
para.ParameterName = paraName;
para.Direction = direction;
para.Value = objectValue;
_parameters.Add(para);
}
public void BeginTransaction()
{
_transaction = _connection.BeginTransaction();
}
public void Commit()
{
if (_transaction != null)
{
_transaction.Commit();
}
}
public void Rollback()
{
if (_transaction != null)
{
_transaction.Rollback();
}
}
public void Dispose()
{
GC.SuppressFinalize(this);
if (_connection.State == ConnectionState.Open)
{
_connection.Close();
}
_connection = null;
_command = null;
_transaction = null;
}
}
答案 0 :(得分:1)
您可以构建SELECT查询并将其分配给SqlCommand对象
Dim cmd As SqlCommand
cmd = New SqlCommand("SELECT * FROM [DBO].[ACCOUNT] WHERE [Username] = @username AND [Password] = @pwd AND Active = 1")
cmd.Parameters.Add(New SqlParameter("@username", txtName.Text))
cmd.Parameters.Add(New SqlParameter("@pwd", txtId.Text))
然后使用Parameters.Add方法将参数名称和值传递给prevent SQL injection,因为我也尝试在参考文档中解释。
由于您的SQL查询比上面的代码更复杂,您可以使用带有参数占位符的字符串查询变量动态构建SQL命令,然后最终将其分配给SqlCommand对象