不谈https只谈http
1、敏感信息的不可见性
使用http协议传输数据很容易被抓包监听传输内容,如果这些数据中存在敏感信息的话,风险太大了。因此我们需要对我们的传输数据进行一定的加密处理,即使数据被预期接收方之外的其它不法分子拦截,也无法轻易的破译此次请求的传输内容!最简单的方案就是对传输数据使用Base64方法转码,使得数据具备一定的不可读性。当然啦,这种方案实际上是不可取的,因为Base64方案太容易被识别然后解密了。比较常见的做法是,发送方和接收方彼此约定密钥,**发送方发送时用密钥对数据加密,接收方用密钥对数据解密。**比如AES128加密算法?但是AES128加密也存在局限性,需要定期维护。就算你认为你这方的内部人员是可信的,你也无法无法保证对方的密钥不会泄漏吧。当然聪明的你可能会说,那我就使用非对称加密算法,比如RSA好了。好像是没啥问题?但是如果数据量比较大的话,RSA加密方法对服务器的压力也是很大的。所以本次结合了AES和RSA来实现我们的数据传输。
2、防止数据被篡改
用签名!用签名!用签名!重要的事情说三遍?例如:当数据被封装好后,我们可以用md5算法计算出待传输数据的摘要字符串作为签名。当服务器接受到数据后,同样使用md5对数据做摘要,同请求报文中的签名作比较,若不一致则说明该http请求数据已被篡改。但仅仅使用md5对数据作摘要就够了吗?万一攻击方发现了数据签名是用md5做的,攻击方只需要对已篡改的数据再做一次md5,同时更新请求中的签名即可。因此如何生成可靠的签名也需要我们仔细的斟酌。有几点我觉得是需要注意的:**1、**无法轻易的根据签名推反推出当前签名所采用的算法;**2、**签名算法的复杂性、可靠性;**3、**不要直接对传输数据作签名,可以先对请求数据作摘要,再使用加密算法生成签名,既可以提升效率也在一定程度上提高了安全性。
3、http请求的真实性
有很多方案可以保证http请求的真实性。比如使用token来进行身份验证,可以借鉴微信的身份验证方案或者jwt实现。本次我们只做了简单的处理,在http请求头中设置了一个时间戳,当服务器接收到数据后,会取出http请求中的时间戳,同时与服务器当前时间作比较。若时间间隔过大,则认为该请求是不真实的,直接拒绝并返回!
发送方:
1.生成签名:将传输对象转换成json字符串jsonStr -> 使用md5对json字符串做摘要处理生成md5摘要 -> 使用RSA公钥对md5数据做加密生成签名signature(对进行md5摘要处理过的jsonStr再进行RSA加密)
2.加密请求报文:动态生成一个AES密钥AESKey->使用AES密钥对jsonStr加密生成bodyStr
3.加密AES密钥:使用Base64工具将密钥AESKey转码为密钥字符串密钥AESKeyStr -> 使用RSA公钥对AESKeyStr加密生成AESKeySecret字符串
构建http post请求
1.构造http post请求对象 -> 将签名signature放到http请求头的Authentication中 ->将AESKeySecret放到http请求头中的Secuitrykey中 -> 将当前时间timeStr放入到http请求头的TimesTamp中 ->将加密生成bodyStr放到http的body中。(将所有加密好的数据按照httppost请求方式放到应该放的位置上)
接收方:
1.请求真实性校验:从http请求头TimesTamp中获取时间戳timeStr,校验timeStr距离服务器当前时间是否超过约定的时间,如果超过,则说明请求不真实,拒绝访问。
2.获取AESKey:从http请求头SecurityKey中获取AESKeySecret字符串 -> 使用RSA密钥对AESKeySecret做解密操作获取AESKey
3.获取bodyStr:从httpbody中获取请求报文主题httpBody ->使用AESKey对httpBody做解密操作取得bodyStr
4.验签:使用MD5摘要算法对bodyStr做处理生成摘要字符串md5Str ->获取http请求头Authentication中的signature字符串 -> 使用RSA密钥对signature字符串做解密操作获取rsaDecryptStr字符串 -> 比较md5Str和rsaDecryptStr是否一致,如果一致则验签通过
业务处理:业务处理 -> 使用AESKey对返回结果做加密处理
处理http请求返回结果:接收请求返回结果 -> 使用AESKey解密返回结果