diff --git a/crmeb/app/adminapi/controller/Login.php b/crmeb/app/adminapi/controller/Login.php index b47a2f0ab..2239de764 100644 --- a/crmeb/app/adminapi/controller/Login.php +++ b/crmeb/app/adminapi/controller/Login.php @@ -11,9 +11,11 @@ namespace app\adminapi\controller; use crmeb\services\CacheService; +use crmeb\utils\Rsa; use think\facade\App; use crmeb\utils\Captcha; use app\services\system\admin\SystemAdminServices; +use think\facade\Cache; /** * 后台登陆 @@ -83,7 +85,7 @@ class Login extends AuthController * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ - public function login() + public function login(Rsa $rsa) { [$account, $password, $key, $captchaVerification, $captchaType] = $this->request->postMore([ 'account', @@ -102,9 +104,10 @@ class Login extends AuthController } $this->validate(['account' => $account, 'pwd' => $password], \app\adminapi\validate\setting\SystemAdminValidata::class, 'get'); + $password = $rsa->privateDecrypt($password); $result = $this->services->login($account, $password, 'admin', $key); if (!$result) { - $num = CacheService::get('login_captcha',1); + $num = CacheService::get('login_captcha', 1); if ($num > 1) { return app('json')->fail(400140, ['login_captcha' => 1]); } @@ -123,4 +126,16 @@ class Login extends AuthController { return app('json')->success($this->services->getLoginInfo()); } + + /** + * 获取 + * @return \think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + */ + public function key(Rsa $rsa) + { + return app('json')->success(['publicKey' => $rsa->getPublicKey()]); + } } diff --git a/crmeb/crmeb/utils/Rsa.php b/crmeb/crmeb/utils/Rsa.php new file mode 100644 index 000000000..a169bf26e --- /dev/null +++ b/crmeb/crmeb/utils/Rsa.php @@ -0,0 +1,194 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\utils; + +/** + * Class Rsa + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + * @package crmeb\utils + */ +class Rsa +{ + /** + * @var string + */ + protected $publicKey; + + /** + * @var string + */ + protected $privateKey; + + /** + * @var string + */ + protected $basePath; + + /** + * 获取证书文件 + * @param $publicKey + * @param $privateKey + */ + public function __construct(string $publicKey = 'cert_public_password.key', string $privateKey = 'cert_private_password.key') + { + $this->basePath = runtime_path(); + if ($publicKey) { + $this->publicKey = $this->basePath . $publicKey; + } + if ($privateKey) { + $this->privateKey = $this->basePath . $publicKey; + } + if (!is_file($this->publicKey) || !is_file($this->privateKey)) { + $this->exportOpenSSLFile(); + } + } + + /** + * @return false|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + */ + public function getPublicKey() + { + if (!is_file($this->publicKey)) { + $this->exportOpenSSLFile(); + } + + return file_get_contents($this->publicKey); + } + + /** + * 生成证书 + * @return bool + */ + public function exportOpenSSLFile($passwork = null) + { + + $publicKey = $privateKey = ''; + $dir = runtime_path() . 'conf'; + $conf = 'openssl.cnf'; + if (!is_dir($dir)) { + mkdir($dir, 0700); + } + if (!file_exists($conf)) { + touch($dir . '/' . $conf); + } + + //参数设置 + $config = [ + "digest_alg" => "sha256", + //字节数 512 1024 2048 4096 等 + "private_key_bits" => 1024, + "config" => $dir . '/' . $conf, + //加密类型 + "private_key_type" => OPENSSL_KEYTYPE_RSA, + ]; + + //创建私钥和公钥 + $res = openssl_pkey_new($config); + if ($res == false) { + //创建失败,请检查openssl.cnf文件是否存在 + return false; + } + + //将密钥导出为PEM编码的字符串,并输出(通过引用传递)。 + openssl_pkey_export($res, $privateKey, $passwork, $config); + $publicKey = openssl_pkey_get_details($res); + $publicKey = $publicKey["key"]; + + //生成证书 + $createPublicFileRet = file_put_contents($this->publicKey, $publicKey); + $createPrivateFileRet = file_put_contents($this->privateKey, $privateKey); + if (!($createPublicFileRet || $createPrivateFileRet)) { + return false; + } + + openssl_free_key($res); + return true; + } + + /** + * 数据加密 + * @param string $data + * @param string|null $passwork + * @return false|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + */ + function privateEncrypt(string $data, string $passwork = null) + { + $encrypted = ''; + $pi_key = openssl_pkey_get_private(file_get_contents($this->privateKey), $passwork);//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id + //最大允许加密长度为117,得分段加密 + $plainData = str_split($data, 100);//生成密钥位数 1024 bit key + foreach ($plainData as $chunk) { + $partialEncrypted = ''; + $encryptionOk = openssl_private_encrypt($chunk, $partialEncrypted, $pi_key);//私钥加密 + if ($encryptionOk === false) { + return false; + } + $encrypted .= $partialEncrypted; + } + + $encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的 + return $encrypted; + } + + /** + * RSA公钥解密(私钥加密的内容通过公钥可以解密出来) + * @param string $public_key 公钥 + * @param string $data 私钥加密后的字符串 + * @return string $decrypted 返回解密后的字符串 + * @author mosishu + */ + function publicDecrypt(string $data) + { + $decrypted = ''; + $pu_key = openssl_pkey_get_public(file_get_contents($this->publicKey));//这个函数可用来判断公钥是否是可用的 + $plainData = str_split(base64_decode($data), 128);//生成密钥位数 1024 bit key + foreach ($plainData as $chunk) { + $str = ''; + $decryptionOk = openssl_public_decrypt($chunk, $str, $pu_key);//公钥解密 + if ($decryptionOk === false) { + return false; + } + $decrypted .= $str; + } + return $decrypted; + } + + /** + * 私钥解密 + * @param string $data + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/5/16 + */ + public function privateDecrypt(string $data) + { + if (!is_file($this->privateKey)) { + $this->exportOpenSSLFile(); + } + + openssl_private_decrypt(base64_decode($data), $decryptedData, file_get_contents($this->privateKey)); + + return $decryptedData; + } + +}