上一篇文章讲了后端java的数据加密的一些常见方式和代码,实际应用中我们会前后端交互,js加密,java解密,或者java加密,js解密,另外引申出数据传输的安全问题。
在之前写的用Hbuilder开发app的文章中介绍了,我们利用js+css就可以开发出自己的混合app,访问服务器接口利用的是封装好的mui ajax,所以和服务器数据的交互也是通过js的ajax来进行的,因此开发app面临的数据传输问题也可以归类为前后端的数据交互安全问题。
比如我们使用ajax的GET方式提交数据,数据就会以拼接的方式拼接到URL中,这时候数据就会赤果果的展示在别人的面前,还是和java类似,我们用Base64对数据进行加密,Base64加密方式是将原文经过简单的字符转换,转换成不容易被肉眼看出的字符编码,但是标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。
为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充’='号,并将标准Base64中的“+”和“/”分别改成了“*”和“-”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。
此外还有一些变种,它们将“+/”改为“-”或“.”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。
Base64要求把每三个8Bit的字节转换为四个6Bit的字节(38 = 46 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
使用方式:我们需要先引入Base64.js,然后调用Base64.encode(string)可以加密,调用Base64.decode(str)就可以解密了。具体代码网上很多,这里就不占字数贴代码了。
实际上js运行在客户端,我们的加密方式很容易被有心人打开源码获取到,我们用base64也只是让人不会一眼看出来明文,当得知我们使用base64加密,直接用base64解密就可以得到正确的内容,如果我们想要加密内容不可逆,可以使用js的md5加密。
在需要加密的页面引用MD5脚本文件:<script src="js/md5.js" type="text/javascript"></script>
然后直接调用就可以了:hex_md5("hello md5");
如果一定要对数据进行加密,还需要可解密的加密方法,那么一是对js进行混淆压缩,二是使用非对称加密算法(详见上一章),web端持有公钥,服务器端持有私钥,即使js被获取到也无法解密公钥加密的信息,因为只有私钥可以解密。
JS中常用的RSA加密库有:jsencrypt,jsrsasign,js-crypto-rsa
简单讲一下jsencrypt的用法:
首先我们需要有一对公钥和私钥,具体可以通过java编写代码获得,或者在网上在线生成公私钥的网站获取到。
然后引入jsencrypt.js:<script src="https://cdn.bootcss.com/jsencrypt/3.0.0-beta.1/jsencrypt.js"></script>
具体使用代码:
<script type="text/javascript">
//公钥
var PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDZUq6x7peTFDMOfgTP4uZhC0oeGNdbEKvQdPnaBRqTJOcuQBc5rsXBULkUtjv0pPbJT1iC127nXq78o35ON7t0dRLS1GM8iZZDMUa4Feqgd+TjSEm0sMiGgAlwVJKkDWykew0N/C8Q9ZtIyU9lACuojZaloT1CBuGxbZRTtfJgQIDAQAB';
//使用公钥加密
var encrypt = new JSEncrypt();
var str = {
"userName":"zhangSan",
"password":"123456"
};
encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + PUBLIC_KEY + '-----END PUBLIC KEY-----');
var encrypted = encrypt.encrypt(str);
console.log('加密后数据:%o', encrypted);
</script>
然后通过ajax传到后台之后java进行解密:
/**
*私钥字符串转私钥RSAPrivateKey
*/
public static RSAPrivateKey getRSAPrivateKeyBybase64(String privateKeyStr) {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(CodeUtils.base64Decode(privateKeyStr));
RSAPrivateKey privateKey = null;
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
try {
privateKey = (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
} catch (InvalidKeySpecException msg) {
LOGGER.error("转换失败:"+msg);
}
return privateKey;
}
/**
*利用私钥解密信息
*/
String privateKeyStr = '私钥balabala';
RSAPrivateKey rsaPrivateKey = getRSAPrivateKeyBybase64(privateKeyStr);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,rsaPrivateKey);
b = cipher.doFinal("前台传来的加密信息".getBytes());
System.out.println(new String(b));
其他的对于如何校验数据在传输过程中是否被篡改,还有如何合理设计权限校验等等,再专门拿一篇文章来整理。
另外如果有兴趣一起进步学习,请搜索名称关注我的公众号:IT成长日记
或扫码关注: