欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ADO.NET防SQL注入與使用參數(shù)增刪改查

 更新時間:2022年05月04日 08:48:18   作者:農(nóng)碼一生  
這篇文章介紹了ADO.NET防SQL注入與使用參數(shù)實(shí)現(xiàn)增刪改查的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、sql注入風(fēng)險(xiǎn)及解決方案

SQL注入是指在事先定義好的SQL語句中注入額外的SQL語句,從此來欺騙數(shù)據(jù)庫服務(wù)器的行為。

示例:制作會員登錄功能。

登錄按鈕代碼如下:

private void btLogin_Click(object sender, EventArgs e)
{
    //1-定義連接字符串 
    string connStr = "server=.;database=DBTEST;uid=sa;pwd=123456";
    //2-定義連接對象,打開連接
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();
    //3-編寫sql語句(此處如果用戶名密碼同時輸入' or '1'='1 則可以造成注入)
    string sql = string.Format("select * from Member where MemberAccount='{0}' and MemberPwd='{1}'"
        ,this.txtAccount.Text,this.txtPwd.Text);
    //4-數(shù)據(jù)適配器抽取信息
    SqlDataAdapter adp = new SqlDataAdapter(sql, conn);
    DataTable dt = new DataTable();  //數(shù)據(jù)表格
    adp.Fill(dt);
    conn.Close();
    if (dt.Rows.Count == 0)
        MessageBox.Show("用戶名或密碼錯誤!");
    else
        MessageBox.Show("登錄成功!");
}

備注:如果在用戶名和密碼輸入框中同時輸入' or '1'='1 則可以造成注入,直接登錄成功,因?yàn)橐呀?jīng)改變了原來sql語句的含義,在查詢條件中有 '1'='1' 的恒等條件。

針對上述登錄功能的問題風(fēng)險(xiǎn)有如下解決方案:

方案一:

對危險(xiǎn)字符進(jìn)行判斷,在登錄代碼之前加入如下代碼進(jìn)行判斷。

if (this.txtAccount.Text.IndexOf("'") >= 0 || this.txtPwd.Text.IndexOf("'") >= 0)
{
    MessageBox.Show("非法登錄!");
    return;
}

方案二:

優(yōu)化SQL語句,先根據(jù)用戶名查詢,查詢有記錄在和密碼文本框內(nèi)容進(jìn)行比對。

private void btLogin_Click(object sender, EventArgs e)
{
    //1-定義連接字符串
    string connStr = "server=.;database=DBTEST;uid=sa;pwd=123456";
    //2-定義連接對象,打開連接
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();
    //3-編寫sql語句
    string sql = string.Format("select * from Member where MemberAccount='{0}'"
        , this.txtAccount.Text);
    //4-數(shù)據(jù)適配器抽取信息
    SqlDataAdapter adp = new SqlDataAdapter(sql, conn);
    DataTable dt = new DataTable();  //數(shù)據(jù)表格
    adp.Fill(dt);
    conn.Close();
    if (dt.Rows.Count == 0)
        MessageBox.Show("用戶名錯誤!");
    else
    {
        if (dt.Rows[0]["MemberPwd"].ToString().Equals(this.txtPwd.Text))
            MessageBox.Show("登錄成功!");
        else
            MessageBox.Show("密碼錯誤!");
    }
}

方案三:

使用參數(shù)化方式編寫sql語句

private void btLogin_Click(object sender, EventArgs e)
{
    //1-定義連接字符串 
    //string connStr = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=.";
    //2-編寫連接字符串(sql用戶名密碼方式連接)
    string connStr = "server=.;database=DBTEST;uid=sa;pwd=123456";
    //2-定義連接對象,打開連接
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();

    //3-編寫sql語句
    string sql = "select * from Member where MemberAccount=@MemberAccount and MemberPwd=@MemberPwd";
    //4-數(shù)據(jù)適配器抽取信息
    SqlDataAdapter adp = new SqlDataAdapter(sql, conn);
    adp.SelectCommand.Parameters.Add(new SqlParameter("@MemberAccount", this.txtAccount.Text));
    adp.SelectCommand.Parameters.Add(new SqlParameter("@MemberPwd",this.txtPwd.Text));
    DataTable dt = new DataTable();  //數(shù)據(jù)表格
    adp.Fill(dt);
    conn.Close();
    if (dt.Rows.Count == 0)
        MessageBox.Show("用戶名或密碼錯誤!");
    else
        MessageBox.Show("登錄成功!");
}

