網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
一、sql注入風(fēng)險(xiǎn)及解決方案
SQL注入是指在事先定義好的SQL語(yǔ)句中注入額外的SQL語(yǔ)句,從此來(lái)欺騙數(shù)據(jù)庫(kù)服務(wù)器的行為。
示例:制作會(huì)員登錄功能。
登錄按鈕代碼如下:
private void btLogin_Click(object sender, EventArgs e)
{
//1-定義連接字符串
string connStr = "server=.;database=DBTEST;uid=sa;pwd=123456";
//2-定義連接對(duì)象,打開(kāi)連接
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
//3-編寫sql語(yǔ)句(此處如果用戶名密碼同時(shí)輸入' 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("用戶名或密碼錯(cuò)誤!");
else
MessageBox.Show("登錄成功!");
}
備注:如果在用戶名和密碼輸入框中同時(shí)輸入' or '1'='1 則可以造成注入,直接登錄成功,因?yàn)橐呀?jīng)改變了原來(lái)sql語(yǔ)句的含義,在查詢條件中有 '1'='1' 的恒等條件。
針對(duì)上述登錄功能的問(wèn)題風(fēng)險(xiǎn)有如下解決方案:
方案一:
對(duì)危險(xiǎn)字符進(jìn)行判斷,在登錄代碼之前加入如下代碼進(jìn)行判斷。
if (this.txtAccount.Text.IndexOf("'") >= 0 || this.txtPwd.Text.IndexOf("'") >= 0)
{
MessageBox.Show("非法登錄!");
return;
}
方案二:
優(yōu)化SQL語(yǔ)句,先根據(jù)用戶名查詢,查詢有記錄在和密碼文本框內(nèi)容進(jìn)行比對(duì)。
private void btLogin_Click(object sender, EventArgs e)
{
//1-定義連接字符串
string connStr = "server=.;database=DBTEST;uid=sa;pwd=123456";
//2-定義連接對(duì)象,打開(kāi)連接
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
//3-編寫sql語(yǔ)句
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("用戶名錯(cuò)誤!");
else
{
if (dt.Rows[0]["MemberPwd"].ToString().Equals(this.txtPwd.Text))
MessageBox.Show("登錄成功!");
else
MessageBox.Show("密碼錯(cuò)誤!");
}
}
方案三:
使用參數(shù)化方式編寫sql語(yǔ)句
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-定義連接對(duì)象,打開(kāi)連接
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
//3-編寫sql語(yǔ)句
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("用戶名或密碼錯(cuò)誤!");
else
MessageBox.Show("登錄成功!");
}
二、參數(shù)化方式實(shí)現(xiàn)增刪改查
此示例在之前項(xiàng)目基礎(chǔ)上進(jìn)行修改,主要將添加數(shù)據(jù)和修改數(shù)據(jù)修改成參數(shù)化方式。
業(yè)務(wù)需求:
- (1)窗體加載的時(shí)候顯示數(shù)據(jù)。
- (2)點(diǎn)擊"添加數(shù)據(jù)"按鈕,彈出新窗體,在新窗體中進(jìn)行數(shù)據(jù)的添加,添加完成后自動(dòng)刷新表格數(shù)據(jù)。
- (3)鼠標(biāo)選中一行,右鍵彈出刪除菜單,可以刪除數(shù)據(jù)
- (4)鼠標(biāo)選中一行,點(diǎn)擊"編輯數(shù)據(jù)"按鈕,彈出新窗體,在新窗體中進(jìn)行數(shù)據(jù)修改,修改后自動(dòng)刷新表格數(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-定義連接對(duì)象,打開(kāi)連接
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
//3-編寫sql語(yǔ)句
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; //自動(dòng)列取消
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("您確定要?jiǎng)h除嗎?", "****系統(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)會(huì)員添加窗體代碼:
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)建連接對(duì)象,打開(kāi)數(shù)據(jù)庫(kù)連接
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
//3-編寫sql語(yǔ)句
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í)行命令的對(duì)象執(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)會(huì)員編輯窗體代碼:
public int MemId { get; set; } //接受外部傳遞過(guò)來(lái)的會(huì)員編號(hào)
//綁定會(huì)員詳情到文本框
private void BindDetail()
{
//1-定義連接字符串
string connStr = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=DBTEST;Data Source=.";
//2-定義連接對(duì)象,打開(kāi)連接
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
//3-編寫sql語(yǔ)句
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("請(qǐng)正確選擇!");
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();
//對(duì)應(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;
//對(duì)應(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ù)庫(kù)
/// <summary>
/// 連接數(shù)據(jù)庫(kù)
/// </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語(yǔ)句前準(zhǔn)備
/// <summary>
/// 準(zhǔn)備執(zhí)行一個(gè)SQL語(yǔ)句
/// </summary>
/// <param name="sql">需要執(zhí)行的SQL語(yǔ)句</param>
public static void PrepareSql(string sql)
{
OpenConn(); //打開(kāi)數(shù)據(jù)庫(kù)連接
adp = new SqlDataAdapter(sql, conn);
}
#endregion
#region 設(shè)置和獲取sql語(yǔ)句的參數(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語(yǔ)句
/// <summary>
/// 執(zhí)行非查詢SQL語(yǔ)句
/// </summary>
/// <returns>受影響行數(shù)</returns>
public static int ExecNonQuery()
{
int result = adp.SelectCommand.ExecuteNonQuery();
conn.Close();
return result;
}
/// <summary>
/// 執(zhí)行查詢SQL語(yǔ)句
/// </summary>
/// <returns>DataTable類型查詢結(jié)果</returns>
public static DataTable ExecQuery()
{
DataTable dt = new DataTable();
adp.Fill(dt);
conn.Close();
return dt;
}
/// <summary>
/// 執(zhí)行查詢SQL語(yǔ)句
/// </summary>
/// <returns>SqlDataReader類型查詢結(jié)果,SqlDataReader需要手動(dòng)關(guān)閉</returns>
public static SqlDataReader ExecDataReader()
{
return adp.SelectCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
/// <summary>
/// 執(zhí)行查詢SQL語(yǔ)句
/// </summary>
/// <returns>查詢結(jié)果第一行第一列</returns>
public static object ExecScalar()
{
object obj = adp.SelectCommand.ExecuteScalar();
conn.Close();
return obj;
}
#endregion
}
原文鏈接:https://www.cnblogs.com/wml-it/p/15967831.html
相關(guān)推薦
- 2022-03-16 Linux下安裝軟件包報(bào)依賴等相關(guān)問(wèn)題的解決方法_Linux
- 2022-03-25 ASP.NET?Core實(shí)時(shí)庫(kù)SignalR簡(jiǎn)介及使用_實(shí)用技巧
- 2022-11-22 Golang分布式鎖詳細(xì)介紹_Golang
- 2022-08-30 android屏幕適配sw規(guī)則
- 2022-10-11 MATLAB中subplot函數(shù)的語(yǔ)法與使用實(shí)例_C 語(yǔ)言
- 2022-01-26 使用Guzzle拓展包請(qǐng)求接口失敗重試
- 2022-07-30 jQuery?UI菜單部件Menu?Widget_jquery
- 2022-11-18 Android?使用壓縮紋理的方案_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支