[ad_1]
SQLサーバーデータベースを使用してアプリケーションを開発しました。 管理者と通常のユーザーによるユーザーログイン用のテーブルがあります。 通常のユーザーでログインすると、通常のユーザーだけでなく管理者用のフォームも開きます。 つまり、通常のユーザーでログインすると 2 つのフォームが開きます。 手伝ってください。
私が試したこと:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Data.SqlClient; namespace Stokvel_Management_System { public partial class Login : Form { public Login() { InitializeComponent(); } public string constring = "Data Source=LAPTOP-TINYIKOB\\SQLEXPRESS;Initial Catalog=Stokvel;Integrated Security=True"; private void BtnLogin_Click(object sender, EventArgs e) { SqlConnection con = new SqlConnection(constring); con.Open(); SqlDataAdapter da = new SqlDataAdapter("select count(*) from loginTab where UserName='" + txtUsername.Text + "' and Password='" + txtPassword.Text + "'and Type='" + UsercomboBox.Text + "'", con); DataTable dt = new DataTable(); da.Fill(dt); if (dt.Rows[0][0].ToString() == "1") { SqlDataAdapter da1 = new SqlDataAdapter("select Type from loginTab where UserName='" + txtUsername.Text + "' and Password='" + txtPassword.Text + "'", con); DataTable dt1 = new DataTable(); da1.Fill(dt1); if (dt1.Rows[0][0].ToString() == "Admin") con.Close(); { Hide(); Admin ad = new Admin(); ad.Show(); } if(dt1.Rows[0][0].ToString()=="User") { Hide(); User us = new User(); us.Show(); } } } } }
解決策 1
最初に対処しなければならない最悪の問題があるので、最後に気づいたことを説明します。
1) SQL コマンドを作成するために文字列を連結しないでください。 偶発的または意図的な SQL インジェクション攻撃にさらされ、データベース全体が破壊される可能性があります。 代わりに常にパラメータ化されたクエリを使用してください。
文字列を連結すると、SQL が次のようなコマンドを受け取るため、問題が発生します。
SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
SQL に関する限り、ユーザーが追加した引用符によって文字列が終了するため、問題が発生します。 しかし、さらに悪化する可能性もあります。 代わりに「x’;DROP TABLE MyTable;–」と入力すると、SQL はまったく異なるコマンドを受け取ります。
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
SQL では、次の 3 つの個別のコマンドとして認識されます。
SELECT * FROM MyTable WHERE StreetAddress = 'x';
完全に有効な SELECT
DROP TABLE MyTable;
完全に有効な「テーブルの削除」コマンド
--'
それ以外はすべてコメントです。
つまり、一致する行を選択し、DB からテーブルを削除し、それ以外は無視します。
したがって、常にパラメータ化されたクエリを使用してください。 または、DB をバックアップから頻繁に復元できるように準備してください。 バックアップは定期的に取っていますよね?
そしてログイン画面では? DB を破壊するのにユーザーである必要さえないので、これは明らかに自殺行為です。
2) パスワードをクリア テキストで保存しないでください。これは重大なセキュリティ リスクです。 その方法については、ここにいくつかの情報があります。 パスワードの保管: その方法。[^]
覚えておいてください。欧州連合のユーザーがいる場合は GDPR が適用されるため、パスワードを機密データとして扱い、安全な方法で保存する必要があります。 テキストはそのどちらでもないので、罰金は …. うーん … 未払いになる可能性があります。 2018年12月、ドイツの企業はそれだけの理由で2万ユーロという比較的低額の罰金を科せられた。
3) DB が行を返したかどうかはチェックしません。入力を間違えると、「インデックスが範囲外です」エラーがスローされ、アプリがクラッシュします。
4) 管理者の接続のみを閉じます。 接続を手動で閉じる代わりに、DB コード全体を次のように囲みます。 using
ブロックすると、システムが自動的に整理してくれます。
5) あなたが気づいた問題 … コードを見てください。
if (dt1.Rows[0][0].ToString() == "Admin") con.Close(); { Hide(); Admin ad = new Admin(); ad.Show(); }
条件が一致すると、接続が閉じられます。その後、条件が一致しなかった場合でも、常に中括弧内のコードが実行されます。
解決策 2
それは私には非常に複雑に思えます。 本当に必要なのは、指定されたユーザー名とパスワードに一致する行を読み取り、ユーザー タイプを返すことだけです。 その情報を使用して、管理フォームまたはユーザー フォームを開くことができます。 1 行を読み取るためだけに 2 つのデータアダプターとデータテーブルを作成すると、リソースが多少無駄になります。 何かのようなもの:
string queryString = "select Type from loginTab where UserName='" + txtUsername.Text + "' and Password='" + txtPassword.Text + "'"; string usertype = "None"; using (SqlConnection connection = new SqlConnection( connectionString)) { SqlCommand command = new SqlCommand( queryString, connection); connection.Open(); using(SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { usertype = reader[0]; // returned value } } } if (usertype == "Admin") { Hide(); Admin ad = new Admin(); ad.Show(); } else if(usertype == "User") { Hide(); User us = new User(); us.Show(); } else { // invalid type, or no matching record. }
[ad_2]
コメント