场景
小程序请求的所有接口参数必须加密,后台返回数据也需要加密,并且增加Token验证
一、小程序端功能编写
1.下载一份Js版的aesUtil.js源码。【注:文章末尾会贴出所有的相关类文件】
2.下载一份Js版的md5.js源码。
3.在pulic.js中进行加解密操作代码如下,其中秘钥和秘钥偏移量要与后台的一致。
var CryptoJS = require('aesUtil.js'); //引用AES源码js
)
iv '91129048100F0494'//十六位十六进制数作为秘钥偏移量
//解密方法
encryptedHexStr Hex);
decrypt AESdecryptsrcs, key{
modemodeCBC
});
return decryptedStr();
}
Encrypt{
encrypted encrypt{
Pkcs7
encryptedciphertext().toupperCase
module
exportsDecrypt;4.在网络请求帮助类中进行参数的加密和返回数据的解密操作。
)
* 网络请求
requestmethod loading urlparams success fail url BASE_URL + //请求参数转为JSON字符串
consolelogurl ' params=> ' jsonStr)
token productionToken//加密请求参数
'请求=>明文参数:')
aesData)
wxrequest({
'Content-Type''application/x-www-form-urlencoded;charset=utf-8'
token
data{
//判断请求结果是否成功
null //解密返回数据
data);
'返回=>明文数据:'result successJSON))
}
}
其中生成Token的规则,【生成Token的规则可根据具体的业务逻辑自己定义,我这里使用的规则是根据请求参数的字母排序取其value并加上当前时间戳再进行MD5加密】
* 生成Token
obj utilobjKeySort value '';
}
value getTokenDatenewDate())
valuereplace/\s+/g""//进行UTF-8编码
md5hex_md5;
objKeySortobj//先用Object内置类的keys方法获取要排序对象的属性名,再利用Array原型上的sort方法对获取的属性名进行排序,newkey是一个数组
//创建一个新的对象,用于存放排好序的键值对
//遍历newkey数组
newObjnewkeyi]]]];
//返回排好序的新对象
}
二、服务端功能编写
由于初学SpringMVC,使用的方式不一定是最优最好的,如有不妥善之处,请各位看官多多指教
思路:
通过过滤器拦截请求参数,通过自定义参数包装器对参数进行解密。
在拦截器获取请求的Token并生成服务器端Token进行验证。
对返回参数通过JSON转换器进行加密处理。
思路图
1.重写HttpServletRequestWrapper,在自定义的HttpServletRequestWrapper 中对参数进行处理
* Created by 吴蜀黍 on 2018-08-07 09:37
@Slf4j
ParameterRequestWrapperHttpServletRequest // 将request交给父类,以便于调用对应方法的时候,将其输出,其实父亲类的实现方式和第一种new的方式类似
//将参数表,赋予给当前的Map以便于持有request中的参数
modifyParameterValues //重载一个构造方法
addAllParametersextendParams);//这里将扩展参数写入参数表
String aesParameter getParameterConstantsNetWorkAES_DATA logdebug"[modifyParameterValues]==========>加密数据:{}" aesParameter//解密
try decryptParameter AesUtilsaesParameterAES_KEY log"[modifyParameterValues]==========> 解密数据:{}" decryptParameter);
aesFlagtruecatchCommonBusinessException efalseerror"[modifyParameterValues]""[modifyParameterValues]==========>"}
/**
*/
@Override
Enumeration getParameterNamesVector<>(()).elements}
name//重写getParameter,代表参数从当前类中的map获取
[];
addAllParameters otherParams//增加多个参数
addParameterObject//增加参数
{
}
* Created by 吴蜀黍 on 2018-08-07 10:02
initFilterConfig filterConfigthrowsservletexception doFilterServletRequest servletRequestServletResponse servletResponseFilterChain filterChainIOException//使用自定义的参数包装器对参数进行处理
destroy}
web.xml中对过滤器进行配置
<filter>
<filter-class>com.xxx.xxx.config.filter.ParameterFilter</filter-class>
<filter-mapping>
<!-- 过滤所有以.json结尾的资源-->
</filter-mapping>
AES加解密操作
* Created by 吴蜀黍 on 2018-08-03 17:47
staticfinal CHARSET_NAME "UTF-8" AES_NAME "AES";
SecurityaddProviderBouncyCastleProvider/**
*/
Exception exthrowCommonBusinessException"加密失败"}
* 解密
());
2.新建拦截器,验证Token以及解密的判断
preHandle httpServletRequestHttpServletResponse httpServletResponse handler//如果不是映射到方法直接通过
aesSuccess BooleanparseBooleanhttpServletRequestgetParameter));
//获取客户端上传Token
(!TokenUtilsverificationToken()))MSG_TOKEN_INVALID;
* 验证失败 发送消息
//对验证失败的返回信息进行加密
"[sendMsg]" writerprintclose();
}
<!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 -->
<!-- 拦截所有请求 -->
<!-- 需排除拦截的地址 -->
<beanclass"com.xxx.xxx.config.interceptor.Asynchandlerinterceptor"/>
</mvc:interceptors>
Token的验证
* Describe:Token帮助类
**/
TokenUtils * 验证Token
* @param token 客户端上传Token
* @return boolean
verificationToken tokenMap mapTypessaleEquals getTokenmapTypes));
List mapKes ArrayList<>();
||
CollectionsmapKesStringBuilder sb StringBuilder();
sbappend//加上时间戳,去除所有空格 进行MD5加密
}
3.对返回数据进行加密处理,新建JSON转换器继承自阿里的FastJsonHttpMessageConverter
* Created by 吴蜀黍 on 2018-08-07 13:57
HttpMessageNotWritableExceptionOutputStreamoutgetBody"[writeInternal]======>返回明文数据:{}" jsonString//对返回数据进行AES加密
();
spring中对JSON转换器进行配置
<mvc:message-converters>
"com.xxx.xxx.config.converter.JsonMessageConverter">
<list>
application/json</value>
</list>
"features">
<!-- 默认的意思就是不配置这个属性,配置了就不是默认了 -->
WriteMapNullValue</value>
WriteDateUseDateFormat</value>
</property>
</mvc:message-converters>
三、测试
1.控制器
* Created by 吴蜀黍 on 2018-08-08 11:13
@RequestMapping"/test"TestController"/test.json"@ResponseBody
createSuccessObj"测试成功"}
2.测试结果
客户端
服务端
在后台自动加解密模块中,原本是打算都在JSON转换器中处理,通过readInternal()解密,再通过writeInternal()加密,奈何调试的过程中总会出现一些未知错误,如有相关大神,请帮忙指点迷津!通过过滤器来处理参数有些大材小用的意思,如果哪位有更好的方案和处理方式欢迎留言,感激不尽!!!
四、客户端JS下载
客户端JS下载,密码:qxql