为什么要研究这个呢,因为我所在单位的信息管理部门在监控系统上发现有大量的明文账号(身份证号)和密码在传输,被告知这很不安全,索性就直接解决这个问题,利用JS前端加密PHP后端再加密来解决这个问题,保证传输过程中数据的非明文传递。
一、登录界面
<script src="js/jquery-1.8.3.min.js"></script>
<script src="js/rollups/aes.js"></script>
<script src="js/components/pad-zeropadding.js"></script>
<script src="js/aes-function.js"></script>
<script>
//以上引用文件会在后面给出文件压缩包(顺便在这里鄙视一下有些论坛,无论什么东西都要下载积分花钱,我也是付费购买后给大家分享出来)
function checkform_login(){
if ($("#username").val()==""){
$("#username").focus();
alert("请输入您的账号!")
return false
}else if ($("#password").val()==""){
$("#password").focus();
alert("请输入您的密码!")
return false
}else{
$("#u_dlcode").val(js_encrypt($("#username").val()))
$("#p_dlcode").val(js_encrypt($("#password").val()))
//$("#username").val($("#u_dlcode").val()+123)
//return false
$("#form_login_true").submit();
return true
}
}
//前端js,使用crypto-js对数据进行AES加密
function js_encrypt(text){
var key = CryptoJS.enc.Latin1.parse('1E390CMD585LLS4S'); //为了避免补位,直接用16位的秘钥
var iv = CryptoJS.enc.Latin1.parse('1104432290129056'); //16位初始向量(请记住这两个都要保证是16位)
var encrypted = CryptoJS.AES.encrypt(text, key, {
iv: iv,
mode:CryptoJS.mode.CBC,
padding:CryptoJS.pad.ZeroPadding
});
return encrypted;
}
</script>
<!--这里只列出必要的页面构成元素,其它布局页面的不再列出了 -->
<!--给用户展示的登录输入框 -->
<form id="form_login" name="form_login" action="javascript:;" method="post">
<input name="username" id="username" type="text" maxlength="20" hidefocus="true" />
<input name="password" id="password" type="password" hidefocus="true" /></td>
<input type="button" name="Submit" id="dlbutton" value="登录系统" onclick="checkform_login()" />
</form>
<!--用户输入完成后,真实POST提交的表单 -->
<form id="form_login_true" name="form_login_true" action="checklogin.html" method="post">
<input name="u_dlcode" id="u_dlcode" type="hidden" value="" />
<input name="p_dlcode" id="p_dlcode" type="hidden" value="" />
</form>
二、PHP验证登录界面
//openssl_encrypt解密,前端通过JS加密
function js_decrypt_openssl($encrypt){
$key = "1E390CMD585LLS4S"; //与JS端的KEY一致
$iv = "1104432290129056"; //这个也是要与JS中的IV一致
//$encrypt = base64_ decode($encrypt); //注意这里的base64_和decode之间不应该有空格,我这么写是因为触发了西数的安全机制,不允许在内容中有这个函数
$decrypted = openssl_decrypt($encrypt, 'AES-128-CBC', $key, 2 , $iv);
$decrypted = rtrim($decrypted, "�");//这个一定要有,要不然在你不用浏览器查看源代码的情况下是很难发现,还有一些乱码存在的
return $decrypted;
}
$u_dlcode=$_POST["u_dlcode"];
$p_dlcode=$_POST["p_dlcode"];
$u_dlcode=iconv('utf-8','gbk',js_decrypt_openssl($u_dlcode));//我这里因为编码问题,防止有中文用户名的,所以我这里再次用iconv转码,这块根据自己程序的需要吧。
$password=iconv('utf-8','gbk',js_decrypt_openssl($p_dlcode));
//以下为PHP验证程序
拿到了POST过来的账号和密码,下面的验证程序大家应该都会的。到此利用前端JS加密,PHP后端解密就完成了,这就有效保证了,在提交前防止别人从路由上截获明文的账号和密码了。
另说明一下我本地使用的是AppServ搭建的PHP7.1.1环境,PHP7.1版本后建议大家使用openssl_decrypt函数。看到以前的代码中,加密解密用的mcrypt 比较多,但是mcrypt 扩展已经过时了大约10年,并且用起来很复杂。因此它被废弃并且被 OpenSSL 所取代。 从PHP 7.2起它将被从核心代码中移除并且移到PECL中。
附上相关JS脚本下载:js前端加密PHP后端解密.rar