二、參數(shù)化方式實(shí)現(xiàn)增刪改查

此示例在之前項(xiàng)目基礎(chǔ)上進(jìn)行修改,主要將添加數(shù)據(jù)和修改數(shù)據(jù)修改成參數(shù)化方式。

業(yè)務(wù)需求:

  • (1)窗體加載的時候顯示數(shù)據(jù)。
  • (2)點(diǎn)擊"添加數(shù)據(jù)"按鈕,彈出新窗體,在新窗體中進(jìn)行數(shù)據(jù)的添加,添加完成后自動刷新表格數(shù)據(jù)。
  • (3)鼠標(biāo)選中一行,右鍵彈出刪除菜單,可以刪除數(shù)據(jù)
  • (4)鼠標(biāo)選中一行,點(diǎn)擊"編輯數(shù)據(jù)"按鈕,彈出新窗體,在新窗體中進(jìn)行數(shù)據(jù)修改,修改后自動刷新表格數(shù)據(jù)。

實(shí)現(xiàn)步驟如下:

(1)查詢窗體顯示數(shù)據(jù)代碼:

//綁定數(shù)據(jù)的方法
public void BindData()
{
    //1-定義連接字符串 
    //string connStr = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=.";
    //2-編寫連接字符串(sql用戶名密碼方式連接)
    string connStr = "server=.;database=DBTEST;uid=sa;pwd=123456";
    //2-定義連接對象,打開連接
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();
    //3-編寫sql語句
    string sql = "select * from Member";
    //4-數(shù)據(jù)適配器抽取信息
    SqlDataAdapter adp = new SqlDataAdapter(sql, conn);
    DataTable dt = new DataTable();  //數(shù)據(jù)表格
    adp.Fill(dt);
    this.dataGridView1.AutoGenerateColumns = false;   //自動列取消
    this.dataGridView1.DataSource = dt;
    conn.Close();
}
private void FrmSelect_Load(object sender, EventArgs e)
{
    BindData();
}

(2)刪除菜單代碼:

private void 刪除ToolStripMenuItem_Click(object sender, EventArgs e)
{
    DialogResult r = MessageBox.Show("您確定要刪除嗎?", "****系統(tǒng)", MessageBoxButtons.YesNo);
    if (r == System.Windows.Forms.DialogResult.No)
    {
        return;
    }
    int memId = int.Parse(this.dataGridView1.SelectedRows[0].Cells[0].Value.ToString());
    string connStr = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=.";
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();
    string sql = "delete from Member where MemberId = " + memId;
    SqlCommand cmd = new SqlCommand(sql, conn);
    int rowCount = cmd.ExecuteNonQuery();
    conn.Close();
    if (rowCount == 1)
        MessageBox.Show("刪除成功!");
    else
        MessageBox.Show("刪除失敗!");
    BindData();
}

(3)會員添加窗體代碼:

