আমি কীভাবে একটি প্যারামিটারাইজড এসকিউএল কোয়েরি তৈরি করব? আমি কেন?


94

আমি শুনেছি যে "প্রত্যেকে" এসকিউএল ইনজেকশন আক্রমণ থেকে রক্ষা করতে প্যারামিটারাইজড এসকিউএল কোয়েরিগুলি ব্যবহার করে প্রতিটি ব্যবহারকারীর ইনপুটকে ফাঁকি দিয়ে না ফেলে।

তুমি এটা কিভাবে করো? সঞ্চিত পদ্ধতি ব্যবহার করার সময় আপনি কী স্বয়ংক্রিয়ভাবে এটি পান?

সুতরাং আমার বুঝতে এটি অ-প্যারামিটারাইজড:

cmdText = String.Format("SELECT foo FROM bar WHERE baz = '{0}'", fuz)

এটি কি পরামিতি হবে?

cmdText = String.Format("EXEC foo_from_baz '{0}'", fuz)

অথবা এসকিউএল ইঞ্জেকশন থেকে নিজেকে বাঁচানোর জন্য আমার কি আরও কিছু আরও বেশি করে করা দরকার?

With command
    .Parameters.Count = 1
    .Parameters.Item(0).ParameterName = "@baz"
    .Parameters.Item(0).Value = fuz
End With

সুরক্ষা বিবেচনা ছাড়াও প্যারামিটারাইজড কোয়েরিগুলি ব্যবহার করার আরও কী কী সুবিধা রয়েছে?

আপডেট: এই দুর্দান্ত নিবন্ধটি গ্রোটোকের একটি প্রশ্নের উল্লেখের সাথে যুক্ত ছিল। http://www.sommarskog.se/dynamic_sql.html


আমি অবাক করেছিলাম যে স্পষ্টতই এই প্রশ্নটি স্ট্যাকওভারফ্লোতে আগে জিজ্ঞাসা করা হয়নি। খুব ভাল!
তামাস সিজনে

4
ওহ, আছে। অবশ্যই খুব আলাদাভাবে বলা হয়েছে, তবে তা রয়েছে।
জোয়েল কোহোর্ন

10
লিটল ববি টেবিলগুলি আপনার ডেটা ধ্বংস করতে আপনার প্যারাম্যাট্রাইজড ক্যোয়ারী ব্যবহার করা উচিত । প্রতিহত করতে পারেনি :)
জেন্ডার

4
উইথ ব্লক নিয়ে এত খারাপ কী?
লুকার প্রকৃতপক্ষে

4
"উইথ ব্লক সম্পর্কে এত খারাপ কী" প্রশ্নের জন্য কারও কাছে কি # প্রশ্ন আছে?
জিম গণনা

উত্তর:


77

আপনার EXEC উদাহরণটি প্যারামিটারাইজ করা হবে না। এই জাতীয় ইনপুট যাতে ক্ষতির কারণ হতে পারে তা রোধ করতে আপনার প্যারামিটারাইজড ক্যোয়ারীগুলি (কিছু চেনাশোনাতে প্রস্তুত বিবৃতি) দরকার:

'; ড্রপ টেবিল বার; -

এটি আপনার ফুজ ভেরিয়েবলের মধ্যে রাখার চেষ্টা করুন (বা যদি আপনি আপনার বার টেবিলকে মূল্য দেন না)। আরও সূক্ষ্ম এবং ক্ষতিকারক অনুসন্ধানগুলিও সম্ভব।

এসকিএল সার্ভারের সাহায্যে আপনি কীভাবে প্যারামিটারগুলি করেন তা এখানে একটি উদাহরণ:

Public Function GetBarFooByBaz(ByVal Baz As String) As String
    Dim sql As String = "SELECT foo FROM bar WHERE baz= @Baz"

    Using cn As New SqlConnection("Your connection string here"), _
        cmd As New SqlCommand(sql, cn)

        cmd.Parameters.Add("@Baz", SqlDbType.VarChar, 50).Value = Baz
        Return cmd.ExecuteScalar().ToString()
    End Using
