我已经尝试了很多变化-我在下面发布的是一个清理版本,我最初的开始。这是一个为基于unity的应用程序编写的帮助工具im。这不是游戏,只是一个二维应用程序。
我想复制一下:curl -f -s -S --user $(ROKU_DEV_CREDENTIALS) --anyauth -F "mysubmit=Install" -F "archive=@out/Archive.zip" http://$(ROKUIP)/plugin_install > /dev/null
这就是我到目前为止所拥有的(见下面的代码),它看起来“有点”工作,但允许身份验证通过,以及大约108 KB的数据(Wireshark说整个ZIP,大约2.8 MB,正在发送,但服务器说只有大约108 KB被接收);我想这可能是一个编码问题(应用程序在Windows10上,服务器是嵌入式Linux服务器[Roku播放器])。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
public class PushBuild : MonoBehaviour {
public RokuDevice SingleDevice;
public Dictionary<string, RokuDevice> ManyDevice;
public bool startUpload;
// Use this for initialization
void Start() {
}
// Update is called once per frame
void Update() {
if (startUpload)
{
StartCoroutine(Upload());
startUpload = false;
}
}
public void QueueUpPush()
{
startUpload = true;
}
IEnumerator Upload()
{
string[] substr = null;
UnityWebRequest www1 = UnityWebRequest.Head("http://10.0.0.232/plugin_install");
yield return www1.Send();
if (www1.isError)
{
Debug.Log(www1.error);
}
else
{
Dictionary<string, string> responseHeaders = www1.GetResponseHeaders();
string nonce;
string[] split = { "=", "\"" };
bool _null = responseHeaders.TryGetValue("WWW-Authenticate", out nonce);
if (nonce != null)
{
substr = nonce.Split(split, StringSplitOptions.RemoveEmptyEntries);
}
}
WWW _file = new WWW("file:///" + "D:\\Workspace\\Roku\\Tempest\\src\\Archive.zip");
yield return _file;
WWWForm form = new WWWForm();
form.AddBinaryData("archive", _file.bytes, "Archive.zip", "application/x-zip-compressed");
form.AddField("mysubmit", "install");
using (UnityWebRequest www = UnityWebRequest.Post("http://10.0.0.232/plugin_install", form))
{
string ha1 = "rokudev:rokudev:0000";
string ha2 = "POST:/plugin_install";
string responseDigest = CalculateResponseDigest(ha1, ha2, substr[5], "00000000", "aef3fafadfaedfadf", "auth");
string authHeaderVal = string.Format("Digest username=\"rokudev\", realm=\"rokudev\", nonce=\"{0}\", uri=\"/plugin_install\", response=\"{1}\", qop=auth, nc=00000000, cnonce=\"aef3fafadfaedfadf\"", substr[5], responseDigest);
www.SetRequestHeader("Authorization", authHeaderVal);
www.Send();
while (www.uploadProgress < 1.0)
{
Debug.Log("still uploading..." + www.uploadProgress);
yield return null;
}
Debug.Log(www.uploadedBytes);
if (www.isError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
Debug.Log(www.downloadHandler.data);
}
}
}
string CalculateResponseDigest(string ha1, string ha2, string serverNonce, string requestCnt, string clientNonce, string qop)
{
byte[] inputBytesHA1 = Encoding.ASCII.GetBytes(ha1);
byte[] HA1 = MD5.Create().ComputeHash(inputBytesHA1);
StringBuilder _returnValHA1 = new StringBuilder(HA1.Length * 2);
foreach (byte b in HA1)
{
_returnValHA1.AppendFormat("{0:x2}", b);
}
byte[] inputBytesHA2 = Encoding.ASCII.GetBytes(ha2);
byte[] HA2 = MD5.Create().ComputeHash(inputBytesHA2);
StringBuilder _returnValHA2 = new StringBuilder(HA2.Length * 2);
foreach (byte b in HA2)
{
_returnValHA2.AppendFormat("{0:x2}", b);
}
byte[] inputBytesHA3 = Encoding.ASCII.GetBytes(string.Format("{0}:{1}:{2}:{3}:{4}:{5}", _returnValHA1, serverNonce, requestCnt, clientNonce, qop, _returnValHA2));
byte[] HA3 = MD5.Create().ComputeHash(inputBytesHA3);
StringBuilder _returnVal = new StringBuilder(HA3.Length * 2);
foreach (byte b in HA3)
{
_returnVal.AppendFormat("{0:x2}", b);
}
return _returnVal.ToString();
}
}
重要提示:
我试过将zip加载为
FileStream
。我试着建立一个未加工C
HttpWebRequest
。我试着匹配罗库的头球确切地。
我同时使用fiddler和wireshark来监视网络流量-据我所知,流量几乎相同(头有点不同,这会产生不同的数据包偏移)。
我甚至对重新组装的包进行了区分(根据wireshark的报告),它们看起来几乎相同(同样主要是头差异)。
我使用了其他人的实现来实现摘要式身份验证——最后我自己实现了。我使用一个到服务器的头来获取nonce值,然后使用该nonce值来构建在摘要中使用的下一篇文章。据我所知,这似乎在起作用…但我怀疑这可能是罪魁祸首(当我构建摘要身份验证头时,roku设备给了我http 100 continue,它似乎接受了我的摘要身份验证和post请求)。
我也玩过编码,跟着
其他SO建议的建议。我可以得到不同字节的上传
将值放入roku中(例如,按原样,在没有编码的情况下,我可以
得到大约115700字节的报告,如果我做utf16我可以得到
27万字节)。从wireshark看来整个zip文件
被推到韩国。我的怀疑是我的编码
搞砸了。
我有wireshark数据、fiddler数据和5种不同的实现(不同于上面的示例),可以共享。我甚至可以分享roku的嵌入式web应用程序使用的javascript来展示它在做什么(这是一篇使用digest auth-kind forward的文章)。告诉我你错过了什么-我已经为此奋斗了两个星期,终于崩溃了寻求帮助!
有什么想法吗?
最佳答案
这个问题可以归结为“如何从c执行http post”和“如何从c执行摘要式身份验证”-如果你用google搜索这个,一些s.o.答案很容易弹出,请按照下面的步骤操作。
编码与此无关,ZIP作为原始八位字节提交。
这里是故障排除(分治)的主意-首先教你的应用上传小拉链,
关于c# - 在C#中复制cURL命令(Unity),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47320949/