利用Laravel事件系統(tǒng)如何實(shí)現(xiàn)登錄日志的記錄詳解
本文介紹的是利用Laravel事件系統(tǒng)實(shí)現(xiàn)登錄日志記錄的相關(guān)內(nèi)容,分享出來(lái)給大家參考,下面來(lái)看看詳細(xì)的介紹:
明確需求
記錄一個(gè)登錄日志,通常需要下列信息:
- 客戶端Agent信息
- 客戶端IP地址
- 訪問(wèn)IP地點(diǎn)
- 登錄時(shí)間
- 登錄用戶信息
確立工具
明確完需求后,根據(jù)每個(gè)需求查找自己所需的工具吧。
- 需求1 jenssegers/agent就可以滿足我們要求
- 需求2 Laravel下直接
Request::getClientIp() - 需求3 zhuzhichao/ip-location-zh這個(gè)包可以滿足要求
- 需求4 time()
- 需求5 登錄用戶模型
開(kāi)工
采用Laravel的事件訂閱系統(tǒng)來(lái)實(shí)現(xiàn),需要實(shí)現(xiàn)一個(gè)登錄事件和一個(gè)登錄事件監(jiān)聽(tīng)器。
生成事件和監(jiān)聽(tīng)器
Laravel命令行支持自動(dòng)生成事件和監(jiān)聽(tīng)器,在App\Providers\EventServiceProvider中添加需要實(shí)現(xiàn)的事件:
protected $listen = [ ..., //添加登錄事件及對(duì)應(yīng)監(jiān)聽(tīng)器,一個(gè)事件可綁定多個(gè)監(jiān)聽(tīng)器 'App\Events\LoginEvent' => [ 'App\Listeners\LoginListener', ], ];
運(yùn)行命令:php artisan event:generate就會(huì)自動(dòng)生成事件和監(jiān)聽(tīng)器,已存在的事件和監(jiān)聽(tīng)器不會(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)聽(tīng)器(Listener)
在監(jiān)聽(tīng)器中,獲取到事件傳遞過(guò)來(lái)的信息,把這些信息記錄到數(shù)據(jù)庫(kù)中,實(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 的方法來(lái)提取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()); //語(yǔ)言
//設(shè)備類型
if ($agent->isTablet()) {
// 平板
$login_info['device_type'] = 'tablet';
} else if ($agent->isMobile()) {
// 便捷設(shè)備
$login_info['device_type'] = 'mobile';
} else if ($agent->isRobot()) {
// 爬蟲(chóng)機(jī)器人
$login_info['device_type'] = 'robot';
$login_info['device'] = $agent->robot(); //機(jī)器人名稱
} else {
// 桌面設(shè)備
$login_info['device_type'] = 'desktop';
}
//插入到數(shù)據(jù)庫(kù)
DB::table('login_log')->insert($login_info);
}
}
這樣,監(jiān)聽(tīng)器就完成了,每次一觸發(fā)登錄事件,就會(huì)在數(shù)據(jù)庫(kù)中添加一條登錄信息。
觸發(fā)事件
通過(guò)全局的event()方法來(lái)觸發(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)聽(tīng)器
有時(shí)監(jiān)聽(tīng)器會(huì)進(jìn)行一些耗時(shí)操作,這時(shí)應(yīng)該結(jié)合Laravel的隊(duì)列系統(tǒng)將監(jiān)聽(tīng)器進(jìn)行隊(duì)列化,前提是已經(jīng)配置了隊(duì)列并開(kāi)啟了隊(duì)列處理器。
隊(duì)列化非常簡(jiǎn)單,只需監(jiān)聽(tīng)器實(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)起來(lái)還是非常優(yōu)雅的,同一個(gè)事件可以很方便的添加各類監(jiān)聽(tīng)器,且各個(gè)監(jiān)聽(tīng)器之間互不干擾,解耦性非常強(qiáng)。加上隊(duì)列系統(tǒng),可以很方便的處理一些后續(xù)任務(wù)。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- Laravel實(shí)現(xiàn)用戶注冊(cè)和登錄
- Laravel搭建后臺(tái)登錄系統(tǒng)步驟詳解
- Laravel 自帶的Auth驗(yàn)證登錄方法
- Laravel 5.4重新登錄實(shí)現(xiàn)跳轉(zhuǎn)到登錄前頁(yè)面的原理和方法
- Laravel重寫(xiě)用戶登錄簡(jiǎn)單示例
- 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)文章
一個(gè)簡(jiǎn)潔的PHP可逆加密函數(shù)(分享)
本篇文章是對(duì)一個(gè)簡(jiǎn)潔的PHP可逆加密函數(shù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
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)微信支付功能詳解
本人最近做了微信支付開(kāi)發(fā),是第一次接觸,其中走了很多彎路,遇到的問(wèn)題也很多。為了讓和我一樣的新人不再遇到類似的問(wèn)題,我把我的開(kāi)發(fā)步驟和問(wèn)題寫(xiě)出來(lái)以供參考,這篇文章主要介紹了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
通過(guò)PHP實(shí)現(xiàn)獲取訪問(wèn)用戶IP
這篇文章主要介紹了通過(guò)PHP實(shí)現(xiàn)獲取訪問(wèn)用戶IP,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05

