简体   繁体   English

从第三方网站 POST 后丢失 session 数据

[英]Losing session data after POST from third party website

I have a Laravel site that redirects to a payment provider (external third party website).我有一个重定向到支付提供商(外部第三方网站)的 Laravel 网站。 When the user completes their payment, they are redirected back to my site via a POST request.当用户完成付款时,他们将通过 POST 请求重定向回我的网站。

The issue I'm having is that the user's session is lost when they return to the confirmation page.我遇到的问题是,当用户返回确认页面时,用户的 session 丢失了。

I wondered if this was behaviour of PHP generally but it seems to be specific to Laravel.我想知道这是否是 PHP 的一般行为,但它似乎特定于 Laravel。

I have checked my sessions.php config file and can confirm the following is set 'expire_on_close' => false, .我已经检查了我的 sessions.php 配置文件,可以确认以下设置为'expire_on_close' => false,

I've created a very basic example of the issue below我在下面创建了一个非常基本的问题示例

My website (pre-sale)我的网站(预售)

Controller Controller

public function redirect()
{
    $user = Auth::user();
    dd($user); // returns User model;
    redirect()->away('http://www.example.com');

}

Payment provider website支付提供商网站

Note, the request is sent via the application within the browser - not a callback.请注意,请求是通过浏览器中的应用程序发送的——而不是回调。 There is also no button.也没有按钮。 I just want to demonstrate the POST back to the Laravel site.我只想演示返回 Laravel 站点的 POST。

<html>
<head></head>
<body>

    <form method="POST" action="http://www.example.com/payment/confirmation">
        <input type="submit">
    </form>

</body>
</html>

My website (post-sale)我的网站(售后)

Route路线

Route::post('/payment/confirmation', 'Payment\PaymentController@confirmation');

Controller Controller

public function confirmation()
{

    $user =  Auth::user();
    dd($user); // Returns null

}

I have added the path to the VerifyCsrfToken middleware's exception array.我已将路径添加到 VerifyCsrfToken 中间件的异常数组。 Is there anything within Laravel that would destroy the session on POSTing via an external website? Laravel 中是否有任何东西会破坏通过外部网站发布的 session? I'm sure I'm missing something obvious.我确定我遗漏了一些明显的东西。 Thanks谢谢

In my testing, it seems the session is not actually destroyed.在我的测试中,session 似乎实际上并没有被破坏。 However, it is not loaded when receiving the external POST request, and the session will be destroyed if you allow the return to the main site to trigger a new session save.但是在接收到外部POST请求时没有加载,如果允许返回主站点触发新的session保存,session会被破坏 By sending a header() redirect and terminating the process before a new session can be saved, it seems that it is possible to restore the existing session.通过在保存新的 session 之前发送header()重定向并终止进程,似乎可以恢复现有的 session。

Okay, perhaps it's a bit gross?好吧,也许有点恶心?

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!
}

I'm not going to say this is a great solution.我不会说这是一个很好的解决方案。 It does feel a bit hackish.确实感觉有点hackish。 Some additional testing may be required.可能需要进行一些额外的测试。 But at first blush, it does seem to work — at least on my end.但乍一看,它似乎确实有效——至少在我这边。 And maybe it gives some additional insight into what's actually going on behind the scenes.也许它可以对幕后实际发生的事情提供一些额外的见解。

Also, I'm not really sure whether you want to expose the payment confirmation page to a GET request.另外,我不确定您是否要将付款确认页面公开给 GET 请求。

But this was an interesting rabbit hole to go down for a bit.但这对于 go 来说是一个有趣的兔子洞。

I was able to resolve this issue by changing 'same_site' => 'lax', to 'same_site' => null, in config/session.php.我可以通过在 config/session.php 'same_site' => null, 'same_site' => 'lax',更改为 'same_site' => null 来解决此问题。 This appears to be a new setting in Laravel 7+.这似乎是 Laravel 7+ 中的新设置。

I'm not sure if there are any security implications caused by this change without further reading but this, for now, fixes the problem.如果没有进一步阅读,我不确定此更改是否会导致任何安全隐患,但目前,这可以解决问题。 It would be a nice feature to somehow whitelist certain domains.以某种方式将某些域列入白名单将是一个不错的功能。

You should keep your cookie session to 'lax', you don't want your cookies available on other sites, etc.你应该让你的 cookie session 保持“宽松”,你不希望你的 cookies 在其他网站上可用等。

The fix as I have found is to pass true for remember when you do a login.我发现的修复方法是在您登录时通过 true 以记住。

Example:例子:

Auth::login(
   user: $user,
   remember: true
);

$request->session()->regenerate();

Your user will now be logged in indefinitely until they log out, ie going away from your site and returning via redirect headers and all that.您的用户现在将无限期登录,直到他们注销,即离开您的站点并通过重定向标头返回等等。 I discovered this when using Passport to receive a callback for Oauth and I needed to log the user in at that point but redirect them to a subdomain for their tenant.我在使用 Passport 接收 Oauth 的回调时发现了这一点,此时我需要让用户登录,但将他们重定向到其租户的子域。

Normally you'll just want the session to be available across your root domain and subdomains like .mydomain.com in your config/env.通常,您只希望 session 在您的根域和子域中可用,例如您的 config/env 中的.mydomain.com

Setting the 'same_site' => null might not work as expected again because Standards related to the Cookie SameSite attribute recently changed https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite设置 'same_site' => null 可能无法再次按预期工作,因为与 Cookie SameSite 属性相关的标准最近更改了https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/同站点

The new default is now Lax, so if you set your same_site to null, the browser will assume the default of Lax which is not the policy you need.新的默认值现在是 Lax,因此如果您将 same_site 设置为 null,浏览器将假定默认值为 Lax,这不是您需要的策略。

You need to explicitly set 'same_site' => "none" and also set您需要明确设置 'same_site' => "none" 并设置

'same_site' => "none"
'secure' => true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM