之前做的后台登录传递用户名、密码和验证码这些一直是明文传输,现在遇到一个客户需求是要求对传输数据进行加密传输,在服务器端解密,搜索网上的代码,测试了很久才调试通过,特贴出核心实现代码,希望对用的上的朋友有所帮助
1、调用crypto-js
这里直接字节跳动的前端静态资源库http://cdn.bytedance.com/,如过期可以网上重新搜索最新版本代码
<script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/crypto-js/4.1.1/crypto-js.min.js" type="application/javascript"></script>
2、前端加密处理代码
注意:
1)密钥key和向量iv,前端和后端应保持一致,否则后端解密失败
<script type="text/javascript">
$(function(){
$(".submit_btn").click(function(e){
e.stopPropagation();//禁止响应父元素的相关事件
e.preventDefault();//防止跳转
var username = $('.username').val();
var password = $('.password').val();
var code = $('.code').val();
var encryptedUsername = encrypt(username);
var encryptedPassword = encrypt(password);
var encryptedCode = encrypt(code);
//var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv , mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding});
//const CryptoJSDecrypt = CryptoJS.enc.Utf8.stringify(decrypted).toString();
//console.log('加密后的用户名: '+encryptedUsername);
//console.log('加密后的密码: '+encryptedPassword);
//console.log('加密后的验证码: '+encryptedCode);
$('input[name=username]').val(encryptedUsername);
$('input[name=password]').val(encryptedPassword);
$('input[name=code]').val(encryptedCode);
$('#myForm').submit();
})
})
//前端js,使用crypto-js对数据进行AES加密
function encrypt(text){
var key = CryptoJS.enc.Latin1.parse('<?php echo $_SESSION['randkey']; ?>'); //为了避免补位,直接用16位的秘钥,密钥,应保密 '1234567890654321'
var iv = CryptoJS.enc.Latin1.parse('<?php echo $_SESSION['randkey']; ?>'); //16位初始向量 '1234567890123456'
var encrypted = CryptoJS.AES.encrypt(text, key, {
iv: iv,
mode:CryptoJS.mode.CBC,
padding:CryptoJS.pad.ZeroPadding
});
return encrypted;
}
</script>
这里对前端输入框做了细节改动,原来的输入框去掉name属性,并加一个name名相同的隐藏字段,用来赋值加密后的字符串
<input type="text" name="username" placeholder="账号" class="login_txt username"> 改成 <input type="text" placeholder="账号" class="login_txt username"> <input type="hidden" name="username"> 其他密码和验证码做类似修改
3、后端实现代码
这里自定义了一个函数生成密钥,并通过$_SESSION[‘randkey’] = $this->randkey();进行保存和传输
注意,生成密钥应在展示页面的时候生成,提交数据的时候获取
随机生成密钥是出于安全考虑,保证每次访问的时候,密钥都不一样
1)需要在php扩展里开启openssl_decrypt
2)PHP版本5.6,PHP版本7.3、测试通过
3)AES-128-cbc应为小写aes-128-cbc,否则在除php7.3的其他版本解密不成功
//生成16位随机数
public function randkey(){
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$code = '';
for ($i = 0; $i < 16; $i++) {
$index = rand(0, strlen($characters) - 1);
$code .= $characters[$index];
}
return $code;
}
//登录函数里,添加如下代码,其他代码不变
public function login() {
if(isset($_GET['dosubmit'])) {
$key = $_SESSION['randkey'];//"1234567890654321";// 和前端使用相同的密钥
$iv = $_SESSION['randkey'];//"1234567890123456";// 和前端使用相同的iv
$encryptedUsername = $_POST["username"];
$encryptedPwd = $_POST["password"];
$encryptedCode = $_POST["code"];
$decryptedUsername = openssl_decrypt($encryptedUsername, 'aes-128-cbc', $key, OPENSSL_ZERO_PADDING , $iv);
$decryptedPwd = openssl_decrypt($encryptedPwd, 'aes-128-cbc', $key, OPENSSL_ZERO_PADDING , $iv);
$decryptedCode = openssl_decrypt($encryptedCode, 'aes-128-cbc', $key, OPENSSL_ZERO_PADDING , $iv);
$_POST["username"] = $decryptedUsername;
$_POST["password"] = $decryptedPwd;
$_POST["code"] = $decryptedCode;
//echo $decryptedUsername."<br />";echo $decryptedPwd."<br />";echo $decryptedCode; echo openssl_error_string();exit;
...........
}else {
$_SESSION['randkey'] = $this->randkey();
}
}

crypto-js利用AES加密用户名密码,php端利用openssl_decrypt解密,$_SESSION传递随机生成密钥代码
