SOAP标头Usernametoken问题 [英] SOAP header Usernametoken problem

查看:117
本文介绍了SOAP标头Usernametoken问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我正在尝试使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