SOAP header Usernametoken проблема
Привет,
Я пытаюсь связать тег заголовка soap sercurity с usernametoken. Я использую алгоритм SHA1 для хэширования пароля с использованием datetime и 16-байтового nonce; вместо этого я попробовал использовать Microsoft.Web.Services3.Безопасность.Маркеры - класс с usernametoken также генерировать случайный код.
Я связываю сообщение SOAP в stringbuilder и использую Msxml2 описывается компонента ServerXMLHTTPClass для отправки запроса и ответа с сервера.
это мой метод построения сообщений soap.
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.
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-сообщения он всегда отвечает как ошибка аутентификации.
Запрос:
<?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>
Ответ:
<?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>
Я не знаю, где я делаю ошибку :(
Может ли кто-нибудь помочь мне решить эту проблему?