End Function

সঞ্চিত পদ্ধতিগুলি কখনও কখনও এসকিউএল ইঞ্জেকশন প্রতিরোধে জমা দেওয়া হয়। তবে, বেশিরভাগ সময় আপনাকে এখনও ক্যোয়ারি প্যারামিটার ব্যবহার করে তাদের কল করতে হবে বা তারা সহায়তা করে না। যদি আপনি একচেটিয়াভাবে সঞ্চিত পদ্ধতি ব্যবহার করেন তবে আপনি অ্যাপ্লিকেশন অ্যাকাউন্টের জন্য SELECT, আপডেট, ALTER, CREATE, মুছে ফেলা ইত্যাদি ইত্যাদির জন্য অনুমতিগুলি বন্ধ করতে পারেন এবং সেভাবে কিছুটা সুরক্ষা পেতে পারেন।


আপনি cmd.Parameters.Add("@Baz", SqlDbType.VarChar, 50).Value = Bazদয়া করে আরও ব্যাখ্যা করতে পারেন ?
কেরি বন্ডোক

4
@ ক্যারিবোনডোক, আপনি কী জানতে চান? সেই রেখাটি এমন একটি প্যারামিটার তৈরি করে @Bazযা টাইপের varchar(50)যা Bazস্ট্রিংয়ের মান নির্ধারিত হয় ।
জেবি কিং

আপনি "কমান্ড.প্রেমিটারস.ডাদিউথভ্যালু (" @ বাজ ", 50)" বলতেও পারেন
গ্যাভিন পার্কিনস

4
@ গ্যাভিনপারকিন্স ধরে নিচ্ছেন যে আপনি বোঝাতে চেয়েছিলেন AddWithValue("@Baz", Baz), আপনি এটি করতে পারেন তবে আপনার করা উচিত নয় , বিশেষত কারণ মানচিত্রে স্ট্রিংয়ের মানগুলি ডিফল্টরূপে nvarcharপ্রকৃত varcharপ্রকারে রূপান্তর করা এমন একটি সাধারণ জায়গা যা সেই লিঙ্কে বর্ণিত প্রভাবগুলিকে ট্রিগার করতে পারে।
জোয়েল কোহোর্ন

15

অবশ্যই শেষটি, অর্থাৎ

নাকি আমার আরও ব্যাপক কিছু করা দরকার ...? (হ্যাঁ, cmd.Parameters.Add())

প্যারামিট্রাইজড ক্যোয়ারির দুটি প্রধান সুবিধা রয়েছে:

  • সুরক্ষা: এসকিউএল ইনজেকশন দুর্বলতাগুলি এড়াতে এটি একটি ভাল উপায়
  • পারফরম্যান্স: আপনি যদি নিয়মিত একই ক্যোয়ারিকে কেবলমাত্র বিভিন্ন প্যারামিটারের সাথে অনুরোধ করেন তবে প্যারামিট্রাইজড ক্যোয়ারী ডাটাবেসটিকে আপনার ক্যোয়ারীগুলি ক্যাশে করার অনুমতি দিতে পারে যা পারফরম্যান্স লাভের যথেষ্ট উত্স।
  • অতিরিক্ত: আপনার ডেটাবেস কোডে তারিখ এবং সময় ফর্ম্যাট করার সমস্যা সম্পর্কে আপনাকে চিন্তা করতে হবে না। একইভাবে, যদি আপনার কোডটি অ-ইংলিশ লোকাল সহ মেশিনগুলিতে চালিত হয়, তবে আপনাকে দশমিক পয়েন্ট / দশমিক কমা নিয়ে সমস্যা হবে না।

5

