如何使用URLencode?请求协助实现URL加密防篡改
我来帮你搞定这个URL编码的问题,先理清楚你的需求和现有代码里的问题:
你想要把URL里的参数部分(包括?和&这些特殊字符)编码成合法的格式,同时希望一定程度上防止用户随意修改参数。不过要先明确:URL编码只是让特殊字符符合URL规范,并不是真正的加密——用户还是可以通过解码工具还原参数。如果要彻底防止修改,得用签名或加密的方式,后面我会提到。
先看你现有代码里的问题:
- 第一个链接直接写了未编码的参数,虽然浏览器会自动处理部分特殊字符,但不够规范;
- 第二个链接的编码格式完全错误(比如
%3Fclient%&3A这种写法是不对的),属于手动乱编的,不符合URL编码规则。
方案1:生成合法的带编码参数的跳转链接(直接跳转用)
如果你的需求是点击链接后直接跳转到indexTest.php并传递参数,只需要对每个参数的值单独编码即可,这样生成的URL既合法,后端也能正常获取参数:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" > <head> <title>Envoi de paramètres dans l'URL</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <?php // 对每个参数的值单独编码 $client = urlencode("Balmain"); $jira = urlencode("Evo8"); $contact = urlencode("Balmain@yahoo.fr"); ?> <p><a href="indexTest.php?client=<?php echo $client; ?>&jira=<?php echo $jira; ?>&contact=<?php echo $contact; ?>">Cliquer ici pour remplir le formulaire!</a></p> </body> </html>
生成的URL会是:indexTest.php?client=Balmain&jira=Evo8&contact=Balmain%40yahoo.fr,其中@被正确编码为%40,符合URL规范。
方案2:把整个URL编码成字符串(用于作为其他参数的值)
如果你的需求是把整个indexTest.php?client=...作为一个编码后的字符串(比如传递给另一个页面作为参数),可以直接对完整URL用urlencode()处理,就能得到你期望的格式:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" > <head> <title>Envoi de paramètres dans l'URL</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <?php $fullUrl = "indexTest.php?client=Balmain&jira=Evo8&contact=Balmain@yahoo.fr"; $encodedFullUrl = urlencode($fullUrl); // 这里可以把编码后的字符串作为参数传递,或者直接输出 echo '<p><a href="anotherPage.php?target=' . $encodedFullUrl . '">Cliquer ici pour remplir le formulaire!</a></p>'; // 如果只是想输出编码后的URL文本,可以直接echo $encodedFullUrl; ?> </body> </html>
此时$encodedFullUrl的值就是你想要的:indexTest.php%3Fclient%3DBalmain%26jira%3DEvo8%26contact%3DBalmain%40yahoo.fr
进阶:防止用户修改参数(真正的防篡改)
前面说过,URL编码不防篡改。如果要确保用户不能修改参数后提交,推荐用签名验证的方式:给参数添加一个基于密钥生成的签名,后端接收时验证签名是否匹配,不匹配就拒绝处理。
生成带签名的链接:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" > <head> <title>Envoi de paramètres dans l'URL</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <?php // 定义参数和保密密钥(后端要和这里用同一个密钥) $params = [ 'client' => 'Balmain', 'jira' => 'Evo8', 'contact' => 'Balmain@yahoo.fr' ]; $secretKey = 'your-own-secret-key-keep-it-safe'; // 生成签名:对参数排序后拼接,用哈希算法生成签名 ksort($params); $signature = hash_hmac('sha256', http_build_query($params), $secretKey); $params['signature'] = $signature; // 生成最终的URL $finalUrl = 'indexTest.php?' . http_build_query($params); ?> <p><a href="<?php echo $finalUrl; ?>">Cliquer ici pour remplir le formulaire!</a></p> </body> </html>
后端(indexTest.php)验证签名:
<?php $secretKey = 'your-own-secret-key-keep-it-safe'; $receivedParams = $_GET; // 取出签名并移除,准备验证 if (!isset($receivedParams['signature'])) { die("参数无效"); } $signature = $receivedParams['signature']; unset($receivedParams['signature']); // 重新生成预期签名,和接收的签名对比 ksort($receivedParams); $expectedSignature = hash_hmac('sha256', http_build_query($receivedParams), $secretKey); if ($signature !== $expectedSignature) { die("参数已被修改,拒绝处理"); } // 验证通过,正常使用参数 $client = $receivedParams['client']; $jira = $receivedParams['jira']; $contact = $receivedParams['contact']; ?>
这样用户只要修改任何参数,签名就会不匹配,后端就能识别并拒绝处理。
内容的提问来源于stack exchange,提问作者Daniel Jean

