最近遇到了一个问题
已经开发、联调完毕的接口,突然在debug模式下运行,调用接口返回签名校验失败,但是release包却没有任何问题
签名计算的过程是把模型内所有字段拼接起来,再按照一个规则产生的
先是看了代码记录,发现这段逻辑没有动过
然后就断点,着重看下签名计算流程
我们是先产生一个requestModel,然后使用反射,获取它的内部所有属性,将他们拼接
断点中发现,反射获取到的requestModel的字段,比我们真实代码中的requestModel类多了两个属性
如图,多出了一个$change和serialVersionUID
最后发现,果然是因为我们后来打开了Instant Run,导致此处反射获取类的属性,比原来多个两个,最终导致客户端签名和服务端的不一致
因为Instant Run为了实现热部署的效果,需要在class中加入字段来表明该类是否有变动
该问题关掉Instant Run可以解决,如需要使用Instant Run,则要在反射代码中加入判断, 遇到$change和serialVersionUID这两个字段时,不参与签名计算
代码如下:
Field[] declaredFields = obj.getClass().getDeclaredFields(); for (Field field : declaredFields) { field.setAccessible(true); if(!(("$change".equals(field.getName()))||("serialVersionUID".equals(field.getName())))){ map.put(field.getName(), field.get(obj)); } }
或者使用该方法也可以判断,是否是由编译器合成的字段:field.isSynthetic()