Работа с полем varbinary в VB.NET - PullRequest
2 голосов
/ 10 июня 2009

Наш партнер звонит в веб-сервис, который включает параметр, называемый токен. Токен является результатом хеширования MD5 из двух чисел и помогает нам подтвердить, что пользователь использует нашу систему партнеров. Наш партнер запрашивает у пользователя две строки, объединяет их, запускает их через MD5 и затем вызывает наш веб-сервис. Результатом MD5 является токен, и он представляется нам в виде строки.

Мы храним действительные токены в БД - так как мы используем SQL Server для вычисления токенов с нашей стороны, SQL, похоже, был наиболее счастливым для хранения токенов как varbinary, что является его собственным результатом для вычисления MD5.

У нас есть два фрагмента кода, которые пытаются сделать то же самое - выполнить запрос на выборку, который извлекает значение на основе представленного токена. Один использует динамический запрос (что является проблемой), но он работает. Другой пытается сделать то же самое параметризованным (более безопасным) способом, он не работает - он не может найти токен.

Вот две конкурирующие попытки. Во-первых, параметризованная версия, которая не работает:

byteArrayToken = System.Text.UnicodeEncoding.Unicode.GetBytes(stringToken)
scSelectThing.CommandText = "select thing from tokenstable where token=@token"
Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary)
param.Value = byteArrayToken
lbOutput2.Text = scSelectThing.ExecuteScalar()

И, во-вторых, версия строки динамического запроса, которая работает:

Dim scSelectThing As New SqlCommand
 scSelectThing.CommandText = "select thing from tokenstable where token=convert(varbinary, " + stringToken + " )"
lbOutput2.Text = scSelectThing.ExecuteScalar()

Когда мы запускаем профилировщик SQL, это то, что фактически выполняется для БД:

exec sp_executesql N'select thing from tokenstable where token=@token',N'@token varbinary(68)',@token=0x3000780046003800380034004100450036003400430038003300440033004100380034003800460046004300380038004200390034003400330043004200370042004600

Мне это не кажется правильным, похоже, что мы делаем что-то, что приводит к тому, что что-то в стеке делает неправильное преобразование куда-то.

Есть идеи, что это будет? Очевидно, что его нельзя запускать с динамическим запросом.

Edit:

Строка является результатом хеширования MD5. Чтобы заставить его работать в Query Analyzer, мы делаем это:

select * from tokenstable where 
token=convert(varbinary, 0xF664AE32C83D3A848FFC88B9443CB7BF )

Обратите внимание на отсутствие кавычек, если мы цитируем его, запрос не выполняется. Поле, которое мы сравниваем, - это varbinary, где SQL Server хранит результаты вычислений MD5 с нашей стороны.

1 Ответ

2 голосов
/ 10 июня 2009

Вероятно, ваша проблема в том, что строковые-> двоичные преобразования используют разные кодировки. Попробуйте использовать System.Text.Encoding.ASCII вместо Unicode и посмотрите, поможет ли это вам. Я предполагаю, что convert() рассматривает вашу строку как varchar вместо nvarchar и использует ASCII вместо Unicode для своей собственной строки-> двоичного преобразования.

Редактировать

Кроме того, является ли эта строка фактическим двоичным эквивалентом хеш-функции, или это шестнадцатеричное представление?

Редактировать 2

Тогда ваша проблема заключается в том, что вы передаете двоичное представление шестнадцатеричного представления ваших двоичных данных. Это достаточно запутанно?

Вам просто нужно преобразовать шестнадцатеричный string в массив byte, прежде чем добавить его в качестве значения для вашего параметра. Это можно сделать с помощью следующего кода, взятого из ответа на на этот вопрос (и переведенного на VB.NET):

Public Shared Function StringToByteArray(ByVal hex As String) As Byte()
    Dim NumberChars As Integer = hex.Length

    Dim bytes(NumberChars / 2) As Byte

    For i As Integer = 0 To NumberChars - 1 Step 2
        bytes(i / 2) = Convert.ToByte(hex.Substring(i, 2), 16)
    Next

    Return bytes
End Function

Итак, ваш код будет выглядеть примерно так ...

byteArrayToken = StringToByteArray(stringToken)
scSelectThing.CommandText = "select thing from tokenstable where token=@token"
Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary)
param.Value = byteArrayToken
lbOutput2.Text = scSelectThing.ExecuteScalar()
...