7

私は Asp.net が初めてで、クラスを使い始めたばかりです。最近、すべてのファイルに対して新しい接続を繰り返し作成する必要がないように、ほとんどの SQL クエリを処理するクラスを作成しました。

私が作成したメソッドの 1 つは、SQL クエリをパラメーターとして受け取り、結果を返します。SQL インジェクションを避けるために、パラメーター化されたクエリを使用する必要があることはわかっています。私の質問は、クエリを文字列パラメーターとして渡すときにこれを行うにはどうすればよいですか?

たとえば、次のメソッドを呼び出します。

public static DataTable SqlDataTable(string sql)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
    {
        SqlCommand cmd = new SqlCommand(sql, conn);
        cmd.Connection.Open();
        DataTable TempTable = new DataTable();
        TempTable.Load(cmd.ExecuteReader());
        return TempTable;
    }
}

したがって、別のファイルから、このメソッドを次のように使用したいと思います。

DataTable dt = new DataTable();

dt = SqlComm.SqlDataTable("SELECT * FROM Users WHERE UserName='" + login.Text  + "' and Password='" + password.Text + "'");

if (dt.Rows.Count > 0)
{
   // do something if the query returns rows
}

これは機能しますが、それでもインジェクションに対して脆弱でしょうか? 変数をパラメーターとして文字列に渡す方法はありますか? クエリ用に新しい SQLCommand オブジェクトを作成し、Parameters.AddWithValue を使用すれば、これを実行できることはわかっていますが、すべての SQL コマンドを別のクラスに配置したかったのです。

4

4 に答える 4

15

これは機能しますが、それでもインジェクションに対して脆弱でしょうか?

ええ、あなたのコードは SQL インジェクションに対して恐ろしく脆弱です。

SQL インジェクションを避けるために、パラメーター化されたクエリを使用する必要があることはわかっています。

ああ、まったくそうです。

私の質問は、クエリを文字列パラメーターとして渡すときにこれを行うにはどうすればよいですか?

クエリを文字列パラメーターとして渡すべきではありません。代わりに、プレースホルダーとそれらのプレースホルダーの値を含む文字列パラメーターとしてクエリを渡す必要があります。

public static DataTable SqlDataTable(string sql, IDictionary<string, object> values)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
    using (SqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = sql;
        foreach (KeyValuePair<string, object> item in values)
        {
            cmd.Parameters.AddWithValue("@" + item.Key, item.Value);
        }

        DataTable table = new DataTable();
        using (var reader = cmd.ExecuteReader())
        {
            table.Load(reader);
            return table;
        }
    }
}

次に、次のように関数を使用します。

DataTable dt = SqlComm.SqlDataTable(
    "SELECT * FROM Users WHERE UserName = @UserName AND Password = @Password",
    new Dictionary<string, object>
    {
        { "UserName", login.Text },
        { "Password", password.Text },
    }
);

if (dt.Rows.Count > 0)
{
   // do something if the query returns rows
}
于 2013-07-07T12:41:20.607 に答える
0

あなたは正しい道を進んでおり、私もあなたが求めていることを実際に行ってきました。ただし、関数に文字列を渡すだけでなく、SQL Command オブジェクトを渡します...このようにして、すべてのコマンドとパラメーターを適切に構築し、...ここで、これを実行してください。行く準備ができています。何かのようなもの

public static DataTable SqlDataTable(SqlCommand cmd)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
    {  
        cmd.Connection = conn;   // store your connection to the command object..
        cmd.Connection.Open();
        DataTable TempTable = new DataTable();
        TempTable.Load(cmd.ExecuteReader());
        return TempTable;
    }
}

public DataTable GetMyCustomers(string likeName)
{
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "select * from SomeTable where LastName like "@someParm%";
    cmd.Parameters.Add( "whateverParm", likeName );  // don't have SQL with me now, guessing syntax

    // so now your SQL Command is all built with parameters and ready to go.
    return SqlDataTable( cmd );
}
于 2013-07-07T12:18:46.767 に答える
0

あなたがやろうとしていることは完全に論理的に理にかなっており、なぜこの実装にたどり着くのか理解できます。しかし、あなたがやろうとしていることは非常に危険であり、ASP.NET に慣れていないため、データの管理をより簡単かつ安全にするさまざまなオプションが利用できることに気付いていないかもしれません。

@iamkrillin は、そのようなテクノロジの 1 つ、オブジェクト リレーショナル マッピング (ORM) をほのめかしました。.NET フレームワークは、実際にはEntity Frameworkと呼ばれる ORM のファースト クラス サポートを備えています。ORM を検討するように彼が提案した理由は、実際の設計が原則として ORM の動作方法と非常に似ているためだと思います。これらは、LINQ で簡単にクエリできるデータベース内のテーブルを表す抽象化されたクラスです。LINQ クエリは自動的にパラメーター化されるため、クエリのセキュリティを管理するストレスから解放されます。それらはオンザフライで SQL を生成し (文字列をデータ アクセス クラスに渡すときと同じ方法で)、データ (配列、リストなど) を返す方法がはるかに柔軟です。

ただし、ORM の欠点の 1 つは、学習曲線がかなり急勾配であることです。単純なオプション (EF より少し古いですが) は、型指定されたデータセットを使用することです。型付きデータセットは、ORM を立ち上げるよりも作成がはるかに簡単で、一般に実装もはるかに簡単です。ORM ほど柔軟ではありませんが、単純で安全な解決済みの方法で、あなたがやろうとしていることを正確に達成します。幸いなことに、ASP.NET が最初に公開されたときは、型指定されたデータセットに重点を置いたトレーニング ビデオが提供されていたため、すぐに使いこなせるように、無料で利用できる高品質のさまざまなビデオ/チュートリアルが用意されていました。

于 2013-07-07T05:01:57.503 に答える
-3

私の提案: orm を使用します。今日からたくさんの選択肢があります

于 2013-07-07T04:08:40.950 に答える