Vasanth@n Ответов: 2

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>



Я не знаю, где я делаю ошибку :(

Может ли кто-нибудь помочь мне решить эту проблему?

2 Ответов

Рейтинг:
1

xcorporation

чувствительный к регистру?

Проверьте байты, которые вы отправляете, и байты, полученные от "зашифрованного" пароля - они, вероятно, отличаются.

Проверьте также имя пользователя.


Рейтинг:
0

Vasanth@n

Эта проблема решена, пожалуйста, используйте Utf-8 кодирование вместо Юникод

byte[] digestbuf = new byte[nonce.Length + Encoding.UTF8.GetByteCount(createtime + password)];
nonce.CopyTo(digestbuf, 0);
Encoding.UTF8.GetBytes(createtime + password).CopyTo(digestbuf, nonce.Length);


:большой палец вверх: подбадривает,
Васант


Dalek Dave

Хорошее Решение.

Member 13042474

Привет.
Я не знаю, слышу ли я ответ, потому что это очень старый пост.
Я не знаю, потому что я первый программист.
В вашем посте " credential = AuthenticationCore (" service", " service ");"

Я не понимаю этой части.
Итак, я добавил Это к предложению.
"Учетные данные что и usercredential = новый параметр usercredential();"

Затем ошибка исчезла, но аутентификация была отклонена.


Фактор: админ / админ
Отлаживать.WriteLine(credential.Имя пользователя + "" + учетные данные.Пароль + "" + учетные данные.Код + "" + набор.Создал + "" + набор.Созданный);

Результат: admin aXeERaYZqMkXsIIsnsiVh0NQdUM = 5eWn2SRx67nMS / 3C5ha6AQ = = 2017-03-10T05: 20: 32.129 Z 2017-03-10T05: 20: 32.129 Z


Могу я услышать объяснение?