原文地址:https://blog.springcoder.cn/posts/5b7ae417.html
背景
在开发中,通常会偷懒将用户的登录信息(账号密码)直接以明文的方式发送到后端,但我们的项目不是所有都用了
https
,这在传输过程中存在一定的风险,于是,我们可以通过
RSA
非对称加密,将用户输入的账号密码进行加密后传输到后端,后端通过私钥解密后得到原始数据,进行后续的逻辑处理。
生成密钥
这里我们可以使用
linux
自带的
openssl
来生成密钥,首先生成私钥,通过如下命令生成:
openssl genrsa -out rsa_private_key.pem 1024
参数1024表示生成的密钥长度为1024比特,默认为2048,生成私钥后,我们通过私钥生成公钥:
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
通过上述命令,即可生成公钥和私钥,对应两个文件,
rsa_private_key.pem
和
rsa_public_key.pem
。
PHP加密解密工具
上述生成了密钥,我们就可以直接用来进行加解密操作了,这里介绍php中实现
rsa
的加解密,密钥文件,我们可以直接使用,也可以将密钥字符复制到php文件中,这里不直接使用密钥文件。项目基于
thinkphp5
框架,我们在extra文件夹下新增一个文件
rsa_key.php
,内容如下:
<?php/**
* rsa加密公钥私钥
*/returnarray(// 私钥'private_key'=>'原样复制私钥文件中的内容',// 公钥'public_key'=>'原样复制公钥文件中的内容',);
新增一个工具类,用于加密解密:
<?phpnamespaceapp\common\util;classRSAUtil{public$privateKey;public$publicKey;/**
* 构造方法
* @access public
*/publicfunction__construct(){//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id//如果直接使用密钥文件,可通过函数file_get_contents()进行读取$this->privateKey=openssl_pkey_get_private(config('rsa_key.private_key'));//这个函数可用来判断公钥是否是可用的$this->publicKey=openssl_pkey_get_public(config('rsa_key.public_key'));}publicfunction__call($method,$args){returnjson(['status'=>'01','msg'=>'方法不存在']);}publicfunctionprivateEncrypt($data){$crypto='';foreach(str_split($data,117)as$chunk){openssl_private_encrypt($chunk,$encryptData,$this->privateKey);$crypto.=$encryptData;}//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的$encrypted=$this->urlsafeB64encode($crypto);return$encrypted;}//加密码时把特殊符号替换成URL可以带的内容functionurlsafeB64encode($string){$data=base64_encode($string);$data=str_replace(array('+','/','='),array('-','_',''),$data);return$data;}//解密码时把转换后的符号替换特殊符号functionurlsafeB64decode($string){$data=str_replace(array('-','_'),array('+','/'),$string);$mod4=strlen($data)%4;if($mod4){$data.=substr('====',$mod4);}returnbase64_decode($data);}//私钥加密的内容通过公钥可用解密出来publicfunctionpublicDecrypt($encrypted){$crypto='';foreach(str_split($this->urlsafeB64decode($encrypted),128)as$chunk){openssl_public_decrypt($chunk,$decryptData,$this->publicKey);$crypto.=$decryptData;}return$crypto;}//公钥加密publicfunctionpublicEncrypt($data){$crypto='';foreach(str_split($data,117)as$chunk){openssl_public_encrypt($chunk,$encryptData,$this->publicKey);$crypto.=$encryptData;}$encrypted=$this->urlsafeB64encode($crypto);return$encrypted;}//私钥解密publicfunctionprivateDecrypt($encrypted){$crypto='';foreach(str_split($this->urlsafeB64decode($encrypted),128)as$chunk){openssl_private_decrypt($chunk,$decryptData,$this->privateKey);$crypto.=$decryptData;}return$crypto;}}
到此,后端的加解密就实现了。
JS前端加密传输
在登录界面,用户输入账号密码信息,点击登录,当参数校验通过,我们就可以对参数进行加密后,提交表单,这里使用
jsencrypt
实现前端的加密。
functionencrypt(data){const publicKey ={$private_key|json_encode};let encryptor =newJSEncrypt();
encryptor.setPublicKey(publicKey)return encryptor.encrypt(data)}
这样,我们可以发现,提交的数据就是被加密过的密文了。
后端接收到参数后,对参数进行解密,即可得到原始数据。
// 登录信息解密$rsaUtil=newRSAUtil();$user_name=$rsaUtil->privateDecrypt('user_name');$password=$rsaUtil->privateDecrypt('password');
版权归原作者 飞鸿先森 所有, 如有侵权,请联系我们删除。