Android问题解决:android.util.Base64.encode 导致签名不匹配 SignatureDoesNotMatch
文章目录
- 前文:遇到问题
- 一问:为什么SignatureDoesNotMatch
- 二问:为什么SignatureDoesNotMatch
- 三问:Signature请求参数为什么多了%0A
- 四问:Signature为什么多了换行
- 五问:android.util.Base64.encode的用法
前文:遇到问题
在折腾《ESP32-C3入门教程——导读》时,需要对接阿里云物联网平台。
想要通过Android App直接调用阿里云物联网云端API。
阿里云并没有直接提供对应的云端开发的Android SDK,就只能自己写了。
结果就遇到了这么一个大坑。签名不匹配,校验不通过。
今天博文,咱们换种写法,5why分析法。
话说每个问题多问几个why,在第5个why的时候,你就能找到根源。
SignatureDoesNotMatch : Specified signature is not matched with our calculation
{"RequestId":"DD7C6D23-8236-5152-85FB-A7869342B749","Message":"Specified signature is not matched with our calculation. server string to sign is:XXXXXXXXX","Recommend":"https://troubleshoot.api.aliyun.com?q=SignatureDoesNotMatch&product=Iot","HostId":"iot.cn-shanghai.aliyuncs.com","Code":"SignatureDoesNotMatch"}
一问:为什么SignatureDoesNotMatch
分析:
- 为什么
SignatureDoesNotMatch
,签名不匹配
? - 大概率是
Signature
计算错误? - 直接看签名机制其中的
Signature
参数的计算过程
验证:
做个对比测试,验证我们计算的Signature
是否正确
- 下载官方提供的java sdk
- 设定一模一样的参数,分别运行java和android
- 打印输出,皆是:
seuSaBh1s8fZ4MGayjxYv4wc3JY=
二问:为什么SignatureDoesNotMatch
分析:
第一步排查直接失败,方向错误,没法接着深挖。
- 换个方向继续问:
Signature
签名正确,为什么还会提示SignatureDoesNotMatch
? - 难道是提交给阿里云的请求字符串错误?
验证:
同上一样,做一个对比测试,验证我们最终得到的请求字符串是否一致。
- 下载官方提供的java sdk
- 设定一模一样的参数,分别运行java和android
- 打印输出,分别如下:
http://iot.cn-shanghai.aliyuncs.com/?SignatureVersion=1.0&Action=QueryDevicePropertyStatus&Format=JSON&SignatureNonce=2E68FD84-A0BE-4D86-BDB2-7578F20290E6&Version=2018-01-20&AccessKeyId=XXXXXXXXX&Signature=seuSaBh1s8fZ4MGayjxYv4wc3JY%3D%0A&SignatureMethod=HMAC-SHA1&RegionId=cn-shanghai&Timestamp=2022-04-21T15%3A30%3A27Z&ProductKey=XXXXXXXXX&DeviceName=XXXXXXXXX
https://iot.cn-shanghai.aliyuncs.com/?AccessKeyId=XXXXXXXXX&Action=QueryDevicePropertyStatus&DeviceName=XXXXXXXXX&Format=JSON&ProductKey=XXXXXXXXX&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=2E68FD84-A0BE-4D86-BDB2-7578F20290E6&SignatureVersion=1.0&Timestamp=2022-04-21T15%3A30%3A27Z&Version=2018-01-20&Signature=seuSaBh1s8fZ4MGayjxYv4wc3JY%3D
- 经过细致的观察和对比,很快发现Android打印输出的是
Signature=seuSaBh1s8fZ4MGayjxYv4wc3JY%3D%0A
- 而Java打印输出的是
Signature=seuSaBh1s8fZ4MGayjxYv4wc3JY%3D
三问:Signature请求参数为什么多了%0A
分析:
Signature
原先的计算结果是seuSaBh1s8fZ4MGayjxYv4wc3JY=
。- 根据签名机制要求,需要将其按照RFC3986的规则进行URL编码后,再添加到请求参数中,即完成对请求签名的过程。
seuSaBh1s8fZ4MGayjxYv4wc3JY=
进行URL编码后得到seuSaBh1s8fZ4MGayjxYv4wc3JY%3D
。- 那么java程序运行的结果是没毛病的,Android运行结果为什么多了
%0A
。 - 由URL编码得知,%0A是换行符经过URL编码得来的。
- 那么得到的结论是Android计算
Signature
的结果是多了一个换行符。 - 这也反推到第一个为什么的猜测是正确的,只是因为换行符靠打印是看不出来的。
四问:Signature为什么多了换行
分析:
- android的Signature计算代码很多也是借鉴签名机制这边的Java代码示例。
- 基本没有修改,唯一修改的地方在于
return new String(Base64.encodeBase64(bytes, false), CHARSET_UTF8);
- 因为android没有该函数,所以我将其改成
return new String(Base64.encode(bytes, Base64.DEFAULT), CHARSET_UTF8);
- 如果代码中哪里有问题,那么最有可能出问题的地方就在这里。
验证:
- 将
return new String(Base64.encode(bytes, Base64.DEFAULT), CHARSET_UTF8);
- 改成
return new String(Base64.encode(bytes, Base64.NO_WRAP), CHARSET_UTF8);
- 问题解决,撒花~
五问:android.util.Base64.encode的用法
分析:
但是,我们不禁还是要问:为什么呢?
从android.util.Base64.java
的源码中得到
/*** Utilities for encoding and decoding the Base64 representation of* binary data. See RFCs <a* href="http://www.ietf.org/rfc/rfc2045.txt">2045</a> and <a* href="http://www.ietf.org/rfc/rfc3548.txt">3548</a>.*/
public class Base64 {/*** Default values for encoder/decoder flags.*/public static final int DEFAULT = 0;/*** Encoder flag bit to omit the padding '=' characters at the end* of the output (if any).*/public static final int NO_PADDING = 1;/*** Encoder flag bit to omit all line terminators (i.e., the output* will be on one long line).*/public static final int NO_WRAP = 2;/*** Encoder flag bit to indicate lines should be terminated with a* CRLF pair instead of just an LF. Has no effect if {@code* NO_WRAP} is specified as well.*/public static final int CRLF = 4;/*** Encoder/decoder flag bit to indicate using the "URL and* filename safe" variant of Base64 (see RFC 3548 section 4) where* {@code -} and {@code _} are used in place of {@code +} and* {@code /}.*/public static final int URL_SAFE = 8;/*** Flag to pass to {@link Base64OutputStream} to indicate that it* should not close the output stream it is wrapping when it* itself is closed.*/public static final int NO_CLOSE = 16;......
flags | 注释 | 说明 |
---|---|---|
DEFAULT | Default values for encoder/decoder flags. | 默认 |
NO_PADDING | Encoder flag bit to omit the padding ‘=’ characters at the end of the output (if any). | 省略末尾填充的= |
NO_WRAP | Encoder flag bit to omit all line terminators (i.e., the output will be on one long line). | 省略所有的终止符 |
CRLF | Encoder flag bit to indicate lines should be terminated with a CRLF pair instead of just an LF. Has no effect if NO_WRAP is specified as well. | 指示行的编码器标志位用CRLF替代LF |
URL_SAFE | Encoder/decoder flag bit to indicate using the “URL and filename safe” variant of Base64 (see RFC 3548 section 4) where - and _ are used in place of + and / | URL和文件名安全方式,替换其中不符合url安全的字符如+和/ |
NO_CLOSE | Flag to pass to Base64OutputStream to indicate that it should not close the output stream it is wrapping when it itself is closed. | 传递给Base64OutputStream标记以指示它本身关闭时不应关闭它正在包装的输出流 |
在这里大概明白了,
DEFAULT
默认会在base64字符串结果添加换行。- 而选择
NO_WRAP
会省略掉这个结尾的换行。 - 所以,问题就出在这。
- 该问题刚好在5why分析法的第五个为什么结束的时候,完美结题!
觉得好,就一键三连呗(点赞+收藏+关注)
Android问题解决:android.util.Base64.encode 导致签名不匹配 SignatureDoesNotMatch相关推荐
- Android报错:java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/Base64;如何解决
原因是使用了java标准库里的java.util.Base64这个类,编译时不会报错,但运行时直接崩溃了. 解决方法是用android自带的Base64类替换,直接import android.uti ...
- android.util.Base64 和 org.apache.commons.codec.binary.Base64
Base64编码: android.util.Base64: //b是byte类型 Base64.encodeToString(b,Base64.DEFAULT); 等于: org.apache.co ...
- Android之解决Base64 encode中文乱码问题
1.问题 需求需要,把字符串转化为UTF-8编码之后需要base64.encode处理,但是我写了 String ss = new String(value.getbytes("UTF-8& ...
- Android 数据加密算法 Des,Base64详解
一,DES加密: 首先网上搜索了一个DES加密算法工具类: import java.security.*; import javax.crypto.*; public class DesHelper ...
- Android选择/拍照 剪裁 base64/16进制/byte上传图片+PHP接收图片
转载请注明出处: http://blog.csdn.net/iwanghang/article/details/65633129 觉得博文有用,请点赞,请评论,请关注,谢谢!~ 老规矩,先上GIF动态 ...
- android 图片转换成base64
1.布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro ...
- [ Android实战 ] android query: BufferQueue has been abandoned 问题解决
[ Android实战 ] android query: BufferQueue has been abandoned 问题解决 背景 日志分析 参考资料 解决方案 源码分析 总结 尊重原创,转载请注 ...
- Android对下载的加固Apk进行签名认证
Android对下载的加固Apk进行签名认证 加固Apk签名认证 下载加固包和签名文件放到文件目录下 验证JDK环境和jarsigner命令 验证apk包是否是已经加密的 对未签名的apk进行签名 加 ...
- vue-quill-editor上传内容由于图片是base64的导致字符太长的问题解决
vue-quill-editor上传内容由于图片是base64的导致字符太长的问题解决 参考文章: (1)vue-quill-editor上传内容由于图片是base64的导致字符太长的问题解决 (2) ...
最新文章
- 视频动作定位的分层自关注网络:ICCV2019论文解析
- mac下用Dosbox搭建dos下的汇编环境
- c语言 char operator,C语言取模运算符(modulus operator)“%”的作用是什么
- python字符串使用技巧
- 结对开发Ⅴ——循环一维数组求和最大的子数组
- 关于选择,说一个同学的真实故事
- rust笔记4 slice类型
- SQL那些事儿(一)
- PHP正则匹配6到16位字符组合(且只能为数字、字母、下划线)
- 2016年小升初海淀区全部初中排名分析
- 数据提交到服务器后,在中间层所做的修改,能及时反应到客户端吗?
- 计算机一直在启动修复怎么关机,电脑开机总是要启动修复修复后重启还要修复怎么处理方法...
- Java中String、StringBuffer、StringBuilder的区别详解
- fashion minst
- Matlab fftshift函数 C 代码实现
- Revit模型如何在网页上显示
- 计算机输入网站打不开,电脑打不开网页怎么办
- java随机答题器_Advanced Random Auto Clicker免费版下载-多合一随机自动答题器 v4.21 免费版 - 安下载...
- ie8css无效,CSS 伪类在IE8中样式无法生效
- 小年到了,回家抢票太难,用Python做个脚本12306自动查票以及自动购票....