处理 VB.NET 中的 varbinary 字段
我们的合作伙伴正在调用一个包含名为令牌的参数的 Web 服务。 令牌是两个数字的 MD5 哈希值的结果,可帮助我们使用我们的合作伙伴系统对用户进行身份验证。 我们的合作伙伴要求用户提供两个字符串,将它们连接起来,通过 MD5 运行它们,然后调用我们的 Web 服务。 MD5的结果就是token,它以字符串的形式提交给我们。
我们将有效令牌存储在数据库中 - 因为我们使用 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
这对我来说看起来不太正确,看起来好像我们正在做的事情会导致堆栈中的某些内容在某处进行错误的转换。
有什么想法吗? 显然,在其中启动动态查询是不可接受的。
编辑:
该字符串是 MD5 哈希结果。 为了使其在查询分析器中工作,我们这样做:
select * from tokenstable where
token=convert(varbinary, 0xF664AE32C83D3A848FFC88B9443CB7BF )
注意缺少引号,如果我们引用它,查询就会失败。 我们要比较的字段是一个 varbinary,其中 SQL Server 已在我们这边存储了 MD5 计算的结果。
A partner of ours is making a call to a web service that includes a parameter called token. Token is the result of an MD5 hash of two numbers, and helps us authenticate that the user using our partners system. Our partner asks the user for two strings, concatenates them, runs them through MD5, and then calls our web service. The result of the MD5 is the token, and it is submitted to us as a string.
We store valid tokens in a DB - since we use the SQL Server to compute the tokens on our end, SQL seemed to be happiest storing the tokens as a varbinary, which is its native result for an MD5 computation.
We have two pieces of code that attempt to do the same thing - run a select query that pulls out a value based on the token submitted. One uses a dynamic query (which is a problem), but it works. The other one attempts to do the same thing in a parameterized (safer) fashion, it does not work - it is unable to locate the token.
Here's the two competing attempts. First, the parameterized version which fails:
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()
And secondly, the dynamic query string version which works:
Dim scSelectThing As New SqlCommand
scSelectThing.CommandText = "select thing from tokenstable where token=convert(varbinary, " + stringToken + " )"
lbOutput2.Text = scSelectThing.ExecuteScalar()
When we run the SQL profiler, this is what is actually being executed against the DB:
exec sp_executesql N'select thing from tokenstable where token=@token',N'@token varbinary(68)',@token=0x3000780046003800380034004100450036003400430038003300440033004100380034003800460046004300380038004200390034003400330043004200370042004600
This doesn't look right to me, it looks as though we're doing something that leads something in the stack to do the wrong conversion somewhere.
Any ideas what that would be? Its obviously not acceptable to launch with a dynamic query in there.
Edit:
The string is an MD5 hash result. To make it work in Query Analyzer we do this:
select * from tokenstable where
token=convert(varbinary, 0xF664AE32C83D3A848FFC88B9443CB7BF )
Note the lack of quotes, if we quote it the query fails. The field that we are comparing to is a varbinary, where SQL Server has stored the results of the MD5 computations on our end.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的问题可能是字符串->二进制转换使用不同的编码。 尝试使用
System.Text.Encoding.ASCII
而不是Unicode
,看看这是否适合您。 我的猜测是convert()
正在将您的字符串视为varchar
而不是nvarchar
并且使用 ASCII 而不是 Unicode 作为自己的字符串字符串->二进制转换。编辑
另外,这个字符串是与哈希值等效的实际二进制文件,还是十六进制表示形式?
编辑2
那么您的问题是您正在传递二进制数据的十六进制表示形式的二进制表示形式。 够令人困惑的吗?
您只需将十六进制
string
转换为byte
数组,然后将其添加为参数的值即可。 您可以使用以下代码来完成此操作,该代码取自 这个问题(并翻译为 VB.NET):所以你的代码看起来像这样......
Your issue is likely that the string->binary conversions are using different encodings. Try using
System.Text.Encoding.ASCII
instead ofUnicode
and see if that does the trick for you. My guess is thatconvert()
is considering your string to be avarchar
instead of annvarchar
and is using ASCII instead of Unicode for its own string->binary conversion.Edit
Also, is this string an actual binary equivalent to the hash, or is it a hexadecimal representation?
Edit 2
Then your issue is that you're passing the binary representation of the hexadecimal representation of your binary data. That confusing enough?
You just need to convert the hex
string
to abyte
array before you add it as a value for your parameter. You can do that with the following code, taken from the answer to this question (and translated to VB.NET):So your code will look something like this...