利用Laravel事件系統(tǒng)如何實(shí)現(xiàn)登錄日志的記錄詳解
本文介紹的是利用Laravel事件系統(tǒng)實(shí)現(xiàn)登錄日志記錄的相關(guān)內(nèi)容,分享出來給大家參考,下面來看看詳細(xì)的介紹:
明確需求
記錄一個(gè)登錄日志,通常需要下列信息:
- 客戶端Agent信息
- 客戶端IP地址
- 訪問IP地點(diǎn)
- 登錄時(shí)間
- 登錄用戶信息
確立工具
明確完需求后,根據(jù)每個(gè)需求查找自己所需的工具吧。
- 需求1 jenssegers/agent就可以滿足我們要求
- 需求2 Laravel下直接
Request::getClientIp() - 需求3 zhuzhichao/ip-location-zh這個(gè)包可以滿足要求
- 需求4 time()
- 需求5 登錄用戶模型
開工
采用Laravel的事件訂閱系統(tǒng)來實(shí)現(xiàn),需要實(shí)現(xiàn)一個(gè)登錄事件和一個(gè)登錄事件監(jiān)聽器。
生成事件和監(jiān)聽器
Laravel命令行支持自動(dòng)生成事件和監(jiān)聽器,在App\Providers\EventServiceProvider中添加需要實(shí)現(xiàn)的事件:
protected $listen = [ ..., //添加登錄事件及對(duì)應(yīng)監(jiān)聽器,一個(gè)事件可綁定多個(gè)監(jiān)聽器 'App\Events\LoginEvent' => [ 'App\Listeners\LoginListener', ], ];
運(yùn)行命令:php artisan event:generate就會(huì)自動(dòng)生成事件和監(jiān)聽器,已存在的事件和監(jiān)聽器不會(huì)發(fā)生改變。
登錄事件(Event)
回顧下需求,我們的登錄事件需要的5點(diǎn)信息,在事件中需要記錄這些信息,所以事件設(shè)計(jì)如下:
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use App\Models\User;
use Jenssegers\Agent\Agent;
class LoginEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* @var User 用戶模型
*/
protected $user;
/**
* @var Agent Agent對(duì)象
*/
protected $agent;
/**
* @var string IP地址
*/
protected $ip;
/**
* @var int 登錄時(shí)間戳
*/
protected $timestamp;
/**
* 實(shí)例化事件時(shí)傳遞這些信息
*/
public function __construct($user, $agent, $ip, $timestamp)
{
$this->user = $user;
$this->agent = $agent;
$this->ip = $ip;
$this->timestamp = $timestamp;
}
public function getUser()
{
return $this->user;
}
public function getAgent()
{
return $this->agent;
}
public function getIp()
{
return $this->ip;
}
public function getTimestamp()
{
return $this->timestamp;
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-default');
}
}
在事件中記錄所需要的信息,并實(shí)現(xiàn)這些信息的get方法。
登錄監(jiān)聽器(Listener)
在監(jiān)聽器中,獲取到事件傳遞過來的信息,把這些信息記錄到數(shù)據(jù)庫中,實(shí)現(xiàn)如下:
namespace App\Listeners;
use App\Events\LoginEvent;
class LoginListener
{
// handle方法中處理事件
public function handle(LoginEvent $event)
{
//獲取事件中保存的信息
$user = $event->getUser();
$agent = $event->getAgent();
$ip = $event->getIp();
$timestamp = $event->getTimestamp();
//登錄信息
$login_info = [
'ip' => $ip,
'login_time' => $timestamp,
'user_id' => $user->id
];
// zhuzhichao/ip-location-zh 包含的方法獲取ip地理位置
$addresses = \Ip::find($ip);
$login_info['address'] = implode(' ', $addresses);
// jenssegers/agent 的方法來提取agent信息
$login_info['device'] = $agent->device(); //設(shè)備名稱
$browser = $agent->browser();
$login_info['browser'] = $browser . ' ' . $agent->version($browser); //瀏覽器
$platform = $agent->platform();
$login_info['platform'] = $platform . ' ' . $agent->version($platform); //操作系統(tǒng)
$login_info['language'] = implode(',', $agent->languages()); //語言
//設(shè)備類型
if ($agent->isTablet()) {
// 平板
$login_info['device_type'] = 'tablet';
} else if ($agent->isMobile()) {
// 便捷設(shè)備
$login_info['device_type'] = 'mobile';
} else if ($agent->isRobot()) {
// 爬蟲機(jī)器人
$login_info['device_type'] = 'robot';
$login_info['device'] = $agent->robot(); //機(jī)器人名稱
} else {
// 桌面設(shè)備
$login_info['device_type'] = 'desktop';
}
//插入到數(shù)據(jù)庫
DB::table('login_log')->insert($login_info);
}
}
這樣,監(jiān)聽器就完成了,每次一觸發(fā)登錄事件,就會(huì)在數(shù)據(jù)庫中添加一條登錄信息。
觸發(fā)事件
通過全局的event()方法來觸發(fā)事件,event()方法的參數(shù)為事件實(shí)例:
namespace App\Controllers;
...
use App\Events\LoginEvent;
use Jenssegers\Agent\Agent;
class AuthControoler extends Controller
{
...
public function login(Request $request)
{
//登錄實(shí)現(xiàn)
...
//登錄成功,觸發(fā)事件
event(new LoginEvent($this->guard()->user(), new Agent(), \Request::getClientIp(), time()));
...
}
}
隊(duì)列化監(jiān)聽器
有時(shí)監(jiān)聽器會(huì)進(jìn)行一些耗時(shí)操作,這時(shí)應(yīng)該結(jié)合Laravel的隊(duì)列系統(tǒng)將監(jiān)聽器進(jìn)行隊(duì)列化,前提是已經(jīng)配置了隊(duì)列并開啟了隊(duì)列處理器。
隊(duì)列化非常簡單,只需監(jiān)聽器實(shí)現(xiàn)ShouldQueue接口即可,即:
namespace App\Listeners;
...
use Illuminate\Contracts\Queue\ShouldQueue;
class LoginListener implements ShouldQueue
{
/**
* 失敗重試次數(shù)
* @var int
*/
public $tries = 1;
...
}
總結(jié)
Laravel的事件系統(tǒng)實(shí)現(xiàn)起來還是非常優(yōu)雅的,同一個(gè)事件可以很方便的添加各類監(jiān)聽器,且各個(gè)監(jiān)聽器之間互不干擾,解耦性非常強(qiáng)。加上隊(duì)列系統(tǒng),可以很方便的處理一些后續(xù)任務(wù)。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- Laravel實(shí)現(xiàn)用戶注冊(cè)和登錄
- Laravel搭建后臺(tái)登錄系統(tǒng)步驟詳解
- Laravel 自帶的Auth驗(yàn)證登錄方法
- Laravel 5.4重新登錄實(shí)現(xiàn)跳轉(zhuǎn)到登錄前頁面的原理和方法
- Laravel重寫用戶登錄簡單示例
- SSO單點(diǎn)登錄的PHP實(shí)現(xiàn)方法(Laravel框架)
- Laravel5.2使用Captcha生成驗(yàn)證碼實(shí)現(xiàn)登錄(session巨坑)
- php的laravel框架快速集成微信登錄的方法
- laravel5.2實(shí)現(xiàn)區(qū)分前后臺(tái)用戶登錄的方法
- Laravel登錄失敗次數(shù)限制的實(shí)現(xiàn)方法
相關(guān)文章
php自定義urlencode,urldecode函數(shù)實(shí)例
這篇文章主要介紹了php自定義urlencode,urldecode函數(shù),實(shí)例分析了php字符串轉(zhuǎn)碼的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
PHP JSAPI調(diào)支付API實(shí)現(xiàn)微信支付功能詳解
本人最近做了微信支付開發(fā),是第一次接觸,其中走了很多彎路,遇到的問題也很多。為了讓和我一樣的新人不再遇到類似的問題,我把我的開發(fā)步驟和問題寫出來以供參考,這篇文章主要介紹了PHP JSAPI調(diào)支付API實(shí)現(xiàn)微信支付功能2022-11-11
php基于表單密碼驗(yàn)證與HTTP驗(yàn)證用法實(shí)例
這篇文章主要介紹了php基于表單密碼驗(yàn)證與HTTP驗(yàn)證用法,以實(shí)例形式較為詳細(xì)的分析了表單密碼驗(yàn)證與HTTP驗(yàn)證的原理與相關(guān)注意事項(xiàng),具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01