private void btAdd_Click(object sender, EventArgs e)
{
    //1-編寫連接字符串(windows方式連接)
    //string connStr = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=.";
    //2-編寫連接字符串(sql用戶名密碼方式連接)
    string connStr = "server=.;database=DBTEST;uid=sa;pwd=123456";
    //2-創(chuàng)建連接對象,打開數(shù)據(jù)庫連接
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();
    //3-編寫sql語句
    string sql = string.Format("insert into Member(MemberAccount,MemberPwd,MemberName,MemberPhone)  values(@MemberAccount,@MemberPwd,@MemberName,@MemberPhone)"
            , this.txtAccount.Text, this.txtPwd.Text, this.txtNickName.Text, this.txtPhone.Text);
    //4-定義執(zhí)行命令的對象執(zhí)行命令
    SqlCommand cmd = new SqlCommand(sql, conn);
    cmd.Parameters.Add(new SqlParameter("@MemberAccount", this.txtAccount.Text));
    cmd.Parameters.Add(new SqlParameter("@MemberPwd", this.txtPwd.Text));
    cmd.Parameters.Add(new SqlParameter("@MemberName", this.txtNickName.Text));
    cmd.Parameters.Add(new SqlParameter("@MemberPhone", this.txtPhone.Text));
    int rowCount = cmd.ExecuteNonQuery();
    conn.Close();
    if (rowCount == 1)
        MessageBox.Show("添加成功!");
    else
        MessageBox.Show("添加失敗!");
    //刷新查詢窗體數(shù)據(jù)并關(guān)閉當(dāng)前窗體
    ((FrmSelect)this.Owner).BindData();
    this.Close();
}

(4)會員編輯窗體代碼:

public int MemId { get; set; }  //接受外部傳遞過來的會員編號
//綁定會員詳情到文本框
private void BindDetail()
{
    //1-定義連接字符串 
    string connStr = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=.";
    //2-定義連接對象,打開連接
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();
    //3-編寫sql語句
    string sql = "select * from Member where MemberId = " + this.MemId;
    //-抽取數(shù)據(jù)
    SqlDataAdapter adp = new SqlDataAdapter(sql, conn);
    DataTable dt = new DataTable();
    adp.Fill(dt);
    conn.Close();
    this.txtAccount.Text = dt.Rows[0]["MemberAccount"].ToString();
    this.txtPwd.Text = dt.Rows[0]["MemberPwd"].ToString();
    this.txtNickName.Text = dt.Rows[0]["MemberName"].ToString();
    this.txtPhone.Text = dt.Rows[0]["MemberPhone"].ToString();
}
private void FrmEdit_Load(object sender, EventArgs e)
{
    BindDetail();
}
private void btUpdate_Click(object sender, EventArgs e)
{
    string connStr = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=.";
    SqlConnection conn = new SqlConnection(connStr);
    conn.Open();
    string sql = "update Member set MemberAccount=@MemberAccount,MemberPwd=@MemberPwd,MemberName=@MemberName,MemberPhone=@MemberPhone where MemberId=@MemberId";
    SqlCommand cmd = new SqlCommand(sql, conn);
    cmd.Parameters.Add(new SqlParameter("@MemberAccount", this.txtAccount.Text));
    cmd.Parameters.Add(new SqlParameter("@MemberPwd", this.txtPwd.Text));
    cmd.Parameters.Add(new SqlParameter("@MemberName", this.txtNickName.Text));
    cmd.Parameters.Add(new SqlParameter("@MemberPhone", this.txtPhone.Text));
    cmd.Parameters.Add(new SqlParameter("@MemberId", this.MemId));
    int rowCount = cmd.ExecuteNonQuery();
    conn.Close();
    if (rowCount == 1)
        MessageBox.Show("修改成功!");
    else
        MessageBox.Show("修改失敗!");
    //刷新查詢窗體數(shù)據(jù)并關(guān)閉當(dāng)前窗體
    ((FrmSelect)this.Owner).BindData();
    this.Close();
}

(5)查詢窗體"添加數(shù)據(jù)"和"編輯數(shù)據(jù)"按鈕的代碼:

private void btAdd_Click(object sender, EventArgs e)
{
    FrmAdd frm = new FrmAdd();
    frm.Owner = this;
    frm.Show();
}
private void btEdit_Click(object sender, EventArgs e)
{
    if (this.dataGridView1.SelectedRows[0].Cells[0].Value.ToString().Equals(""))
    {
        MessageBox.Show("請正確選擇!");
        return;
    }
    int memId = int.Parse(this.dataGridView1.SelectedRows[0].Cells[0].Value.ToString());
    FrmEdit frm = new FrmEdit();
    frm.MemId = memId;
    frm.Owner = this;
    frm.Show();
}

三、封裝DBHelper類

