我正在使用带有内置用户电子邮件验证流程的 Laravel 7.3。
我正在尝试在流程中实现“返回 URL”,以便在验证用户的电子邮件后将用户重定向到特定的 URL。这对于用户在应用程序上启动操作(例如订阅)很有用。该操作需要一个帐户,并且一个帐户需要验证。
我在流程的每一步都在 URL 中包含了返回 URL,并且正在生成一个如下所示的验证 URL:
https://localhost/email/verify/287/23e499466a6bad538df7ce48e090294502502a86?expires=1630005974&signature=f77d57494132c71735e744a224e5116974fec33b482ec5874c40ca6321d200e6&return=https://localhost/subscribe
到目前为止,一切都很好。但是,这会返回 403。跟踪它会导致我:
vendor\laravel\framework\src\Illuminate\Routing\UrlGenerator.php
/
Illuminate\Routing\UrlGenerator
public function hasCorrectSignature(Request $request, $absolute = true)
{
$url = $absolute ? $request->url() : '/'.$request->path();
$original = rtrim($url.'?'.Arr::query(
Arr::except($request->query(), 'signature')
), '?');
$signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));
return hash_equals($signature, (string) $request->query('signature', ''));
}
倾倒$original
向我展示了这一点:https://localhost/email/verify/287/23e499466a6bad538df7ce48e090294502502a86?expires=1630005974&return=https%3A%2F%2Flocalhost%2Fsubscribe%2F2
这是我所期待的,但函数返回false
,它会抛出 403。
我无法想象这是一个不寻常的用例,但我正在努力在网上找到有关实现它的最佳方法的任何信息。
下面是我构建 URL 的方式,这在我的VerifyEmail
通知中。我尝试添加return
作为签名路由本身的参数,但它也是 403s:
$url = URL::temporarySignedRoute(
'verification.verify',
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
[
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
]
);
// Add this here rather than as a parameter so it doesn't form part of the hash
$url = $url.'&return='.request()->get('return') ?? '';
return $url;
更令人费解的是,如果在验证 URL 中return
为空,那么如果验证就好了。例如这有效:
https://localhost.com/email/verify/287/23e499466a6bad538df7ce48e090294502502a86?expires=1630005974&signature=f77d57494132c71735e744a224e5116974fec33b482ec5874c40ca6321d200e6&return=
编辑:
经过进一步调查后,我发现将返回 URL 添加到签名 URL 生成意味着它只要return
不为空就可以工作。如果传递的是空字符串,则在验证时会生成 403。
$url = URL::temporarySignedRoute(
'verification.verify',
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
[
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
'return' => rtrim(request()->get('return'), '/') ?? '',
]
);
return $url;
如果有return
值,上述工作正常,否则为 403s。