谨慎使用系统换行符

项目中有一个计算Http请求哈希值的环节,客户端按照指定文本格式生成哈希值;服务端收到Http请求后按照相同格式的生成文本并计算哈希,比较哈希值的异同判断请求信息是否被篡改。定义的文本格式如下:

Request Method      + "\n" +
Accept              + "\n" +  
Content-Type        + "\n" +
Request URI         + "\n" +
MD5(Request Body)   + "\n" +
jti                 + "\n" +
iat

公司内部测试没啥问题,移交给客户后报出生成的哈希值和工具生成的哈希值不匹配,而用工具生成的哈希值是可以请求服务接口的。截图也看了,日志也看了,明明是相同的文本,为啥生成的哈希就是不一样呢。找了好久才发现是不可见字符的影响,原来在服务端拼接指定格式文本的时候使用的StringBuilderAppendLine方法,而AppendLine方法的内部自动追加了一个Environment.NewLine.

我们都知道“\n”是换行符,一直以来C#的各种编程实践都推荐使用 Environment.NewLine 用于指定系统换行符,但是 Environment.NewLine != “\n”. 所以在这个示例中正确的用法应该是使用Append方法,在Append方法里添加”\n”作为换行使用.

操作系统回车换行所用字符
Linux/Unix/Android/Mac OS X 10\n = Newline = 0x0A = 10 = LF =Line Feed = 换行 = Ctrl + J
Mac OS 9\r = Return = 0x0D = 13 = CR = Carriage Return = 回车 = Ctrl + M
Windows/Dos\r \n = 0x0D 0x0A = CR LF = 回车 换行

Windows平台的换行符是”\r\n“,而Linux平台的换行符是”\n“,在不同平台下调用系统换行符返回的换行符是不一样的。很多时候我们需要保证平台兼容性,让Linux平台和Windows平台的保持一致时应该拒绝使用编程语言提供的系统换行符,应该使用原生的”\n”或”\r\n”。至于是使用”\n”还是”\r\n”来定义换行格式,理论上都可以,只要约定好就行。

编程语言/环境系统换行符
C#Environment.NewLine
Java/JDK7前System.getProperty(“line.separator”)
Java/JDK7后System.lineSeparator()
Pythonos.linesep
后记:在排查完问题后,很好奇到底还有那些字符属于不可见字符。原来在ASCII中存在控制字符和打印字符的说法,通常我们说的不可见字符大多是控制字符。常见的控制字符(US-ASCII控制字符)见下表。
十进制十六进制控制字符转义字符说明
000NUL\0Null character(空字符)
101SOHStart of Header(标题开始)
202STXStart of Text(正文开始)
303ETXEnd of Text(正文结束)
404EOTEnd of Transmission(传输结束)
505ENQEnquiry(请求)
606ACKAcknowledgment(收到通知/响应)
707BEL\aBell(响铃)
808BS\bBackspace(退格)
909HT\tHorizontal Tab(水平制表符)
100ALF\nLine feed(换行键)
110BVT\vVertical Tab(垂直制表符)
120CFF\fForm feed(换页键)
130DCR\rCarriage return(回车键)
140ESOShift Out(不用切换)
150FSIShift In(启用切换)
1610DLEData Link Escape(数据链路转义)
1711DC1Device Control 1(设备控制1) /XON(Transmit On)
1812DC2Device Control 2(设备控制2)
1913DC3Device Control 3(设备控制3) /XOFF(Transmit Off)
2014DC4Device Control 4(设备控制4)
2115NAKNegative Acknowledgement(拒绝接收/无响应)
2216SYNSynchronous Idle(同步空闲)
2317ETBEnd of Trans the Block(传输块结束)
2418CANCancel(取消)
2519EMEnd of Medium(已到介质末端/介质存储已满)
261ASUBSubstitute(替补/替换)
271BESC\eEscape(溢出/逃离/取消)
281CFSFile Separator(文件分割符)
291DGSGroup Separator(分组符)
301ERSRecord Separator(记录分隔符)
311FUSUnit Separator(单元分隔符)
3220SPWhite space
1277FDELDelete(删除)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值