100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 文件上传接口需要进行请求体加密怎么处理?竟牵出string与byte[]的事故

文件上传接口需要进行请求体加密怎么处理?竟牵出string与byte[]的事故

时间:2022-04-26 04:44:15

相关推荐

文件上传接口需要进行请求体加密怎么处理?竟牵出string与byte[]的事故

今天对接一个接口,是一个国外的支付相关的内容。里面有一个接口为创建钱包,他们的设计是先接口post过去一些基本的创建信息,返回给你一个钱包ID,然后根据这个钱包ID,上传单个文件,返回给文件ID,再通过更新钱包,把文件ID和文件类型自行关联到钱包ID上。

结果在做第二步的时候,也就是上传文件的时候,这个代码使用Python来实现时如下:

def doc_upload(self): timestamp = int(time.time() * 1000) url = self.api_url + "/documents?ownerSrn=wallet:[INSERT WALLERT ID]&timestamp={}".format(timestamp) body = open("6pic.jpg", "rb").read() headers = {} headers["Content-Type"] = "image/jpg" headers["X-Api-Version"] = self.api_version headers["X-Api-Key"] = self.api_key headers["X-Api-Signature"] = hmac.new(self.api_secret.encode("utf-8"), url.encode("utf-8") + body, "SHA256").hexdigest() print(url,headers) response1 = requests.request("POST", url, headers=headers, >return response1.text

得益于Python非常开放灵活的数据定义,直接打开一个文件,可以获得一个bytes,也就是在这里的body命名。然后又可以把它塞到hmac中进行加密计算,还能直接和encode后的内容使用加号相加,更是又可以直接作为Request请求里的data内容。所以可以说是一次到位,也非常Python的简洁高效和可读等优点了。

可是一开始,我没看出这些特点来,更是没想到,应该把这个思想用到把上面的代码转为java时使用到。问题就出在,java多了这个数据类型上来了。回顾一下这次转java代码的过程。一开始,我将获取到文件流转为byte数组。然后把这个byte数组通过new String(bytes,"utf-8")转为了字符string类型,想通过这样来通用到原来的请求方法中,请求方法代码摘取如下,使用原始的包连接:

connection.setRequestProperty("X-Api-Key", apiKey);connection.setRequestProperty("X-Api-Signature", computeSignature(secretKey, targetURL, requestBody));connection.setDoOutput(true);connection.setRequestMethod(method);DataOutputStream wr = new DataOutputStream( connection.getOutputStream());wr.write(requestBody.getBytes("UTF-8"));

这里传过来的的requestBody就是bytes转后的String。仔细看可以发现,最后做write的时候,还是把内容转为byte数组。查看FilterOutputStream类发现,除了这个就只有int可以了。结果一运行,认证不通过。

为什么好端端的我只是对byte进行了string转换而已,还指定了统一的字符编码utf-8,为什么会说加密的签名信息不通过呢?看一下原来的加密获取签名部分的代码:

String >Mac sha256Hmac = Mac.getInstance("HmacSHA256"); SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"); sha256Hmac.init(key); byte[] macData = sha256Hmac.doFinal(data.getBytes("UTF-8")); String result = ""; for (final byte element : macData) { result += Integer.toString((element & 0xff) + 0x100, 16).substring(1); }

可以发现不管是做new SecretKeySpec(byte[] var1, String var2)还是sha256Hmac的doFinal(byte[] var1)都是对byte进行处理的。而这里的data,使用一个字符型的url加上一个来自byte数组创建的字符串组成的新字符串,再进行getBytes(),得到的会不是原始的两个内容。换句话说,(string1 +( byte 2 []->string 2) )->byte 3[] ≠ (string1->byte 1 []) add byty 2 [],也就是一个字符串加上字节数组转换的字符串后得到的这个长字符整个转为字节数组后的字节数组,不等于先将这个字符串转为字节数据后加上一个不转的数组得到的字节数组。解决这个问题时,将原方法体中的请求内容参数由string,改为byte[],之后,就一直用这个原始的Byte[]进行后面的所有操作,当需要相加时,使用数组间的相加方法。问题得以解决。可以看出,string转byte[]相比如把byte[]转为string在做加密这件事上,有着天然的优势和通顺保障。

不过,深处的原因呢?

对于这string和byte[]之间的转换故事,也有一些人进行了分析。可以看一看。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。