Laravel 5 中的登录事件处理


login event handling in laravel 5

我甚至试图在我的 L5 应用程序中挂接登录以设置上次登录时间和 IP 地址。 我可以使其与以下内容一起使用:

Event::listen('auth.login', function($event)
{
    Auth::user()->last_login = new DateTime;
    Auth::user()->last_login_ip = Request::getClientIp();
    Auth::user()->save();
});

但是,我想知道在 L5 中执行此操作的最佳方法是使用事件处理程序对象。 我尝试创建一个事件处理程序并将 auth.login 添加为事件服务提供商中的数组键,但这不起作用。 我不确定 auth.login 事件是否可能。 如果不是, 放置上述代码最合适的位置在哪里。为了进行测试,我把它放在我的 routes.php 文件中,但我知道这不是它应该在的地方。

在 laravel 5.2 中; auth.login 不起作用...必须使用以下内容:

protected $listen = [
    'Illuminate'Auth'Events'Attempting' => [
        'App'Listeners'LogAuthenticationAttempt',
    ],
    'Illuminate'Auth'Events'Login' => [
        'App'Listeners'LogSuccessfulLogin',
    ],
    'Illuminate'Auth'Events'Logout' => [
        'App'Listeners'LogSuccessfulLogout',
    ],
    'Illuminate'Auth'Events'Lockout' => [
        'App'Listeners'LogLockout',
    ],
];

如此处的文档中所述

编辑:这仅适用于 5.0.* 和 5.1.*。

有关 5.2.* 解决方案,请参阅下面的 JuLiAnc 响应。

在处理了两个提议的答案以及更多的研究之后,我终于想出了如何以我最初尝试的方式做到这一点。

我运行了以下工匠命令

$ php artisan handler:event AuthLoginEventHandler

然后我更改了生成的类,删除了 Event 类的导入并导入了用户模型。我还User $user$remember传递给了句柄方法,因为当 auth.login 事件被触发时,这就是传递的内容。

<?php namespace App'Handlers'Events;
use Illuminate'Queue'InteractsWithQueue;
use Illuminate'Contracts'Queue'ShouldBeQueued;
use App'User;
class AuthLoginEventHandler {
    /**
     * Create the event handler.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param  User $user
     * @param  $remember
     * @return void
     */
    public function handle(User $user, $remember)
    {
        dd("login fired and handled by class with User instance and remember variable");
    }
}

现在我打开了 EventServiceProvide.php并修改了 $listen 数组,如下所示:

protected $listen = [
    'auth.login' => [
        'App'Handlers'Events'AuthLoginEventHandler',
    ],
];

我意识到如果一开始这不起作用,您可能需要

$ php artisan clear-compiled

现在,我们可以使用事件处理程序类响应通过 auth.login 事件登录的用户!

小心询问做X的最佳方法是什么,因为特别是Laravel提供了许多完成相同任务的方法 - 在某些情况下,有些方法比其他方法更好。

看看Laravel文档,我个人会选择"基本用法",因为它似乎与您所说的用例相匹配。

如果我们运行以下 Artisan 命令,我们可以为 UserLoggedIn 事件生成一个模板。

$ php artisan make:event UserLoggedIn

(请注意过去时,因为事件发生了,然后订阅者会收到事件发生的通知)

(注意2:命名空间中的app字符串是Laravel开箱即用的,如果您执行了php artisan app:name命令,则可能会有所不同)

为我们生成以下类:

<?php namespace app'Events;
use app'Events'Event;
use Illuminate'Queue'SerializesModels;
class UserLoggedIn extends Event {
    use SerializesModels;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
}

如果我们向构造函数添加 userId 参数,则事件不需要知道身份验证外观/保护协定。这意味着我们的UserLoggedIn事件代码不会与 Eloquent 或您决定在应用中使用的身份验证框架紧密耦合。无论如何,让我们添加该userId参数。

<?php namespace app'Events;
use app'Events'Event;
use app'User;
use Illuminate'Queue'SerializesModels;
class UserLoggedIn extends Event {
    use SerializesModels;
    public $userId;
    /**
     * Create a new event instance.
     *
     * @param int userId the primary key of the user who was just authenticated.
     *
     * @return void
     */
    public function __construct($userId)
    {
        $this->userId = $userId;
    }
}

现在你可能想知道,这很好,但是我们如何对这个事件采取行动?好问题!我们需要创建一个事件处理程序来处理触发此事件的时间。现在让我们使用 Artisan 来做到这一点:

