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

作者使用谷歌浏览器,通过按下F12对第三方网站http协议的接口抓包进行分析操作。

场景

运维小哥哥偶尔使用某某外包公司的网站系统,做设备录入工作,流程简单:

  1. 录入设备基本信息,有7、8个字段需要输入,然后点击保存按钮;
  2. 基本信息保存成功,进入设备类型选择操作,然后点击生成设备标识按钮;
  3. 设备标识生成成功,录入设备关联的模块信息,简单设备只需要录入2条模块,复杂的设备有6条模块,每个模块有3、4个字段需要输入,最后点击保存。

一条设备录入成功,单身多年的手速可能也花不了几分钟,其实这也没啥。

突然领导说有1000个设备需要搞?运维小哥哥哭了,这时就该开发人员上场了:

  1. 运维准备一个Excel模板,输入需要录入的1000个设备基本信息、设备类型信息,这个工作量不大,就半天吧,最多一天工作量;
  2. 开发做个C/S客户端小工具,程序中按业务要求配置模块录入规则;
  3. 程序执行过程中录入一个设备就把生成的设备标识与设备关联;
  4. 全部录入完成,提供一个Excel导出,可将设备基本信息、生成的设备标识全部关联导出,工作完成。

经过几天的开发工作,开发哥哥将精心打磨的小工具交给运维小哥,运维小哥哥使用后投来了赞许的目光...

问题

前面铺垫的话有点啰嗦了,开发这个小工具时,开发小哥遇到一个问题:

这是某个接口的信息,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解析失败”,调用代码如下:

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());
}

文末分享

  • 后台回复数字【00】:获取DotNet、Java、C++、前端等技术资料
  • 添加微信群:添加号主微信号【dotnet9】,备注【入群】
  • 添加QQ群:群号【771992300】,备注【Dotnet9】

时间如流水,只能流去不流回。

  • 公众号:Dotnet9
  • 号主微信号:dotnet9
  • 作者及编辑:沙漠之尽头的狼
  • 原文链接:点击阅读
  • 日期:2021-01-09

最近遇到的问题记录:UrlEncode、UrlDecode的更多相关文章

  1. 终端命令对字符串进行sha1、md5、base64、urlencode/urldecode

    sha1.md5.base64 mac $ echo -n foo|shasum 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33 - $ 2c26b46b68ffc6 ...

  2. c# UrlEncode,UrlDecode

    用 C#  winform  处理 utf-8,gb2312编码转换方法 首先,在项目属性 的  应用程序——目标框架中,选择 .NET Framework 4 然后再添加引用——.NET 中选择  ...

  3. 关于URLEnCode,URLDeCode,Base64,公钥私钥

    1.Base64非常适合http.mime协议,所以在一些类似webservice中可以用Base64. 用法如下:传出去之前先 Convert.ToBase64String(encryptedByt ...

  4. urlencode urldecode

    1.urlencode()函数原理就是首先把中文字符转换为十六进制,然后 在每个字符前面加一个标识符%. urldecode()函数与urlencode()函 数原理相反,用于解码已编码的 URL 字 ...

  5. 【原创】c# Winform 使用 web 的UrlEncode/UrlDecode 方法

    1.先 右键引用,添加 System.Web 数据集 2.语句如下 string s= System.Web.HttpUtility.UrlEncode("123", System ...

  6. python中Url链接编码处理(urlencode,urldecode)

    做完了flask-web应用,这几天想用爬虫做个好玩的电影链接整合器,平时找电影都是在dytt或者dy2018之类的网站,在用dytt搜索电影<美国队长时>,发现他的搜索链接是这样的:ht ...

  7. lua urlencode urldecode URL编码

    URL编码其实就是对一些字符转义为%加上该字符对应ASCII码的二位十六进制形式. 如: 字符 特殊字符的含义 URL编码 # 用来标志特定的文档位置 % % 对特殊字符进行编码 % & 分隔 ...

  8. Objective-C urlEncode urlDecode

    @interface NSString (stringByDecodingURLFormat) - (NSString *)stringByDecodingURLFormat; - (NSString ...

  9. asp.net面试题汇总

    1.静态成员和非静态成员的区别? 答: 静态变量使用 static 修饰符进行声明,在类被实例化时创建,通过类进行访问不带有 static 修饰符声明的变量称做非静态变量,在对象被实例化时创建,通过对 ...

  10. 130道C#面试题

    C#/.Net/数据库笔试资料C#资料(一)1.静态成员和非静态成员的区别?答:静态变量使用 static 修饰符进行声明,在类被实例化时创建,通过类进行访问不带有 static 修饰符声明的变量称做 ...

随机推荐

  1. django查询-列延迟加载only()、defer()

    这玩意和sqlalchemy的几乎一样. only():只加载给定的列,其他列只有在使用时会发起二次查询 defer():不加载指定的列,刚好和only()相反. 实例: >>> r ...

  2. 加速计算,为何会成为 AI 时代的计算力“新宠” 审核中

    随着科技的发展,处理大量数据和进行复杂计算的需求越来越高,人工智能.大数据和物联网等领域更是如此,传统的计算方式已经无法满足这些需求.因此,加速计算作为一种现代计算方式,成了必要的手段.加速计算具有前 ...

  3. uniapp-welive仿微信/抖音直播带货|uni-app+vue3+pinia短视频直播商城

    基于uniapp+vue3+uv-ui跨端H5+小程序+App短视频+直播带货商城Uniapp-WeLive. uni-welive一款全新基于uniapp+vue3+pinia+vk-uview等技 ...

  4. 设计模式Java实战,彻底学会

    ​ ​这是全网最强的Java设计模式实战教程.此教程用实际项目场景,结合SpringBoot,让你真正掌握设计模式. 网址是:Java设计模式实战专栏介绍 - 自学精灵(也可以百度搜索"自学 ...

  5. JavaFx之从controller关闭stage(十八)

    JavaFx之从controller关闭stage(十八) 开发时,我们需要从controller的button时间中关闭当前,那么你的按钮事件可以这样: @FXML public Button ca ...

  6. 【scikit-learn基础】--『监督学习』之 决策树分类

    决策树分类算法是一种监督学习算法,它的基本原理是将数据集通过一系列的问题进行拆分,这些问题被视为决策树的叶子节点和内部节点.决策树的每个分支代表一个可能的决策结果,而每个叶子节点代表一个最终的分类结果 ...

  7. 主控FC1179 U盘量产修复

    当我们的U盘出现如下情况的话,可以做为参考修复 第一步:可以用Chip Genius工具,查看U盘主控(可得知主控厂商:一芯 ,主控型号:FC1179). 第二步:下载主控相对应的量产工具(笔者已经上 ...

  8. ubuntu安装mysql8,debian安装mysql8,linux安装mysql8,x86_64架构,deb包

    作者主页:https://www.cnblogs.com/milkbox 参考: 修改大小写:MySQL8.0安装后更改不区分大小写!包你必生效!_mysql8.0不区分大小写-CSDN博客 整个安装 ...

  9. 13、Flutter AspectRatio 调整子元素child的宽高比

    AspectRatio的作用是根据设置调整子元素child的宽高比.   childAspectRatio 是 GridView 和 AspectRatio 控件中的一个参数   AspectRati ...

  10. NebulaGraph实战:2-NebulaGraph手工和Python操作

      图数据库是专门存储庞大的图形网络并从中检索信息的数据库.它可以将图中的数据高效存储为点(Vertex)和边(Edge),还可以将属性(Property)附加到点和边上.本文以示例数据集basket ...