最近発生したログUrlEncode、UrlDecode

最近発生したログUrlEncode、UrlDecode

シンプルな共有。

最后更新 2021/01/09 17:03
沙漠尽头的狼
预计阅读 6 分钟
分类
.NET
标签
.NET C# Web API UrlDecode UrlEncode

本文阅读前了解知识:什么时候需要使用 UrlEncode 和 UrlDecode 函数

筆者はGoogleブラウザを用いて,F12を押すことで第三者サイトのHTTPプロトコルのインターフェイスをスナップしたパケット解析操作を行った.

シーンはこちら

運用と保守の弟は時折、特定のアウトソーシング会社のウェブサイトシステムを使用して、機器の入力作業を行い、プロセスは簡単です:

录入设备信息

  1. 入力機器の基本情報は、入力する必要がある7、8つのフィールドがあり、保存ボタンをクリックします。
  2. 基本情報の保存に成功して,設備タイプ選択操作に入り,その後設備識別ボタンをクリックする;
  3. 機器識別が正常に生成され、機器関連モジュール情報を入力し、単純な機器は2つのモジュールを入力する必要があり、複雑な機器は6つのモジュールを持ち、各モジュールは3つまたは4つのフィールドを入力し、最後にクリックして保存します。

デバイス入力の成功、単一の年の手の速度は数分かかることがありますが、実際には何もありません。

1000台の機材が必要だと言われました。弟は泣いていたので、開発者はここに来ました。

  1. 操作とメンテナンスは、Excelテンプレートを準備し、入力する必要がある1000の基本的な機器情報と機器の種類情報を入力します。この作業負荷は大きくありません。半日、最大1日の作業負荷です。
  2. C/Sクライアントの小さなツールを開発し、ビジネス要件に従ってモジュール入力ルールを設定します。
  3. プログラムの実行中にデバイスを入力すると、生成されたデバイス識別子がデバイスに関連付けられます。
  4. すべての入力が完了し、Excelエクスポートが提供され、機器の基本情報、生成された機器IDをすべて関連付けてエクスポートでき、作業が完了します。

経过几天的开発工作,开発哥将精磨的小工具渡给运営小哥,运営小哥使用后投来了赞否的眼视。。

問題は

少し冗長な言葉の前に、この小さなツールの開発、開発兄弟は問題に遭遇しました:

xxxインターフェース

xxx接口

这是某个接口的信息,Content-Typeapplication/x-www-form-urlencoded,下面参数使用的Form Data,即参数使用了UrlEncode,比如未编码前的一个参数:

"Content":"{"AP_Name":"HK_7889","IP":"192.168.0.1"}"

编码后(可以使用这个在线 URL 编码解码工具验证):

"Content":"%7B%22AP_Name%22%3A%22HK_7889%22%2C%22IP%22%3A%2292.168.0.1%22%7D"

使用Postman测试时,未对参数使用UrlEncode,接口测试成功,开发这个小工具时,有 3 个接口都是类似的,未进行UrlEncode操作:

var client = new RestClient("http://admin.lqclass.com/api/device");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("Content", "{\"AP_Name\":\"HK_7889\",\"IP\":\"92.168.0.1\"}");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

しかし、スクリーンショットのパラメータのような、もう少し複雑なインターフェイスがあります。

"Content":"{"AP_Name":"HK_7889","IP":"192.168.0.1","Module":[{"M_Name":"cameri0","Desc":"cameri0","AP_PUID":"54632325461320320"},{"M_Name":"cameri1","Desc":"cameri1","AP_PUID":"54636325461320320"},{"M_Name":"cameri2","Desc":"cameri2","AP_PUID":"54632325421320320"}]}"

Content值格式化看得清楚一点,Module是设备关联的模块信息:

{
  "AP_Name": "HK_7889",
  "IP": "192.168.0.1",
  "Module": [
    {
      "M_Name": "cameri0",
      "Desc": "cameri0",
      "AP_PUID": "54632325461320320"
    },
    {
      "M_Name": "cameri1",
      "Desc": "cameri1",
      "AP_PUID": "54636325461320320"
    },
    {
      "M_Name": "cameri2",
      "Desc": "cameri2",
      "AP_PUID": "54632325421320320"
    }
  ]
}

实际UrlEncode后的参数为:

"Content":"%7B%22AP_Name%22%3A%22HK_7889%22%2C%22IP%22%3A%22192.168.0.1%22%2C%22Module%22%3A%22%255B%257B%2522M_Name%2522%253A%2522cameri0%2522%252C%2522Desc%2522%253A%2522cameri0%2522%252C%2522AP_PUID%2522%253A%252254632325461320320%2522%257D%252C%257B%2522M_Name%2522%253A%2522cameri1%2522%252C%2522Desc%2522%253A%2522cameri1%2522%252C%2522AP_PUID%2522%253A%252254636325461320320%2522%257D%252C%257B%2522M_Name%2522%253A%2522cameri2%2522%252C%2522Desc%2522%253A%2522cameri2%2522%252C%2522AP_PUID%2522%253A%252254632325421320320%2522%257D%255D%22%7D"