$ php artisan handler:event UpdateUserMetaData --event=UserLoggedIn

我们将新的事件处理程序命名为 UpdateUserMetaData,并告诉 Artisan 我们要处理的事件是UserLoggedIn事件。

现在我们在app/Handlers/Events/UpdateUserMetaData.php内部有一些看起来像这样的代码:

<?php namespace app'Handlers'Events;
use app'Events'UserLoggedIn;
use Illuminate'Queue'InteractsWithQueue;
use Illuminate'Contracts'Queue'ShouldBeQueued;
class UpdateUserMetaData {
    /**
     * Create the event handler.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param  UserLoggedIn  $event
     * @return void
     */
    public function handle(UserLoggedIn $event)
    {
        //
    }
}

我们可以更新句柄方法,以便能够像您上面指定的那样轻松处理此事件:

<?php namespace app'Handlers'Events;
use app'Events'UserLoggedIn;
use Illuminate'Http'Request;
class UpdateUserMetaData {
    protected $request;
    /**
     * Create the event handler.
     *
     * @param Request $request
     */
    public function __construct(Request $request)
    {
        $this->request = $request;
    }
    /**
     * Handle the event.
     *
     * @param  UserLoggedIn  $event
     */
    public function handle(UserLoggedIn $event)
    {
        $user = User::find($event->userId); // find the user associated with this event
        $user->last_login = new DateTime;
        $user->last_login_ip = $this->request->getClientIp();
        $user->save();
    }
}

作为旁注,如果您不熟悉 Carbon,您可能需要考虑使用它,以便您可以利用其出色的 API,就像在大多数模型上使用 Eloquent 的 created_atupdated_at时间戳字段一样。这里有一个链接,告诉你Eloquent哪些字段应该与Carbon一起使用:http://laravel.com/docs/master/eloquent#date-mutators。

这段代码在您的Laravel应用程序中工作之前,我们必须执行最后两个步骤。

  1. 我们需要将事件映射到 app/Providers 目录下 EventServiceProvider 类中的事件处理程序。

  2. 我们需要在登录后触发事件。

要完成第一步,我们只需要将我们的事件类添加到 $listeners 属性中,如下所示app/Providers/EventServiceProvder.php

    UserLoggedIn::class => [
        UpdateUserMetaData::class
    ]

如果您导入 EventServiceProvider 类中的类,并且您使用的是 PHP 5.5,则上述方法将起作用。如果您使用的是较低的 PHP 版本,则需要以字符串形式提供每个类的完整路径,如下所示:'app/Events/UserLoggedIn''app/Handlers/Events/UpdateUserMetaData'

$listeners数组将事件映射到其各自的处理程序。

好了,现在是最后一步!在代码库中,找到对用户进行身份验证的位置并添加以下内容:

event(new 'app'Events'UserLoggedIn(Auth::user()->id));

我们完成了!我在写这个答案时测试了这段代码,如果您有任何问题,请随时提出后续问题。

对于 5.2 类似

的东西

在侦听器中:

use Carbon'Carbon;
use Illuminate'Auth'Events'Login;
class UpdateLastLoginWithIp
{
    public function handle(Login $event)
    {
        $event->user->last_login_at = Carbon::now();
        $event->user->last_login_ip = Request::getClientIp()
        $event->user->save();
    }
}

在 EventServiceProvider 中.php :

protected $listen = [
        'Illuminate'Auth'Events'Login' => [
            'City'Listeners'UpdateLastLoginWithIp',
        ],
    ];

通常,您可以通过逐步执行此操作来实现 用户登录日志

首先,您应该拥有身份验证脚手架

  1. 将此用作事件,
      登录
    • 事件的"亮起''身份验证''事件''登录"
    • 注销
    • 事件的"照亮''身份验证''事件''注销"

位于 的登录和注销事件:

vendor''laravel''framework''src''Illuminate''Auth''Events

事件服务提供商.php

protected $listen = [
    'Illuminate'Auth'Events'Login' => [
        'App'Listeners'LoginLogs',
    ],
    'Illuminate'Auth'Events'Logout' => [
        'App'Listeners'LogoutLogs',
    ],
];

public function boot()
{
    parent::boot();
}
  1. 然后在完成事件服务提供程序后,执行下一步
    • 键入此工匠命令 PHP 工匠事件:生成
    • 在应用程序文件夹中查找文件夹侦听器,检查是否包含 php 文件登录日志和注销日志
  2. 创建迁移模型

