用hash_hmac()签名电子邮件。
$token = hash_hmac('sha256', 'email@example.com', 'secret-server-key');
然后将其传递给电子邮件模板,因此您的退订链接将类似于:
<a href="http://example.com/unsubscribe?email=email@example.com&token=abcec5cdca4d760d34e8c02107ae68f251f08aaa9dd14956c2f0ab84a33f6441">
然后当用户单击它时,对电子邮件参数进行签名,如果令牌匹配则继续。
<?php
if (isset($_GET['email'], $_GET['token']) &&
$_GET['token'] === hash_hmac('sha256', $_GET['email'], 'secret-server-key')
) {
// lagit
}
只要您不分享secret-server-key,这是安全的。
编辑:
挑战来自@FunkFortyNiner 的 cmets
您可以对电子邮件进行签名并将其编码为单个令牌。本质上就像现在的 JWT 但没有 json ;p
所以你的令牌看起来像:ZW1haWxAZXhhbXBsZS5jb20.abcec5cdca4d760d34e8c02107ae68f251f08aaa9dd14956c2f0ab84a33f6441,但会涉及更多的检查代码。如果你真的很偏执,也许它是值得的。
<?php
$email = 'email@example.com';
function base64url_encode($str) {
return rtrim(strtr(base64_encode($str), '+/', '-_'), '=');
}
function base64url_decode($str) {
return base64_decode(strtr($str, '-_', '+/'));
}
$token = base64url_encode($email).'.'.hash_hmac('sha256', $email, 'secret-server-key');
// mock got token
$_GET['token'] = $token;
// when checking
if (isset($_GET['token'])) {
$tok = explode('.', $_GET['token']);
// check token parts
if (count($tok) !== 2) {
// not valid token
throw new \Exception('Invalid token!');
}
// check email segment
if (!isset($tok[0]) || !filter_var(base64url_decode($tok[0]), FILTER_VALIDATE_EMAIL)) {
// not valid email
throw new \Exception('Invalid token!');
}
$email = base64url_decode($tok[0]);
if ($tok[1] !== hash_hmac('sha256', $email, 'secret-server-key')) {
// failed verification
throw new \Exception('Invalid token!');
}
//
echo 'Its lagit!';
// do somthing with $email
}
https://3v4l.org/tcqk8