আপনি আপনার শেষ উদাহরণটি নিয়ে যেতে চান কারণ এটিই কেবলমাত্র সত্যিকারের প্যারামিট্রাইজড। সুরক্ষা উদ্বেগ ছাড়াও (যা আপনি আরও ভাবতে পারেন) এডিও.নেট প্যারামিট্রাইজেশন পরিচালনা করতে দেওয়া ভাল কারণ আপনি যে মানটি দিয়ে যাচ্ছেন তার চারপাশে একক উদ্ধৃতি প্রয়োজন কিনা বা Typeপ্রতিটি প্যারামিটারের পরীক্ষা না করেই তা নিশ্চিত হওয়া যায় না ।

[সম্পাদনা] এখানে একটি উদাহরণ:

SqlCommand command = new SqlCommand(
    "select foo from bar where baz = @baz",
    yourSqlConnection
);

SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@baz";
parameter.Value = "xyz";

command.Parameters.Add(parameter);

4
এর সাথে সুস্পষ্ট:। নেট স্ট্রিংগুলি ইউনিকোড, এবং তাই পরামিতিগুলি ডিফল্টভাবে NVarChar ধরে নেবে। যদি এটি সত্যিই কোনও ভারচার কলাম হয় তবে এটি বড় পারফরম্যান্সের সমস্যা তৈরি করতে পারে।
জোয়েল কোহর্ন

2

বেশিরভাগ লোক পিএইচপি এর পিডিও বা পার্ল ডিবিআইয়ের মতো সার্ভার সাইড প্রোগ্রামিং ল্যাঙ্গুয়েজ লাইব্রেরির মাধ্যমে এটি করতে পারে।

উদাহরণস্বরূপ, পিডিওতে:

$dbh=pdo_connect(); //you need a connection function, returns a pdo db connection

$sql='insert into squip values(null,?,?)';

$statement=$dbh->prepare($sql);

$data=array('my user supplied data','more stuff');

$statement->execute($data);

if($statement->rowCount()==1){/*it worked*/}

এটি ডাটাবেস সন্নিবেশের জন্য আপনার ডেটা এড়িয়ে যাওয়ার যত্ন নেয়।

একটি সুবিধা হ'ল আপনি একটি প্রস্তুত বিবৃতি দিয়ে একটি সন্নিবেশকে বহুবার পুনরাবৃত্তি করতে পারেন, গতির সুবিধা অর্জন করে।

উদাহরণস্বরূপ, উপরের ক্যোয়ারিতে আমি একবার বিবৃতিটি প্রস্তুত করতে পারি এবং তারপরে গুচ্ছ থেকে ডেটা অ্যারে তৈরি করে লুপ করতে পারি - -> যতবার প্রয়োজন ততবার সম্পাদন করে।


1

আপনার কমান্ড পাঠ্যের মতো হওয়া প্রয়োজন:

cmdText = "SELECT foo FROM bar WHERE baz = ?"

cmdText = "EXEC foo_from_baz ?"

তারপরে প্যারামিটারের মান যুক্ত করুন। এই পদ্ধতিটি নিশ্চিত করে যে মান কনানটি কেবলমাত্র মান হিসাবে ব্যবহৃত হবে, অন্য পদ্ধতিতে যদি ভেরিয়েবল ফুজকে সেট করা থাকে

"x'; delete from foo where 'a' = 'a"

আপনি কি দেখতে পাচ্ছেন?


0

এসকিউএল দিয়ে শুরু করার জন্য এখানে একটি স্বল্প শ্রেণি রয়েছে এবং আপনি সেখান থেকে তৈরি করে ক্লাসে যুক্ত করতে পারেন।

মাইএসকিউএল

