我们的合作伙伴正在调用包含名为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计算的结果。
答案 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()