我试图向一个符合onvif的摄像头提出一个网络请求,但我的反应有困难。
我遵循了ONVIF应用程序程序员的指南,我想出了这个soap消息来获取设备信息:
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tt="http://www.onvif.org/ver10/schema"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
<s:Header>
<wsse:Security>
<wsse:Username>admin</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wssusername-token-profile-1.0#PasswordDigest">
WndlORLsIdMIyyvb99lzSgm0iGI=
</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
Rjc0QUUzNDI2MTMyMTI4OTJCQjI1QzM2RUEzMDUzNEUxMTlFNEQ2Mg==
</wsse:Nonce>
<wsu:Created>2017-05-11T11:48:56.8823852ZZ</wsu:Created>
</wsse:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetDeviceInformation xmlns="http://www.onvif.org/ver10/device/wsdl" />
</s:Body>
</s:Envelope>设备的响应是:
<SOAP-ENV:Envelope (...)>
<SOAP-ENV:Header>
</SOAP-ENV:Header>
<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:Code>
<SOAP-ENV:Reason>
<SOAP-ENV:Text xml:lang="en">Sender not Authorized</SOAP-ENV:Text>
</SOAP-ENV:Reason>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>我通过减去我的计算机和设备之间的偏移量来计算创建的时间,这样就可以用与设备兼容的日期时间发送消息。
我的请求中遗漏了什么吗?考虑到用户名和密码是正确的,是什么导致了这个问题?
发布于 2017-06-01 10:36:31
因此,经过一些断断续续的研究,试验和错误,我设法解决了我的问题。我使用wireshark检查Onvif设备管理器应用程序发送给摄像机的内容,最后得到以下消息:
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<Security s:mustUnderstand="1" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username>admin</Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">6KZX13jsvYLOE72Fb7Nc4tCFE60=</Password>
<Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Xd0vNthkfp/VCmVtoHr3QA==</Nonce>
<Created xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2017-06-01T10:29:01.001Z</Created>
</UsernameToken>
</Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetDeviceInformation xmlns="http://www.onvif.org/ver10/device/wsdl" />
</s:Body>
</s:Envelope>为了计算现在和密码摘要,我还更改了我使用的方法,最后得到了这个方法:
public static void GetPasswordDigest(string ONVIFPassword, TimeSpan CameraTimeOffset, out string nonceb64_out, out string created_out, out string passwordDigest_out)
{
//Get nonce
Random rnd = new Random();
Byte[] nonce_b = new Byte[16];
rnd.NextBytes(nonce_b);
string nonce64 = Convert.ToBase64String(nonce_b);
nonceb64_out = nonce64;
//Get timestamp
DateTime created = DateTime.UtcNow - CameraTimeOffset;
string creationtime = created.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
Byte[] creationtime_b = Encoding.ASCII.GetBytes(creationtime);
created_out = creationtime;
//Convert the plain password to bytes
Byte[] password_b = Encoding.ASCII.GetBytes(ONVIFPassword);
//Concatenate nonce_b + creationtime_b + password_b
Byte[] concatenation_b = new byte[nonce_b.Length + creationtime_b.Length + password_b.Length];
System.Buffer.BlockCopy(nonce_b, 0, concatenation_b, 0, nonce_b.Length);
System.Buffer.BlockCopy(creationtime_b, 0, concatenation_b, nonce_b.Length, creationtime_b.Length);
System.Buffer.BlockCopy(password_b, 0, concatenation_b, nonce_b.Length + creationtime_b.Length, password_b.Length);
//Apply SHA1 on the concatenation
SHA1 sha = new SHA1CryptoServiceProvider();
Byte[] pdresult = sha.ComputeHash(concatenation_b);
string passworddigest = Convert.ToBase64String(pdresult);
passwordDigest_out = passworddigest;
} 这个方法在很大程度上是基于某人对StackOverflow中另一个问题的回答,不幸的是,我忘了保存链接或人名。我希望这能帮助那些和我一样的人。
发布于 2022-09-07 18:40:11
这只是为那些在这里遇到类似问题的人准备的。通常,特别是如果您不知道照相机使用哪种身份验证方案,则应该发送一个GetCapabilities命令。它属于PRE_AUTH服务类,因此不需要任何身份验证,作为它的伙伴GetSystemDateAndTime。响应包含一个Capabilities树。转到Device节点。Security子程序描述了摄像机支持的内容。这些都是从真正的摄像机捕捉到的:
第2部分中的照相机不接受在SOAP信封的标题中提供安全信息的请求。测试的模型需要TLS。
ONVIF芯规范是一个重要的参考资料。
https://stackoverflow.com/questions/43912896
复制相似问题