Pergunta

Um parceiro nosso está fazendo uma chamada para um serviço da Web que inclua um parâmetro chamado Token. O token é o resultado de um hash MD5 de dois números e nos ajuda a autenticar que o usuário usando nosso sistema Partners. Nosso parceiro pede ao usuário duas seqüências de seqüências, concatena -as, as executa pelo MD5 e depois chama nosso serviço da web. O resultado do MD5 é o token e é enviado para nós como uma string.

Armazenamos tokens válidos em um banco de dados - já que usamos o SQL Server para calcular os tokens do nosso lado, o SQL parecia mais feliz armazenar os tokens como uma varbinária, que é seu resultado nativo para um computação MD5.

Temos duas partes de código que tentam fazer a mesma coisa - execute uma consulta selecionada que retire um valor com base no token enviado. Um usa uma consulta dinâmica (o que é um problema), mas funciona. O outro tenta fazer a mesma coisa de maneira parametrizada (mais segura), não funciona - é incapaz de localizar o token.

Aqui estão as duas tentativas concorrentes. Primeiro, a versão parametrizada que falha:

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

E em segundo lugar, a versão dinâmica da string de consulta que funciona:

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

Quando executamos o SQL Profiler, é isso que realmente está sendo executado contra o banco de dados:

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

Isso não parece certo para mim, parece que estamos fazendo algo que leva algo na pilha para fazer a conversão errada em algum lugar.

Alguma idéia do que seria? Obviamente, não é aceitável lançar com uma consulta dinâmica lá.

Editar:

A string é um resultado de hash md5. Para fazer funcionar no analisador de consultas, fazemos isso:

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

Observe a falta de cotações, se o citarmos, a consulta falha. O campo com o qual estamos comparando é um varbinário, onde o SQL Server armazenou os resultados dos cálculos MD5 na nossa extremidade.

Foi útil?

Solução

Seu problema é provável que as conversões binárias estejam usando diferentes codificações. Tente usar System.Text.Encoding.ASCII ao invés de Unicode E veja se isso faz o truque para você. Meu palpite é que convert() está considerando sua string como um varchar em vez de um nvarchar e está usando ASCII em vez de unicode para sua própria conversão binária.

Editar

Além disso, essa string é um equivalente binário real ao hash ou é uma representação hexadecimal?

Editar 2

Então seu problema é que você está passando pela representação binária da representação hexadecimal de seus dados binários. Isso confuso o suficiente?

Você só precisa converter o hexadecimal string para um byte Array antes de adicioná -lo como um valor para o seu parâmetro. Você pode fazer isso com o seguinte código, retirado da resposta para essa questão (e traduzido para 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

Então, seu código vai parecer algo assim ...

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()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top