Public Class mysql

    'Connection string for mysql
    Public SQLSource As String = "Server=123.456.789.123;userid=someuser;password=somesecurepassword;database=somedefaultdatabase;"

    'database connection classes

    Private DBcon As New MySqlConnection
    Private SQLcmd As MySqlCommand
    Public DBDA As New MySqlDataAdapter
    Public DBDT As New DataTable
    Public BindSource As New BindingSource
    ' parameters
    Public Params As New List(Of MySqlParameter)

    ' some stats
    Public RecordCount As Integer
    Public Exception As String

    Function ExecScalar(SQLQuery As String) As Long
        Dim theID As Long
        DBcon.ConnectionString = SQLSource
        Try
            DBcon.Open()
            SQLcmd = New MySqlCommand(SQLQuery, DBcon)
            'loads params into the query
            Params.ForEach(Sub(p) SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value))

            'or like this is also good
            'For Each p As MySqlParameter In Params
            ' SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value)
            ' Next
            ' clears params
            Params.Clear()
            'return the Id of the last insert or result of other query
            theID = Convert.ToInt32(SQLcmd.ExecuteScalar())
            DBcon.Close()

        Catch ex As MySqlException
            Exception = ex.Message
            theID = -1
        Finally
            DBcon.Dispose()
        End Try
        ExecScalar = theID
    End Function

    Sub ExecQuery(SQLQuery As String)

        DBcon.ConnectionString = SQLSource
        Try
            DBcon.Open()
            SQLcmd = New MySqlCommand(SQLQuery, DBcon)
            'loads params into the query
            Params.ForEach(Sub(p) SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value))

            'or like this is also good
            'For Each p As MySqlParameter In Params
            ' SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value)
            ' Next
            ' clears params

            Params.Clear()
            DBDA.SelectCommand = SQLcmd
            DBDA.Update(DBDT)
            DBDA.Fill(DBDT)
            BindSource.DataSource = DBDT  ' DBDT will contain your database table with your records
            DBcon.Close()
        Catch ex As MySqlException
            Exception = ex.Message
        Finally
            DBcon.Dispose()
        End Try
    End Sub
    ' add parameters to the list
    Public Sub AddParam(Name As String, Value As Object)
        Dim NewParam As New MySqlParameter(Name, Value)
        Params.Add(NewParam)
    End Sub
End Class

এমএস এসকিউএল / এক্সপ্রেস

Public Class MSSQLDB
    ' CREATE YOUR DB CONNECTION
    'Change the datasource
    Public SQLSource As String = "Data Source=someserver\sqlexpress;Integrated Security=True"
    Private DBCon As New SqlConnection(SQLSource)

    ' PREPARE DB COMMAND
    Private DBCmd As SqlCommand

    ' DB DATA
    Public DBDA As SqlDataAdapter
    Public DBDT As DataTable

    ' QUERY PARAMETERS
    Public Params As New List(Of SqlParameter)

    ' QUERY STATISTICS
    Public RecordCount As Integer
    Public Exception As String

    Public Sub ExecQuery(Query As String, Optional ByVal RunScalar As Boolean = False, Optional ByRef NewID As Long = -1)
        ' RESET QUERY STATS
        RecordCount = 0
        Exception = ""
        Dim RunScalar As Boolean = False

        Try
            ' OPEN A CONNECTION
            DBCon.Open()

            ' CREATE DB COMMAND
            DBCmd = New SqlCommand(Query, DBCon)

            ' LOAD PARAMS INTO DB COMMAND
            Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))

            ' CLEAR PARAMS LIST
            Params.Clear()

            ' EXECUTE COMMAND & FILL DATATABLE
            If RunScalar = True Then
                NewID = DBCmd.ExecuteScalar()
            End If
            DBDT = New DataTable
            DBDA = New SqlDataAdapter(DBCmd)
            RecordCount = DBDA.Fill(DBDT)
        Catch ex As Exception
            Exception = ex.Message
        End Try


        ' CLOSE YOUR CONNECTION
        If DBCon.State = ConnectionState.Open Then DBCon.Close()
    End Sub

    ' INCLUDE QUERY & COMMAND PARAMETERS
    Public Sub AddParam(Name As String, Value As Object)
        Dim NewParam As New SqlParameter(Name, Value)
        Params.Add(NewParam)
    End Sub
End Class
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.