本来一般接口,如上面成功执行的 C#代码那般直接未UrlEncode调用是没问题的。

しかし、このインターフェイスが呼び出され、サーバーはエラーメッセージを返します:“xxx resolution failed”、呼び出しコードは次のとおりです:

var client = new RestClient("http://admin.lqclass.com/api/device");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("Content", "{\"AP_Name\":\"HK_7889\",\"IP\":\"192.168.0.1\",\"Module\":[{\"M_Name\":\"cameri0\",\"Desc\":\"cameri0\",\"AP_PUID\":\"54632325461320320\"},{\"M_Name\":\"cameri1\",\"Desc\":\"cameri1\",\"AP_PUID\":\"54636325461320320\"},{\"M_Name\":\"cameri2\",\"Desc\":\"cameri2\",\"AP_PUID\":\"54632325421320320\"}]}");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

两处调用代码哪里不同?只是 Content 值不一样,最后怀疑是不是需要手动进行UrlEncode?又不是 url 参数,为啥需要编码呢?不管啦,先编码了再说。

問題解決のため

パラメータのエンコード後、次のように呼び出します。

var client = new RestClient("http://admin.lqclass.com/api/device");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("Content", "%7B%22AP_Name%22%3A%22HK_7889%22%2C%22IP%22%3A%22192.168.0.1%22%2C%22Module%22%3A%22%255B%257B%2522M_Name%2522%253A%2522cameri0%2522%252C%2522Desc%2522%253A%2522cameri0%2522%252C%2522AP_PUID%2522%253A%252254632325461320320%2522%257D%252C%257B%2522M_Name%2522%253A%2522cameri1%2522%252C%2522Desc%2522%253A%2522cameri1%2522%252C%2522AP_PUID%2522%253A%252254636325461320320%2522%257D%252C%257B%2522M_Name%2522%253A%2522cameri2%2522%252C%2522Desc%2522%253A%2522cameri2%2522%252C%2522AP_PUID%2522%253A%252254632325421320320%2522%257D%255D%22%7D");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

哈哈,成功了,这里简单猜测下:别人的服务对接收的参数可能做了UrlDecode操作。

其实中间还做了一个参数的UrlEncode操作,即下面的Module参数值:

"Content":{"AP_Name":"HK_7889","IP":"192.168.0.1","Module":[{"M_Name":"cameri0","Desc":"cameri0","AP_PUID":"54632325461320320"},{"M_Name":"cameri1","Desc":"cameri1","AP_PUID":"54636325461320320"},{"M_Name":"cameri2","Desc":"cameri2","AP_PUID":"54632325421320320"}]}

第一次UrlEncode,即先对Module的值进行UrlEncode

"Content":{"AP_Name":"HK_7889","IP":"192.168.0.1","Module":%5B%7B%22M_Name%22%3A%22cameri0%22%2C%22Desc%22%3A%22cameri0%22%2C%22AP_PUID%22%3A%2254632325461320320%22%7D%2C%7B%22M_Name%22%3A%22cameri1%22%2C%22Desc%22%3A%22cameri1%22%2C%22AP_PUID%22%3A%2254636325461320320%22%7D%2C%7B%22M_Name%22%3A%22cameri2%22%2C%22Desc%22%3A%22cameri2%22%2C%22AP_PUID%22%3A%2254632325421320320%22%7D%5D}

第二次UrlEncode即是上面成功的参数方式了,对整个Content的值进行UrlEncode,看上面成功的参数,不重复贴了。

最終的な概要

抓别人数据包时,不要凭印象、已有知识判定该怎么怎么做,比如前面的参数,不使用UrlEncode时,调用成功了,其他包我是否也沿用相同的方式使用就正确呢?搞不定时,多尝试猜测的方法。

キャッチコピーは“彼に任せなさい”。

本文使用的UrlEncode C# 代码:

public static string UrlEncode(string str)
{
    StringBuilder sb = new StringBuilder();
    byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str); //默认是System.Text.Encoding.Default.GetBytes(str)
    for (int i = 0; i < byStr.Length; i++)
    {
        sb.Append(@"%" + Convert.ToString(byStr[i], 16));
    }

    return (sb.ToString());
}
Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2024/01/19

FluentValidation検証のチュートリアル

FluentValidationは、. NET開発に基づく検証フレームワークで、オープンソースで無料でエレガントで、チェーン操作をサポートし、理解しやすく、完全な機能を備えており、MVC5、WebApi2、ASP.NET COREと深く統合することができ、コンポーネント内に12種類の一般的な検証子を提供し、スケーラビリティが良く、カスタム検証子をサポートし、ローカライズされた多言語をサポートします。

继续阅读
同分类 / 同标签 2023/01/11

gと実操. NET编

バックエンドサービス間の呼び出しと同様に、バックエンドとバックエンドのやりとりにもWebApi + JSONを使用してきました。

继续阅读