Angular 5与PHP使用CryptoJS加密后PHP解密返回null问题
解决Angular CryptoJS加密后PHP解密返回null的问题
我之前也碰到过一模一样的问题,折腾了好一会儿才找到原因,咱们一步步来排查解决:
核心问题分析
出现null解密结果,大概率是这几个原因导致的:
- 前端直接传递了CryptoJS的加密对象,而非序列化后的字符串格式
- 请求头设置错误,导致参数没有正常传递到后端
- 后端没有先确认参数是否接收成功,且第三方解密库的逻辑和CryptoJS默认加密逻辑不匹配
修正后的前端Angular代码
ngOnInit() { let user = "am"; let key = "pizza"; // 关键:将加密对象转为字符串格式,否则后端无法解析 let enc = crypto.AES.encrypt(user, key).toString(); // 先测试本地解密是否正常,确保前端加密逻辑没问题 let dec = crypto.AES.decrypt(enc, key); console.log("本地解密结果:", dec.toString(crypto.enc.Utf8)); // 修正请求头:Access-Control-Allow-Origin是后端响应头,前端不需要设置 const headerOptions = new HttpHeaders() .set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); const params = new HttpParams().set('name', enc); this.http.post('http://aff.local/test.php', params, { headers: headerOptions }).subscribe( res => { console.log(res); alert(res) }, error => { console.log(error); } ) }
修正后的PHP脚本
<?php header('Access-Control-Allow-Origin: *'); header('Content-Type: application/json'); header('Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS'); header('Access-Control-Allow-Headers: *'); error_reporting(E_ALL); include('./cryptojs-aes.php'); ini_set('log_errors', 0); ini_set('display_errors', 1); // 先确认是否接收到参数,避免空指针问题 if (!isset($_POST['name'])) { echo json_encode(['error' => '参数name未传递']); exit; } $host = "localhost"; $db = "dentist"; $user = "root"; $pass = "root"; try { $conn = new PDO("mysql:host={$host};dbname={$db};", $user, $pass); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $conn->exec("SET CHARACTER SET utf8mb4"); $enc = $_POST['name']; $key = "pizza"; // 可以先打印加密值,确认和前端输出一致,排查参数传递问题 // var_dump($enc); $dec = cryptoJSAesDecrypt($key, $enc); if (empty($dec)) { echo json_encode(['error' => '解密失败,请检查密钥或加密格式']); } else { echo json_encode($dec); } } catch(PDOException $e) { echo json_encode(['error' => '数据库连接失败:' . $e->getMessage()]); } ?>
额外排查建议
- 验证参数传递:在PHP里用
var_dump($_POST)查看是否接收到前端传递的加密字符串,确保没有被转义或截断 - 匹配加密逻辑:如果第三方
cryptojs-aes.php库还是无法解密,可以替换成以下原生openssl实现(完全匹配CryptoJS默认加密逻辑):
function cryptoJSAesDecrypt($passphrase, $jsonString){ $obj = json_decode(base64_decode($jsonString), true); $salt = hex2bin($obj["s"]); $iv = hex2bin($obj["iv"]); $ciphertext = base64_decode($obj["ct"]); $iterations = 999; $key = hash_pbkdf2("sha1", $passphrase, $salt, $iterations, 32, true); $decrypted = openssl_decrypt($ciphertext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); return $decrypted; }
CryptoJS默认会用字符串密钥生成MD5密钥、随机IV,并将加密结果打包成JSON后base64编码,上面的函数就是对应这个流程的解密逻辑。
内容的提问来源于stack exchange,提问作者alim1990
相关产品推荐
相关产品推荐

