之前做的后台登录传递用户名、密码和验证码这些一直是明文传输,现在遇到一个客户需求是要求对传输数据进行加密传输,在服务器端解密,搜索网上的代码,测试了很久才调试通过,特贴出核心实现代码,希望对用的上的朋友有所帮助
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版本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(); } }