我已经尝试了很多变化-我在下面发布的是一个清理版本,我最初的开始。这是一个为基于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。我试着建立一个
未加工CHttpWebRequest。我试着匹配罗库的头球
确切地。
我同时使用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/

10-11 11:38