2009-06-10 23 views
2

我們的合作伙伴正在調用包含名爲token的參數的Web服務。令牌是兩個數字的MD5哈希結果,並幫助我們驗證用戶使用我們的合作伙伴系統。我們的合作伙伴詢問用戶兩個字符串,連接它們,通過MD5運行它們,然後調用我們的Web服務。 MD5的結果是令牌,它以字符串形式提交給我們。處理VB.NET中的varbinary字段

我們將有效標記存儲在數據庫中 - 因爲我們使用SQL Server來計算標記,所以SQL似乎很高興將標記存儲爲varbinary,這是MD5計算的本機結果。

我們有兩段代碼試圖做同樣的事情 - 運行一個select查詢,根據提交的標記提取一個值。一個使用動態查詢(這是一個問題),但它工作。另一個嘗試以參數化(更安全)的方式做同樣的事情,它不起作用 - 它無法找到令牌。

下面是兩個相互競爭的嘗試。首先,參數化版本,它失敗:

byteArrayToken = System.Text.UnicodeEncoding.Unicode.GetBytes(stringToken) 
scSelectThing.CommandText = "select thing from tokenstable where [email protected]" 
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 tok[email protected]',N'@token varbinary(68)',@token=0x3000780046003800380034004100450036003400430038003300440033004100380034003800460046004300380038004200390034003400330043004200370042004600 

這不看我的權利,它看起來好像我們正在做的事情,導致一些在堆棧中的某個地方做了錯誤的轉換。

任何想法會是什麼?在那裏用動態查詢啓動顯然是不可接受的。

編輯:

該字符串是一個MD5哈希結果。爲了使它在查詢分析器中工作,我們這樣做:

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

請注意缺少引號,如果我們引用它,查詢失敗。我們比較的領域是一個varbinary,其中SQL Server在我們的末端存儲了MD5計算的結果。

+0

回答更新...您需要先將十六進制轉換爲一個字節數組。 – 2009-06-10 18:23:50

回答

2

你的問題很可能是string-> binary轉換使用不同的編碼。嘗試使用System.Text.Encoding.ASCII而不是Unicode,看看這是否適合你。我的猜測是,convert()正在考慮您的字符串是varchar而不是nvarchar,並且正在使用ASCII而不是Unicode進行自己的字符串 - >二進制轉換。

編輯

而且,這是一個字符串實際的二進制等同於散列,或它是一個十六進制表示?

編輯2

那麼你的問題是,你通過你的二進制數據的十六進制表示的二進制表示。這足以令人困惑?

您只需將十六進制數string轉換爲byte數組,然後再將其作爲參數值添加。你可以做到這一點與下面的代碼,從答案帶到this question(並轉換爲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 [email protected]" 
Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary) 
param.Value = byteArrayToken 
lbOutput2.Text = scSelectThing.ExecuteScalar() 
+0

雖然作爲varbinary存儲,但我們擁有的輸入字符串是從PHP的md5()返回的十六進制表示形式。 – 2009-06-10 17:48:57