2009-06-10 6 views
2

Ein Partner von uns ruft einen Webdienst an, der einen Parameter enthält, der als Token bezeichnet wird. Token ist das Ergebnis eines MD5-Hashs aus zwei Zahlen und hilft uns dabei, zu authentifizieren, dass der Benutzer unser Partnersystem verwendet. Unser Partner fragt den Benutzer nach zwei Strings, verknüpft sie miteinander, führt sie über MD5 aus und ruft dann unseren Web-Service an. Das Ergebnis des MD5 ist das Token, das uns als String übergeben wird.Umgang mit einem varbinary-Feld in VB.NET

Wir speichern gültige Tokens in einer DB - da wir den SQL Server verwenden, um die Token an unserem Ende zu berechnen, schien SQL am glücklichsten zu sein, die Tokens als varbinary zu speichern, was das native Ergebnis für eine MD5-Berechnung ist.

Wir haben zwei Codeabschnitte, die versuchen, das Gleiche zu tun - führen Sie eine Select-Abfrage aus, die einen Wert basierend auf dem übergebenen Token ausliest. Man verwendet eine dynamische Abfrage (was ein Problem ist), aber es funktioniert. Der andere versucht das Gleiche auf parametrisierte (sichere) Weise zu tun, es funktioniert nicht - es ist nicht in der Lage, das Token zu lokalisieren.

Hier sind die zwei konkurrierenden Versuche. Zunächst wird die parametrisierte Version, die fehlschlägt:

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() 

Und zweitens die dynamische Abfrage-String-Version, die funktioniert:

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

Wenn wir die SQL Profiler ausführen, das ist, was eigentlich gegen die DB ausgeführt wird :

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

Dies ist für mich nicht gut aussieht, sieht es aus, als ob wir etwas, das etwas in den Stapel führt tun irgendwo die falsche Umwandlung zu tun.

Irgendwelche Ideen, was das wäre? Es ist offensichtlich nicht akzeptabel, mit einer dynamischen Abfrage dort zu starten.

Edit:

Der String ist ein MD5-Hash-Ergebnis. Um es in Query Analyzer zu machen arbeiten wir dies tun:

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

Hinweis das Fehlen von Anführungszeichen, wenn wir sie zitieren die Abfrage fehlschlägt. Das Feld, mit dem wir vergleichen, ist ein varbinary, in dem SQL Server die Ergebnisse der MD5-Berechnungen an unserem Ende gespeichert hat.

+0

Antwort aktualisiert ... müssen Sie zuerst von hex in ein Byte-Array konvertieren. –

Antwort

2

Ihr Problem ist wahrscheinlich, dass die Zeichenfolge -> binäre Konvertierungen verschiedene Kodierungen verwenden. Versuchen Sie, System.Text.Encoding.ASCII anstelle von Unicode zu verwenden, und sehen Sie, ob das den Trick für Sie tut. Meine Vermutung ist, dass convert() Ihre Zeichenfolge als varchar anstelle von betrachtet und ASCII anstelle von Unicode für seine eigene Zeichenfolge-> Binär-Konvertierung verwendet.

bearbeiten

Auch ist diese Zeichenfolge eine tatsächliche binäre Äquivalent zu dem Hash, oder ist es eine hexadezimale Darstellung?

Edit 2

Dann ist das Problem, dass Sie die binäre Darstellung der hexadezimale Darstellung Ihrer Binärdaten vorbei sind. Das verwirrend genug?

Sie müssen nur das Hex string in ein byte Array konvertieren, bevor Sie es als Wert für Ihren Parameter hinzufügen. Sie können mit dem folgenden Code tun, aus der Antwort auf this question genommen (und übersetzt in 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 

So wird Ihr Code wie folgt aussehen ...

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

Die Eingabe-Zeichenkette, die wir als Varbinary gespeichert haben, ist eine Hexadezimaldarstellung, wie sie von PHPs md5() zurückgegeben wird. –

+0

Funktioniert! Perfekter Dank für Ihre Hilfe! –