SOAP标头Usernametoken问题 [英] SOAP header Usernametoken problem
问题描述
我正在尝试使用usernametoken绑定soap sercurity标头标记。我使用SHA1算法来使用datetime和16字节nonce散列密码;相反,我尝试过使用Microsoft.Web.Services3.Security.Tokens - UsernameToken类来生成随机数。
我在stringbuilder中绑定SOAP消息,并使用 MSXML2 组件的 ServerXMLHTTPClass 从中发送请求和响应服务器。
这是我的肥皂消息构建方法。
Hi,
I am trying to bind soap sercurity header tag with usernametoken. I am using SHA1 algorithm to hashing the password with using datetime and 16 byte nonce; instead I have tried with Microsoft.Web.Services3.Security.Tokens - UsernameToken class also to generate nonce.
I am binding the SOAP message in stringbuilder and using MSXML2 component's ServerXMLHTTPClass to send request and response from the server.
this is my soap message building method.
sb.Append("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsdl=\"http://www.onvif.org/ver10/device/wsdl\">");
credential = AuthenticationCore("service", "service");
sb.Append("<soap:Header>");
sb.Append("<wsse:Security soap:mustUnderstand = \"true\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">");
sb.Append("<wsse:UsernameToken wsu:Id=\"UsernameToken-" + System.Guid.NewGuid() + "\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">");
sb.Append("<wsse:Username>" + credential.UserName + "</wsse:Username>");
sb.Append("<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + credential.Password + "</wsse:Password>");
sb.Append("<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + credential.Nonce + "</wsse:Nonce>");
sb.Append("<wsu:Created>" + credential.Created + "</wsu:Created>");
sb.Append("</wsse:UsernameToken>");
sb.Append("</wsse:Security>");
sb.Append("</soap:Header>");
//sb.Append(GetHeadder());
sb.Append("<soap:Body>");
if (BodyContent != null)
sb.Append(BodyContent.ToString());
sb.Append("</soap:Body>");
sb.Append("</soap:Envelope>");
这是我用来加密密码并生成的方法nonce。
and this is my method which i am using to encrypt the password and generate nonce.
internal const int NonceLength = 0x10;
private RNGCryptoServiceProvider Rand;
private byte[] CreateNonce()
{
byte[] buf = new byte[NonceLength];
Rand.GetBytes(buf);
return buf;
}
private UserCredential AuthenticationCore(string username, string password)
{
UserCredential Return = new UserCredential();
UsernameToken usernameToken = new UsernameToken(username, password, PasswordOption.SendHashed);
try
{
//Rand = new RNGCryptoServiceProvider();
//byte[] nonce = CreateNonce();
byte[] nonce = usernameToken.Nonce;
string createtime; // = DateTime.Now.ToUniversalTime().ToString(DateTimeFormatInfo.InvariantInfo.SortableDateTimePattern) + "Z";
//createtime = DateTime.Now.ToUniversalTime().ToString(DateTimeFormatInfo.InvariantInfo.SortableDateTimePattern) + "Z";
createtime = DateTime.UtcNow.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFF") + "Z";
string expiretime = DateTime.UtcNow.AddMinutes(5).ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFF") + "Z";
byte[] digestbuf = new byte[nonce.Length + Encoding.Unicode.GetByteCount(createtime + password)];
nonce.CopyTo(digestbuf, 0);
Encoding.Unicode.GetBytes(createtime + password).CopyTo(digestbuf, nonce.Length);
SHA1 sha1 = SHA1.Create();
string digest = Convert.ToBase64String(sha1.ComputeHash(digestbuf));
//SHA256 sha256 = SHA256.Create();
//string digest = Convert.ToBase64String(sha256.ComputeHash(digestbuf));
Return.UserName = username;
Return.Password = digest;
Return.Nonce = Convert.ToBase64String(nonce);
Return.Created = createtime;
Return.Expaire = expiretime;
}
catch
{
}
return Return;
}
public struct UserCredential
{
public string UserName;
public string Password;
public string Nonce;
public string Created;
public string Expaire;
}
但是在发送Soap消息请求时,它总是响应身份验证失败。
请求:
but while send the Soap message request, it alway response as Authentication failed.
Request:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsdl="http://www.onvif.org/ver10/device/wsdl">
<soap:Header>
<wsse:Security soap:mustUnderstand = "true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-3ae8d972-d014-47b0-858b-2364f6119763" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>service</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">jJdUs+AXDHZou8EmltlzwwNbe/M=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">V0db+It+XZpH5s2mrh1ylA==</wsse:Nonce>
<wsu:Created>2010-11-22T06:43:47.61Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<tds:GetDeviceInformation xmlns:tet="http://www.onvif.org/ver10/events/wsdl" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver10/imaging/wsdl" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" />
</soap:Body>
</soap:Envelope>
回复:
Response:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:ter="http://www.onvif.org/ver10/error">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<SOAP-ENV:Code>
<SOAP-ENV:Value>SOAP-ENV:Sender</SOAP-ENV:Value>
<SOAP-ENV:Subcode>
<SOAP-ENV:Value>ter:NotAuthorized</SOAP-ENV:Value>
<SOAP-ENV:Subcode>
<SOAP-ENV:Value>ter:SenderNotAuthorized</SOAP-ENV:Value>
</SOAP-ENV:Subcode>
</SOAP-ENV:Subcode>
</SOAP-ENV:Code>
<SOAP-ENV:Reason>
<SOAP-ENV:Text>The requested action requires authorization</SOAP-ENV:Text>
</SOAP-ENV:Reason>
<SOAP-ENV:Node>http://www.w3.org/2003/05/soap-envelope/node/ultimateReceiver</SOAP-ENV:Node>
<SOAP-ENV:Role>http://www.w3.org/2003/05/soap-envelope/node/ultimateReceiver</SOAP-ENV:Role>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
我不知道在哪里我犯了错误:(
有谁能帮我解决这个问题?
I don't know where I am doing the mistake :(
Can anyone help me to solve this problem?
推荐答案
case敏感?
检查发送的字节数和从加密密码收到的字节数 - 它们可能有所不同。
检查用户名。
case sensitive?
Check the bytes you send and the bytes received from the 'encrypted' password - they differ probably.
Check username as well.
此问题已解决,请使用 Utf-8 编码代替 unicode
This problem is solved, please use Utf-8 encoding instead of unicode
byte[] digestbuf = new byte[nonce.Length + Encoding.UTF8.GetByteCount(createtime + password)];
nonce.CopyTo(digestbuf, 0);
Encoding.UTF8.GetBytes(createtime + password).CopyTo(digestbuf, nonce.Length);
:thumbsup :振作起来,
Vasanth
:thumbsup: Cheers up,
Vasanth
这篇关于SOAP标头Usernametoken问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!