处理 VB.NET 中的 varbinary 字段

发布于 2024-07-24 05:15:24 字数 1701 浏览 6 评论 0原文

我们的合作伙伴正在调用一个包含名为令牌的参数的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

姜生凉生 2024-07-31 05:15:25

您的问题可能是字符串->二进制转换使用不同的编码。 尝试使用 System.Text.Encoding.ASCII 而不是 Unicode ,看看这是否适合您。 我的猜测是 convert() 正在将您的字符串视为 varchar 而不是 nvarchar 并且使用 ASCII 而不是 Unicode 作为自己的字符串字符串->二进制转换。

编辑

另外,这个字符串是与哈希值等效的实际二进制文件,还是十六进制表示形式?

编辑2

那么您的问题是您正在传递二进制数据的十六进制表示形式的二进制表示形式。 够令人困惑的吗?

您只需将十六进制 string 转换为 byte 数组,然后将其添加为参数的值即可。 您可以使用以下代码来完成此操作,该代码取自 这个问题(并翻译为 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()

Your issue is likely that the string->binary conversions are using different encodings. Try using System.Text.Encoding.ASCII instead of Unicode and see if that does the trick for you. My guess is that convert() is considering your string to be a varchar instead of an nvarchar 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 a byte 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):

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 your code will look something like this...

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文