5

SQL Server は初めてです

次のようにテーブルを作成しました。

CREATE TABLE Accidents (
     Id INT NOT NULL PRIMARY KEY IDENTITY,
     GUID VARCHAR(100),
     Latitude VARCHAR(100),
     Longitude VARCHAR(100),
     PhotoName VARCHAR(100)        
     )

次のように、そのテーブルにデータを挿入する Web サービスを作成しました。

    SqlConnection con = new SqlConnection(@"workstation id=DatabaseSample.mssql.somee.com;packet size=4096;user id=???;pwd=???;data source=DatabaseSample.mssql.somee.com;persist security info=False;initial catalog=DatabaseSample");

    public string addAccidentToDatabase(string GUID, string imageBase64String, string latitude, string longitude, string photoName)
    {
        SqlCommand cmd = new SqlCommand("INSERT INTO Accidents (GUID,Latitude,Longitude,PhotoName) VALUES ("
            + GUID + "," + latitude + "," + longitude + "," + photoName + ")", con);

        try
        {
            con.Open();
            cmd.ExecuteNonQuery();
        }
        catch (Exception e)
        {
            return e.Message;
        }
        finally
        {
            con.Close();
        }

        return "succeeded";
    }

これらはすべて、無料のホスティング サーバーにホストされています。

VS2010 から Web サービスをテストし、すべてのパラメーターに数値を渡すと、新しい行がテーブルに正常に追加されます。しかし、「a」などの少なくとも 1 つの文字列をサービスに渡すと、次の結果が得られます。

<string xmlns="http://tempuri.org/">Invalid column name 'a'.</string>

行は追加されません。なぜ彼は「a」を列名と考えたのだろうか?誰でも助けることができますか?

4

5 に答える 5

8

なぜ彼は「a」を列名と考えたのだろうか?

それは難しいことではありません。ソフトウェアを開発してデプロイし、それが実行されることを期待するべきではありません。テストする必要があります。実行中のコードをクラス メソッドに抽出し、それをサービスから呼び出します。開発時には、このメソッドを単体テストまたはコマンドライン プログラム、またはテストしたいものから呼び出します。

問題: クエリで文字列 (または必要に応じて varchars) を引用符で囲みません。たとえば、クエリ文字列をコンソールに出力しただけの場合は、それが表示されます。

しかし、正直なところ、それはあなたの問題の中で最も小さいものです. SQL を手作りするべきではありません。少なくともパラメーター化されたクエリを使用します。したがって、クエリを次のようにします。

"INSERT INTO Accidents (GUID, Latitude, Longitude, PhotoName) 
                VALUES (@GUID, @Latitude, @Longitude, @PhotoName)"

パラメータをバインドします。

cmd.Parameters.AddWithValue("@GUID", GUID);
...
于 2013-05-11T21:59:08.333 に答える
4

コードをこれに置き換えてください。

 SqlCommand cmd = new SqlCommand("INSERT INTO Accidents (GUID,Latitude,Longitude,PhotoName) " + 
                                 "VALUES (@guid, @lat, @long, @photo)", con);
 cmd.Parameters.AddWithValue("@guid", GUID);
 cmd.Parameters.AddWithValue("@lat", latitude);
 cmd.Parameters.AddWithValue("@long", longitude);
 cmd.Parameters.AddWithValue("@photo", photoName);

なんで?たとえば、文字列の 1 つに一重引用符が含まれているとします。
クエリは構文エラーで失敗します。しかし、文字列にとどまらないでください。日付と10進数はどうですか?次の顧客が異なる設定で失敗するように、データベースのグローバリゼーション設定に適した方法でそれらをフォーマットする必要があります。パラメータがこれを解決します。

最悪。悪意のあるユーザーが PhotoName の入力ボックスに次のように入力したとします。

 p1.jpg'); DROP TABLE ACCIDENTS; -- 

これは非常に大きな問題です。これはSql Injectionと呼ばれ、そうです、パラメータがこれを防ぎます。機密情報が含まれるデータベースにこのコードを書かないでください。

于 2013-05-11T22:08:34.257 に答える
2

文字列を引用符で囲む必要があります。値を直接代入しているだけなので、SQL はそれらを列として解析しようとしています。

SqlCommand cmd = new SqlCommand("INSERT INTO Accidents (GUID,Latitude,Longitude,PhotoName)    
       VALUES ('" + GUID + "','" + latitude + "','" + longitude + "','" + photoName + "')", con);

ただし、これは非常に安全でないコードであることに注意してください。これは、SQL インジェクションに非常に陥りやすいです。代わりにパラメータ化されたクエリを使用してみてください。

于 2013-05-11T21:59:43.160 に答える
2

あなたの GUID 値は . で始まっていると思いますa。それがで始まったら、3おそらくもっと面白いものになるでしょう。

文字列として渡し、引用符でエスケープしていないため、エラーが発生します。

SqlCommand cmd = new SqlCommand("INSERT INTO Accidents (GUID,Latitude,Longitude,PhotoName) VALUES ("
            + "\"" + GUID + "\"," + latitude + "," + longitude + ",\"" + photoName + "\")", con);

いくつかのポイント:

  1. この方法でクエリを作成することは本当に避けるべきです。ストアド プロシージャまたはパラメーター化されたクエリを使用します。

  2. なぜ aguidを として保存するのvarchar()ですか? 非常に優れたGuidデータ型が利用可能です。

  3. データ型にちなんで列に名前を付けないでください。

于 2013-05-11T21:59:56.130 に答える
1

文字列値には一重引用符が必要です

ただし、攻撃を避けるためにSQLParametersを使用することを強くお勧めしますSQLInjections

ここで SQL パラメータの使用例を見つけることができます

于 2013-05-11T22:00:08.647 に答える