Flutter加密URL查询参数并在PHP中解密的技术问题
解决方案:Flutter加密完整查询参数 + PHP解密解析
核心思路
不要拆分加密查询参数的各个片段(如&function=),而是将所有需要传递的业务参数打包成一个完整字符串(键值对或JSON格式),整体加密后仅在URL中传递iv和加密后的密文,确保?后无明文业务参数。
Flutter端修改代码
1. 统一加密函数
删除重复的encryptJob和encryptMessage,用单一函数处理所有字符串加密:
import 'dart:convert'; import 'package:encrypt/encrypt.dart'; import 'package:http/http.dart' as http; // 假设key和iv已提前定义(需与PHP端完全一致) final Key key = Key.fromBase64('你的密钥Base64字符串'); final IV iv = IV.fromBase64('你的IVBase64字符串'); String encryptString(String input) { final encrypter = Encrypter(AES(key, mode: AESMode.cbc)); final encrypted = encrypter.encrypt(input, iv: iv); return encrypted.base64; }
2. 重构参数加密与请求逻辑
将所有业务参数打包后整体加密,URL仅传递iv和加密后的密文:
Future<void> fetchData() async { // 1. 打包所有业务参数(示例:传递function和多个job) // 方式1:键值对格式(适合简单参数) final paramsString = "function=getJobs&jobs=$job1,$job2,$job3,$job4"; // 方式2:JSON格式(适合复杂/多结构参数,推荐) // final paramsMap = { // 'function': 'getJobs', // 'jobs': [job1, job2, job3, job4] // }; // final paramsString = jsonEncode(paramsMap); // 2. 加密完整参数字符串 final encryptedParams = encryptString(paramsString); // 3. URL编码iv和密文,避免特殊字符破坏URL结构 final encodedIV = Uri.encodeComponent(iv.base64); final encodedEncryptedParams = Uri.encodeComponent(encryptedParams); // 4. 构建无明文业务参数的URL final webServiceUrl = 'http://localhost/get_encrypt_request.php?iv=$encodedIV&data=$encodedEncryptedParams'; final url = Uri.parse(webServiceUrl); final response = await http.get(url); print('$url\n'); print(response.body); setState(() { data = response.body; }); if (response.statusCode == 200) { print('请求成功'); } else { print('获取数据失败:${response.statusCode}'); } }
PHP端解密与解析代码
确保AES配置与Flutter完全一致(密钥长度、模式、填充方式),解密后解析参数:
<?php // 与Flutter端一致的密钥(需解码为二进制) $key = base64_decode('你的密钥Base64字符串'); // 接收URL参数并解码 $iv = isset($_GET['iv']) ? base64_decode(urldecode($_GET['iv'])) : ''; $encryptedData = isset($_GET['data']) ? urldecode($_GET['data']) : ''; if (empty($iv) || empty($encryptedData)) { echo json_encode(['error' => '参数缺失']); exit; } // 解密数据(注意AES-256-CBC对应256位密钥,128位则用AES-128-CBC) $decrypted = openssl_decrypt( base64_decode($encryptedData), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv ); if ($decrypted === false) { echo json_encode(['error' => '解密失败', 'detail' => openssl_error_string()]); exit; } // 解析参数(对应Flutter端的打包方式) // 方式1:解析键值对字符串 parse_str($decrypted, $params); // 方式2:解析JSON字符串(如果Flutter用JSON打包) // $params = json_decode($decrypted, true); // if (json_last_error() !== JSON_ERROR_NONE) { // echo json_encode(['error' => '参数解析失败']); // exit; // } // 业务逻辑处理 $function = $params['function'] ?? ''; $jobs = explode(',', $params['jobs'] ?? ''); if ($function === 'getJobs' && !empty($jobs)) { // 示例:根据jobs返回对应数据 $result = []; foreach ($jobs as $job) { $result[] = [ 'job_id' => $job, 'name' => '任务_' . $job, 'status' => '执行中' ]; } echo json_encode($result); } else { echo json_encode(['error' => '无效业务参数']); } ?>
关键注意事项
- 配置一致性:Flutter与PHP端必须使用相同的密钥、IV、AES模式(CBC)和填充方式(PKCS7,两端默认均为该填充)。
- URL编码:加密后的Base64字符串可能包含
+、/、=等URL特殊字符,必须用Uri.encodeComponent(Flutter)和urldecode(PHP)处理,避免参数解析错误。 - 参数打包方式:简单参数用键值对,复杂结构推荐用JSON,提升扩展性和可读性。
内容的提问来源于stack exchange,提问作者David Koch
相关产品推荐
相关产品推荐