class DBHelper
{
    //SQL連接字符串-SQL身份認(rèn)證方式登錄
    public static string connStr = "server=.;database=DBTEST;uid=sa;pwd=123456;";

    //SQL連接字符串-Windows身份認(rèn)證方式登錄
    //public static string connStr = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=.";

    //讀取配置文件appSettings節(jié)點(diǎn)讀取字符串(需要添加引用System.Configuration)
    //public static string connStr = ConfigurationManager.AppSettings["DefaultConn"].ToString();
    //對應(yīng)的配置文件如下:
    //<appSettings>
    //  <add key="DefaultConn" value="Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=."/>
    //</appSettings>

    //讀取配置文件ConnectionStrings節(jié)點(diǎn)讀取字符串(需要添加引用System.Configuration)
    //public static string connStr = ConfigurationManager.ConnectionStrings["DefaultConn"].ConnectionString;
    //對應(yīng)配置文件如下:
    //<connectionStrings>
    //    <add name="DefaultConn" connectionString="Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=."/>
    //</connectionStrings>

    public static SqlConnection conn = null;
    public static SqlDataAdapter adp = null;

    #region 連接數(shù)據(jù)庫
    /// <summary>
    /// 連接數(shù)據(jù)庫
    /// </summary>
    public static void OpenConn()
    {
        if (conn == null)
        {
            conn = new SqlConnection(connStr);
            conn.Open();
        }
        if (conn.State == System.Data.ConnectionState.Closed)
        {
            conn.Open();
        }
        if (conn.State == System.Data.ConnectionState.Broken)
        {
            conn.Close();
            conn.Open();
        }
    }
    #endregion

    #region 執(zhí)行SQL語句前準(zhǔn)備
    /// <summary>
    /// 準(zhǔn)備執(zhí)行一個SQL語句
    /// </summary>
    /// <param name="sql">需要執(zhí)行的SQL語句</param>
    public static void PrepareSql(string sql)
    {
        OpenConn(); //打開數(shù)據(jù)庫連接
        adp = new SqlDataAdapter(sql, conn);
    }
    #endregion

    #region 設(shè)置和獲取sql語句的參數(shù)
    /// <summary>
    /// 設(shè)置傳入?yún)?shù)
    /// </summary>
    /// <param name="parameterName">參數(shù)名稱</param>
    /// <param name="parameterValue">參數(shù)值</param>
    public static void SetParameter(string parameterName, object parameterValue)
    {
        parameterName = "@" + parameterName.Trim();
        if (parameterValue == null)
            parameterValue = DBNull.Value;
        adp.SelectCommand.Parameters.Add(new SqlParameter(parameterName, parameterValue));
    }
    #endregion

    #region 執(zhí)行SQL語句
    /// <summary>
    /// 執(zhí)行非查詢SQL語句
    /// </summary>
    /// <returns>受影響行數(shù)</returns>
    public static int ExecNonQuery()
    {
        int result = adp.SelectCommand.ExecuteNonQuery();
        conn.Close();
        return result;
    }
    /// <summary>
    /// 執(zhí)行查詢SQL語句
    /// </summary>
    /// <returns>DataTable類型查詢結(jié)果</returns>
    public static DataTable ExecQuery()
    {
        DataTable dt = new DataTable();
        adp.Fill(dt);
        conn.Close();
        return dt;
    }
    /// <summary>
    /// 執(zhí)行查詢SQL語句
    /// </summary>
    /// <returns>SqlDataReader類型查詢結(jié)果,SqlDataReader需要手動關(guān)閉</returns>
    public static SqlDataReader ExecDataReader()
    {
        return adp.SelectCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }
    /// <summary>
    /// 執(zhí)行查詢SQL語句
    /// </summary>
    /// <returns>查詢結(jié)果第一行第一列</returns>
    public static object ExecScalar()
    {
        object obj = adp.SelectCommand.ExecuteScalar();
        conn.Close();
        return obj;
    }
    #endregion
}

到此這篇關(guān)于ADO.NET防SQL注入與使用參數(shù)增刪改查的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論