命令: PHP 工匠制作:迁移create_UserLoginHistory

迁移文件

public function up()
{
    Schema::create('tbl_user_login_history', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->integer('user_id');
        $table->datetime('login_at')->nullable();
        $table->datetime('logout_at')->nullable();
        $table->string('login_ip')->nullable();
        $table->string('role');
        $table->string('session_id');
        $table->timestamps();
    });
}

public function down()
{
    Schema::dropIfExists('tbl_user_login_history');
}

然后你的模型用户登录历史

public $timestamps = false;
protected $table = 'tbl_user_login_history';
protected $fillable = ['user_id','login_at','logout_at','login_ip','role','session_id'];
public function setLogOutLog(){
    $this->where('session_id',request()->session()->getId())->update([
        'logout_at' =>Carbon::now(),
        ]);
}
public function setLogInLog(){
    $this->insert(
        ['user_id' => Auth::user()->id,'login_at' =>Carbon::now(),
        'login_ip'=>request()->getClientIp(),'role' =>Auth::user()->role,
        'session_id'=>request()->session()->getId()
        ]);  
}

4.在迁移和模型创建过程之后,假设您已经在"用户"表中具有角色

  1. 侦听器部分

侦听器登录日志

use App'UserLoginHistory;

private $UserLoginHistory; 
public function __construct(UserLoginHistory $UserLoginHistory)
{
  // the initialization of  private $UserLoginHistory; 
    $this->UserLoginHistory = $UserLoginHistory;
}

public function handle(Login $event)
{   
     // from model UserLoginHistory
     $this->UserLoginHistory->setLogInLog();
}

侦听器注销日志

private $UserLogoutHistory; 
public function __construct(UserLoginHistory $UserLoginHistory)
{
    // the initialization of  private $UserLogoutHistory; 
    $this->UserLogoutHistory = $UserLoginHistory;
}

public function handle(Logout $event)
{
    // from model UserLoginHistory
     $this->UserLogoutHistory->setLogOutLog();
}

完成所有步骤后,尝试使用身份验证登录

这是我

的方法:
我已经在用户登录时使用以下命令制作事件处理程序:

  • 拉维尔 5.8

1) 运行以下 artian 命令
php artisan make:listener Auth/UserLoggedIn --event='Illuminate'Auth'Events'Login' *

它将在文件夹app'Listeners'Auth'中创建一个侦听器:UserLoggedIn

2)然后您需要将此侦听器添加到EventServiceProvider :**

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

最后,当用户登录位于UserLoggedIn监听器handle功能时,您可以进行记录:

public function handle(Login $event)
    {
        //you have access to user object by using : $event->user
    }
  • 您可以使用所有其他身份验证事件,以下是可能的事件:
'Illuminate'Auth'Events'Registered', 
'Illuminate'Auth'Events'Attempting', 
'Illuminate'Auth'Events'Authenticated', 
'Illuminate'Auth'Events'Login', 
'Illuminate'Auth'Events'Failed',
'Illuminate'Auth'Events'Logout',
'Illuminate'Auth'Events'Lockout',

**您可以在EventServiceProvider中使用所有这些事件:https://laravel.com/docs/5.8/authentication#events

打开 EventServiceProvider.php在引导方法中,您可以通过回调侦听'auth.login'事件。

public function boot(DispatcherContract $events)
{
    parent::boot($events);
    $events->listen('auth.login', function() 
    {
        dd('logged in event');
    });
}

您可能希望创建侦听器,以便将回调函数移动到其他地方。按照这个 http://laravel.com/docs/4.2/events#using-classes-as-listeners<</p>

div class="answers"这样做>

就是这样做

    <?php
namespace App'Providers;
use App'User;
use Auth;
use DB;

use Illuminate'Contracts'Events'Dispatcher as DispatcherContract;
use Illuminate'Foundation'Support'Providers'EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
    ];
    /**
     * Register any other events for your application.
     *
     * @param  'Illuminate'Contracts'Events'Dispatcher  $events
     * @return void
     */
    public function boot(DispatcherContract $events)
    {
        parent::boot($events);
        $events->listen('auth.login', function() 
        {
            DB::table('users')
                -> where('id', Auth::id())
                -> update(array(
                        'last_login'    => date('Y-m-d H:i:s')
                    ));
        });
        //
    }
}