POST 后从第三方网站丢失会话数据
Losing session data after POST from third party website
我有一个 Laravel 网站可以重定向到支付提供商(外部第三方网站)。当用户完成付款后,他们将通过 POST 请求重定向回我的网站。
我遇到的问题是,当用户 return 进入确认页面时,他们的会话丢失了。
我想知道这是否是 PHP 的普遍行为,但它似乎特定于 Laravel。
我检查了我的 sessions.php 配置文件,可以确认设置了以下内容 'expire_on_close' => false,
。
我已经为下面的问题创建了一个非常基本的示例
我的网站(预售)
控制器
public function redirect()
{
$user = Auth::user();
dd($user); // returns User model;
redirect()->away('http://www.example.com');
}
支付提供商网站
请注意,请求是通过浏览器内的应用程序发送的 - 而不是回调。也没有按钮。我只是想演示 POST 回到 Laravel 站点。
<html>
<head></head>
<body>
<form method="POST" action="http://www.example.com/payment/confirmation">
<input type="submit">
</form>
</body>
</html>
我的网站(post-促销)
路线
Route::post('/payment/confirmation', 'Payment\PaymentController@confirmation');
控制器
public function confirmation()
{
$user = Auth::user();
dd($user); // Returns null
}
我已将路径添加到 VerifyCsrfToken 中间件的异常数组。 Laravel 中是否有任何东西会破坏通过外部网站在 POST 上的会话?我确定我遗漏了一些明显的东西。谢谢
在我的测试中,会话似乎并没有真正被销毁。但是在接收到外部POST请求时不会加载,如果允许return到主站触发新的session会被销毁会话保存。通过发送 header()
重定向并在保存新会话之前终止进程,似乎可以恢复现有会话。
好吧,也许有点恶心?
Route::match(['get','post'],'/payment/confirmation','Payment\PaymentController@confirmation');
public function confirmation(Request $request)
{
// assert cookie or reload current URL
if (! $request->hasHeader('Cookie')) {
header('Location: '.url()->current());
exit;
}
$user = Auth::user();
dd($user); // user exists!
}
我不会说这是一个很好的解决方案。确实感觉有点hackish。可能需要进行一些额外的测试。但乍一看,它似乎确实有效——至少对我而言是这样。也许它可以让您深入了解幕后实际发生的事情。
此外,我不确定您是否要将付款确认页面公开给 GET 请求。
但这是一个有趣的兔子洞。
我通过在 config/session.php 中将 'same_site' => 'lax',
更改为 'same_site' => null,
解决了这个问题。这似乎是 Laravel 7+ 中的新设置。
在没有进一步阅读的情况下,我不确定此更改是否会导致任何安全隐患,但目前,这可以解决问题。以某种方式将某些域列入白名单将是一个不错的功能。
设置 'same_site' => null 可能无法再次按预期工作,因为与 Cookie SameSite 属性相关的标准最近发生了变化 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
新的默认值现在是 Lax,因此如果您将 same_site 设置为 null,浏览器将采用默认值 Lax,这不是您需要的策略。
您需要明确设置 'same_site' =>“none”,same_site 的值 none 要求您的连接是安全的,因此,设置 'secure' => 真。
'same_site' => "none"
'secure' => true
您应该将您的 cookie session 保留到 'lax',您不希望您的 cookie 在其他网站上可用,等等。
我发现的修复方法是在登录时传递 true 以记住。
示例:
Auth::login(
user: $user,
remember: true
);
$request->session()->regenerate();
您的用户现在将无限期登录,直到他们注销,即离开您的站点并通过重定向 headers 返回等等。我在使用 Passport 接收 Oauth 回调时发现了这一点,此时我需要让用户登录,但将他们重定向到他们租户的子域。
通常您只希望 session 在您的根域和子域中可用,例如 config/env.
中的 .mydomain.com
我有一个 Laravel 网站可以重定向到支付提供商(外部第三方网站)。当用户完成付款后,他们将通过 POST 请求重定向回我的网站。
我遇到的问题是,当用户 return 进入确认页面时,他们的会话丢失了。
我想知道这是否是 PHP 的普遍行为,但它似乎特定于 Laravel。
我检查了我的 sessions.php 配置文件,可以确认设置了以下内容 'expire_on_close' => false,
。
我已经为下面的问题创建了一个非常基本的示例
我的网站(预售)
控制器
public function redirect()
{
$user = Auth::user();
dd($user); // returns User model;
redirect()->away('http://www.example.com');
}
支付提供商网站
请注意,请求是通过浏览器内的应用程序发送的 - 而不是回调。也没有按钮。我只是想演示 POST 回到 Laravel 站点。
<html>
<head></head>
<body>
<form method="POST" action="http://www.example.com/payment/confirmation">
<input type="submit">
</form>
</body>
</html>
我的网站(post-促销)
路线
Route::post('/payment/confirmation', 'Payment\PaymentController@confirmation');
控制器
public function confirmation()
{
$user = Auth::user();
dd($user); // Returns null
}
我已将路径添加到 VerifyCsrfToken 中间件的异常数组。 Laravel 中是否有任何东西会破坏通过外部网站在 POST 上的会话?我确定我遗漏了一些明显的东西。谢谢
在我的测试中,会话似乎并没有真正被销毁。但是在接收到外部POST请求时不会加载,如果允许return到主站触发新的session会被销毁会话保存。通过发送 header()
重定向并在保存新会话之前终止进程,似乎可以恢复现有会话。
好吧,也许有点恶心?
Route::match(['get','post'],'/payment/confirmation','Payment\PaymentController@confirmation');
public function confirmation(Request $request)
{
// assert cookie or reload current URL
if (! $request->hasHeader('Cookie')) {
header('Location: '.url()->current());
exit;
}
$user = Auth::user();
dd($user); // user exists!
}
我不会说这是一个很好的解决方案。确实感觉有点hackish。可能需要进行一些额外的测试。但乍一看,它似乎确实有效——至少对我而言是这样。也许它可以让您深入了解幕后实际发生的事情。
此外,我不确定您是否要将付款确认页面公开给 GET 请求。
但这是一个有趣的兔子洞。
我通过在 config/session.php 中将 'same_site' => 'lax',
更改为 'same_site' => null,
解决了这个问题。这似乎是 Laravel 7+ 中的新设置。
在没有进一步阅读的情况下,我不确定此更改是否会导致任何安全隐患,但目前,这可以解决问题。以某种方式将某些域列入白名单将是一个不错的功能。
设置 'same_site' => null 可能无法再次按预期工作,因为与 Cookie SameSite 属性相关的标准最近发生了变化 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
新的默认值现在是 Lax,因此如果您将 same_site 设置为 null,浏览器将采用默认值 Lax,这不是您需要的策略。
您需要明确设置 'same_site' =>“none”,same_site 的值 none 要求您的连接是安全的,因此,设置 'secure' => 真。
'same_site' => "none"
'secure' => true
您应该将您的 cookie session 保留到 'lax',您不希望您的 cookie 在其他网站上可用,等等。
我发现的修复方法是在登录时传递 true 以记住。
示例:
Auth::login(
user: $user,
remember: true
);
$request->session()->regenerate();
您的用户现在将无限期登录,直到他们注销,即离开您的站点并通过重定向 headers 返回等等。我在使用 Passport 接收 Oauth 回调时发现了这一点,此时我需要让用户登录,但将他们重定向到他们租户的子域。
通常您只希望 session 在您的根域和子域中可用,例如 config/env.
中的.mydomain.com