【问题标题】:Migrating anonymous session data and restricting it to authenticated user迁移匿名会话数据并将其限制为经过身份验证的用户
【发布时间】:2016-06-27 14:43:25
【问题描述】:

现在,我的 Web 应用程序的匿名(未经身份验证)用户的会话数据在登录或注册后不会移动/分配给用户。

例如:匿名用户与应用程序交互,创建一些会话数据(例如购物车中的产品),然后登录/注册然后注销,会话数据仍然可以访问,并且不会移动/无法访问给现在未经身份验证的用户。

我正在使用文件会话驱动程序(无数据库),也许有人可以提供一些需要更改的示例(我假设在会话配置中),以便将匿名用户创建的任何会话数据分配给并且仅此用户通过登录或注册进行身份验证后才能访问,并且仅在用户通过身份验证时访问。

这样做的要求是因为应用程序的用户创建了唯一的对象(与他们的 user_id 相关联),这些对象仅在订单处理运行时付款后才会保留。我将它们存储在会话中,直到用户登录/注册并完成最后的订单步骤,然后它们才会持久化。所以我绝对不能在用户注销后将用户特定的对象保留在非身份验证的会话中。我可以在注销时刷新会话,但理想情况下我想在用户重新登录时保留它们。

【问题讨论】:

    标签: php laravel laravel-5


    【解决方案1】:

    身份验证系统仅使用会话作为存储来跨请求保持身份验证状态。但是,Laravel 的身份验证系统不负责处理所有您的会话数据,它只关心存储身份验证相关信息,例如用户详细信息。如果您想为经过身份验证的用户处理额外的会话数据,则需要手动完成。

    逻辑很简单:

    • 如果用户执行某些操作,例如向购物车添加东西,则数据会保留在那里,因为会话通过 cookie 绑定到发出请求的浏览器。

    • 如果用户从同一浏览器登录,Laravel 的身份验证系统会检查凭据,如果它们正确,它会将有关该用户的必要信息存储在同一会话中。先前存储的有关购物车的数据仍然存在且未触及,因此您可以在登录用户的上下文中使用它。如果此时您想要保留会话购物车,以便用户将来访问他/她的帐户时可以使用它,那么您需要将详细信息存储在数据库中。下面是几个步骤,展示了实现这一目标的方法:

    1. 创建一个事件监听器,我们将其命名为SyncShoppingCart,它将监听Illuminate\Auth\Events\Login 事件(命令\\ 中的双反斜杠用于转义单个斜杠):

    php artisan make:listener SyncShoppingCart --event=Illuminate\\Auth\\Events\\Login
    

    2. 上一条命令在app/Listeners 中创建了一个名为SyncShoppingCart.php 的文件。现在您只需要将购物车数据存储在该类的handle 方法中的用户中。下面的示例假设您有一个 cart_item 表来存储有关添加到购物车的项目的信息,并且您有一个为它定义的 CartItem 模型。此示例已简化,您需要对其进行修改以满足您的需要,但这是理解此方法的一个很好的起点:

    public function handle(Login $event)
    {
        // Iterate over the session cart items and 
        foreach (session()->get('cart') as $item) {
            $cartItem = new App\CartItem();
    
            // Set the user ID for the cart item so you know
            // which user added this item to the cart
            $cartItem->user_id = Auth::id();
    
            // Set the product ID and any other properties
            // you want stored for the cart item
            $cartItem = $item->product_id;
            // ...
    
            // Save the cart item to the database
            $cartItem->save();
        }
    
        session()->forget('cart');
    }
    

    3.然后在$listen数组中的app/Providers/EventServiceProvider.php中注册偶数监听器:

    protected $listen = [
        ...
        'Illuminate\Auth\Events\Login' => [
            'App\Listeners\SyncShoppingCart',
        ],
    ];
    

    现在,每当用户登录时,都会调用App\Listeners\SyncShoppingCart::handle 方法并将会话购物车中的项目添加到数据库中。当然,在用户登录后,您还应该存储添加到数据库中的新项目,单独的会话应该用于存储客人的购物车信息。注销时,您可以从会话中删除购物车并完成它,因为您知道购物车内容存储在数据库中,并且可以在用户下次登录时检索。


    你可以在 Laravel 文档中阅读更多关于 Authentication EventsSessionsEvents 的信息。

    【讨论】:

    • 我不只是希望在经过身份验证的用户注销后删除购物车会话数据。我希望它保留,但现在该用户只能在他们再次进行身份验证/登录时才能访问。因此,如果匿名用户将产品添加到购物车,然后登录/验证然后注销,会话数据将保留,但现在只有在验证后该用户才能访问。同样,如果经过身份验证的用户将产品添加到购物车然后退出,购物车的所有会话数据都会保留,但只有在用户重新登录后才能访问。
    • 我认为您可能误解了会话的工作方式。会话是短暂的,只擅长在用户浏览网站时存储信息,正如我在回答中提到的,会话绑定到浏览器。因此,即使您将会话设置为在 10 年后过期(这不是一件好事),并且您在该会话中存储了信息,它也只能在一个浏览器中使用,该浏览器在 cookie 中保存会话 ID,如果用户使用登录来自另一个浏览器的同一帐户,该会话将不可用。如果你想持久化你需要存储在数据库中的购物车信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 2016-10-09
    • 2019-06-28
    • 2017-03-18
    • 1970-01-01
    相关资源
    最近更新 更多