处理VB.NET中的varbinary字段

时间:2009-06-10 16:33:00

标签: sql vb.net md5 varbinary

我们的合作伙伴正在调用包含名为token的参数的Web服务。令牌是两个数字的MD5哈希的结果,并帮助我们使用我们的合作伙伴系统验证用户。我们的合作伙伴要求用户输入两个字符串,连接它们,通过MD5运行它们,然后调用我们的Web服务。 MD5的结果是令牌,它以字符串形式提交给我们。

我们在数据库中存储有效令牌 - 因为我们使用SQL Server来计算我们的令牌,SQL似乎最幸福地将令牌存储为varbinary,这是MD5计算的本机结果。

我们有两段代码试图做同样的事情 - 运行一个select查询,根据提交的令牌提取一个值。一个使用动态查询(这是一个问题),但它的工作原理。另一个尝试以参数化(更安全)的方式做同样的事情,它不起作用 - 它无法找到令牌。

这是两次相互竞争的尝试。首先,失败的参数化版本:

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分析器时,这就是对DB实际执行的内容:

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

这对我来说看起来并不合适,看起来我们正在做一些事情,导致堆栈中的某些东西在某处做错误的转换。

任何想法会是什么?在那里启动动态查询显然是不可接受的。

编辑:

该字符串是MD5哈希结果。为了使它在查询分析器中工作,我们这样做:

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

注意缺少引号,如果我们引用它,查询失败。我们要比较的字段是varbinary,其中SQL Server已经存储了MD5计算的结果。

1 个答案:

答案 0 :(得分:2)

您的问题可能是字符串 - >二进制转换使用了不同的编码。尝试使用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 token=@token"
Dim param As SqlParameter = scSelectThing.Parameters.Add("@token", SqlDbType.VarBinary)
param.Value = byteArrayToken
lbOutput2.Text = scSelectThing.ExecuteScalar()