摘要:需求一個(gè)用戶(hù)不能重復(fù)登錄后登錄者可以踢掉前者設(shè)計(jì)思路核心概念用戶(hù)是用戶(hù)表主鍵算法用戶(hù)用戶(hù)登錄的時(shí)間戳中存儲(chǔ)一份中存儲(chǔ)一份登錄的時(shí)間戳根據(jù)中登錄時(shí)間戳運(yùn)算后得到用戶(hù)訪(fǎng)問(wèn)時(shí)如果那么認(rèn)為重復(fù)登陸銷(xiāo)毀登錄信息跳轉(zhuǎn)到登錄頁(yè)面流程描述用戶(hù)登錄的時(shí)候使用
需求
一個(gè)用戶(hù)不能重復(fù)登錄. 后登錄者可以踢掉前者.
設(shè)計(jì)思路: 核心概念用戶(hù)ID: 是用戶(hù)表主鍵 singleToken 算法: singleToken = md5(用戶(hù)IP + 用戶(hù)ID + 登錄的Unix時(shí)間戳) SESSION 中存儲(chǔ)一份 SESSION_SINGLE_TOKEN REDIS 中存儲(chǔ)一份 登錄的Unix時(shí)間戳 REDIS_SINGLE_TOKEN = 根據(jù)REDIS中登錄時(shí)間戳運(yùn)算后得到token 用戶(hù)訪(fǎng)問(wèn)時(shí): 如果 SESSION_SINGLE_TOKEN != REDIS_SINGLE_TOKEN 那么 認(rèn)為重復(fù)登陸,銷(xiāo)毀登錄信息,跳轉(zhuǎn)到登錄頁(yè)面流程描述
用戶(hù)登錄的時(shí)候使用用戶(hù)IP+用戶(hù)表主鍵+Unix時(shí)間戳組成的字符串, 經(jīng)過(guò)md5運(yùn)算生成一個(gè)singleToken 字符串. 并且存入session.
在redis中保存登錄時(shí)的 Unix時(shí)間戳,redis中保存的內(nèi)容應(yīng)該有過(guò)期時(shí)間, 通常和session過(guò)期時(shí)間一致.
key : SINGLE_TOKEN + 用戶(hù)id value : 登錄時(shí) unix時(shí)間戳
每一次用戶(hù)請(qǐng)求需要登錄驗(yàn)證的url, 那么用session中的singleToken 和 經(jīng)過(guò)md5運(yùn)算的 登錄IP+用戶(hù)ID+redis中的Unix時(shí)間戳 字符串作比較.
如果一致那么方可訪(fǎng)問(wèn).
如果redis中的時(shí)間戳為空,那么只是返回login頁(yè)面.
如果redis中時(shí)間戳不為空且兩個(gè)計(jì)算后的token不一致那么說(shuō)明兩個(gè)賬戶(hù)同時(shí)登錄了, 那么返回login畫(huà)面并提示您的賬戶(hù)在其他位置登錄,不能重復(fù)登錄之類(lèi)的消息.
開(kāi)始實(shí)現(xiàn): 建立測(cè)試項(xiàng)目(準(zhǔn)備工作)為了展示我們的功能, 創(chuàng)建一個(gè)名為singleLogin的新項(xiàng)目.
composer create-project --prefer-dist laravel/laravel singleLogin
創(chuàng)建系統(tǒng)自帶的認(rèn)證
php artisan make:auth
php artisan route:list
+--------+----------+------------------------+----------+------------------------------------------------------------------------+--------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+------------------------+----------+------------------------------------------------------------------------+--------------+ | | GET|HEAD | / | | Closure | web | | | GET|HEAD | api/user | | Closure | api,auth:api | | | GET|HEAD | home | | AppHttpControllersHomeController@index | web,auth | | | GET|HEAD | login | login | AppHttpControllersAuthLoginController@showLoginForm | web,guest | | | POST | login | | AppHttpControllersAuthLoginController@login | web,guest | | | POST | logout | logout | AppHttpControllersAuthLoginController@logout | web | | | POST | password/email | | AppHttpControllersAuthForgotPasswordController@sendResetLinkEmail | web,guest | | | GET|HEAD | password/reset | | AppHttpControllersAuthForgotPasswordController@showLinkRequestForm | web,guest | | | POST | password/reset | | AppHttpControllersAuthResetPasswordController@reset | web,guest | | | GET|HEAD | password/reset/{token} | | AppHttpControllersAuthResetPasswordController@showResetForm | web,guest | | | GET|HEAD | register | register | AppHttpControllersAuthRegisterController@showRegistrationForm | web,guest | | | POST | register | | AppHttpControllersAuthRegisterController@register | web,guest | +--------+----------+------------------------+----------+------------------------------------------------------------------------+--------------+安裝redis擴(kuò)展
composer require predis/predis修改配置文件
配置一下數(shù)據(jù)庫(kù)(根目錄下的.env文件)
DB_CONNECTION=mysql DB_HOST=你的數(shù)據(jù)庫(kù)IP DB_PORT=3306 DB_DATABASE=你的數(shù)據(jù)庫(kù)名 DB_USERNAME=你的用戶(hù)名 DB_PASSWORD=你的密碼 REDIS_HOST=192.168.1.100 REDIS_PASSWORD=null REDIS_PORT=6379
配置好之后執(zhí)行migrate命令
php artisan migrate
輸出內(nèi)容
Migration table created successfully. Migrated: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_100000_create_password_resets_table
經(jīng)過(guò)以上的操作準(zhǔn)備工作就已經(jīng)做好了
創(chuàng)建單用戶(hù)中間件接下來(lái)為了驗(yàn)證每次的url訪(fǎng)問(wèn)請(qǐng)求, 我們需要1個(gè)middleware
php artisan make:middleware SingleLoginMiddleware
系統(tǒng)會(huì)生成一個(gè)文件 app/Http/Middleware/SingleLoginMidleware.php
把他修改成下面的樣子
guest()) { if ($request->ajax() || $request->wantsJson()) { return response("Unauthorized.", 401); } else { return redirect()->guest("/login"); } } if ($this->isRelogin($request)) { //清空登錄數(shù)據(jù), 重定向 $request->session()->flush(); $request->session()->regenerate(); return redirect()->guest("/login"); } return $next($request); } /** * 判斷用戶(hù)是否 重復(fù)登錄 * @param $request * @return bool */ protected function isRelogin($request) { $user = Auth::user(); if ($user) { $cookieSingleToken = session("SINGLE_TOKEN"); if ($cookieSingleToken) { // 從 Redis 獲取 time $lastLoginTimestamp = Redis::get("SINGLE_TOKEN_" . $user->id); // 重新獲取加密參數(shù)加密 $ip = $request->getClientIp(); $redisSingleToken = md5($ip . $user->id . $lastLoginTimestamp); if ($cookieSingleToken != $redisSingleToken) { //認(rèn)定為重復(fù)登錄了 return true; } return false; } } return false; } }注冊(cè)單用戶(hù)中間件
注冊(cè) SingleLoginMiddleware 到 kernel
打開(kāi) path/singleLogin/src/app/Http/Kernel.php
//在下面添加singleLogin一行 protected $routeMiddleware = [ "auth" => IlluminateAuthMiddlewareAuthenticate::class, ... IlluminateRoutingMiddlewareThrottleRequests::class, "auth.singleLogin" => AppHttpMiddlewareSingleLoginMiddleware::class, ];配置中間件保護(hù)URL
設(shè)置 SingleLoginMiddleware 來(lái)保護(hù) /home url,
修改 routes/web.php ,修改后如下
"auth.singleLogin"], function() { # 用戶(hù)登錄成功后的路由 Route::get("/home", "HomeController@index"); });
修改 app/Http/Controllers/HomeController.php 刪掉部分代碼, 修改后如下
重寫(xiě)登錄功能驗(yàn)證登錄操作我們還需要一個(gè)登錄功能.
建立 app/Foundation/SingleLoginAuthenticatesUsers.php 文件內(nèi)容如下
這個(gè)文件的主要目的是改寫(xiě)系統(tǒng)生成的 src/vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php
traits 的一個(gè)登錄后方法, 以實(shí)現(xiàn)我們登錄之后的一些處理.session()->regenerate(); $this->clearLoginAttempts($request); #這里來(lái)做登錄后的操作 $this->singleLogin($request); return $this->authenticated($request, $this->guard()->user()) ?: redirect()->intended($this->redirectPath()); } /** * 執(zhí)行單用戶(hù)登錄, 存儲(chǔ)必要數(shù)據(jù) * @param Request $request * @throws Exception */ protected function singleLogin(Request $request) { try { $timeStampNow = time(); $userLoginIp = $request->getClientIp(); $user = Auth::user(); $singleToken = md5($userLoginIp . $user->id . $timeStampNow); Redis::set("SINGLE_TOKEN_" . $user->id, $timeStampNow); session(["SINGLE_TOKEN" => $singleToken]); } catch (Exception $exception) { throw new Exception($exception); } } }然后我們修改 app/Http/Controllers/Auth/LoginController.php 中關(guān)于上面AuthenticatesUsers trait 的引用的地方, 修改后如下:
!!注意別忘了引入命名空間!!
use AuthenticatesUsers, SingleLoginAuthenticatesUsers{ SingleLoginAuthenticatesUsers::sendLoginResponse insteadof AuthenticatesUsers; }測(cè)試結(jié)果這樣我們就替換掉了系統(tǒng)中的 sendLoginResponse
方法取而代之的是我們 SingleLoginAuthenticatesUsers 中定義的 sendLoginResponse 方法分別使用兩個(gè)瀏覽器訪(fǎng)問(wèn) localhost/home,
第一瀏覽器登錄之后, 再去第二瀏覽器進(jìn)行登錄
然后再回到第一個(gè)瀏覽器的 localhost/home 刷新一下 發(fā)現(xiàn)跳轉(zhuǎn)到了 localhost/login
這樣就完成簡(jiǎn)單的單用戶(hù)登錄功能.參考文檔:
Laravel 單用戶(hù)登錄 作者:Destiny
PHP中的Traits詳解 作者:tabalt
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/22217.html
摘要:本文經(jīng)授權(quán)轉(zhuǎn)自社區(qū)說(shuō)明發(fā)布臨近,大體構(gòu)建已經(jīng)完成,文檔整理完成后即可發(fā)布。附帶了一個(gè)響應(yīng)式郵件模板,通知類(lèi)中唯一需要做的就是像下面這樣發(fā)送消息錯(cuò)誤處理是一個(gè)可選的擴(kuò)展包,提供了完整可用的服務(wù)。 本文經(jīng)授權(quán)轉(zhuǎn)自 PHPHub 社區(qū) 說(shuō)明 Laravel 5.3 發(fā)布臨近,大體構(gòu)建已經(jīng)完成,文檔整理完成后即可發(fā)布。 下面是對(duì) Laravel 5.3 新特性的整理,不完整列表。 1、全文搜...
摘要:最佳實(shí)踐良好的編碼規(guī)范單元測(cè)試持續(xù)集成文檔,從一開(kāi)始就形成良好的編碼習(xí)慣。真實(shí)的電商業(yè)務(wù)所有的業(yè)務(wù)需求來(lái)自真實(shí)的客戶(hù),并且線(xiàn)上良好運(yùn)營(yíng)中。 重要通知: Laravel + 小程序的開(kāi)源電商版本源碼已經(jīng)在 github 上拉,歡迎提交 issue 和 star :) 開(kāi)源電商 Server 端: Laravel API源碼 開(kāi)源電商 client 端:小程序源碼 iBrand 簡(jiǎn)介...
摘要:提供了一種全新的發(fā)送通知的方式。個(gè)人理解是可以基于某事件操作觸發(fā)一系列的通知任務(wù),而通知方式由通知渠道接管,這樣使得通知或推送邏輯更抽象,更易于管理和重構(gòu)。在之前,我是利用的來(lái)完成這一系列通知。使用的配置文件還是原來(lái)的,無(wú)需重新配置。 Laravel Notification Laravel 5.3 提供了一種全新的發(fā)送通知的方式:Notification 。個(gè)人理解是可以基于某事件(...
摘要:的機(jī)器學(xué)習(xí)庫(kù)的機(jī)器學(xué)習(xí)庫(kù),包括算法交叉驗(yàn)證神經(jīng)網(wǎng)絡(luò)等內(nèi)容。在即將到來(lái)的大會(huì)上,她將和大家分享在機(jī)器學(xué)習(xí)領(lǐng)域的全新可能。入門(mén)總結(jié)入門(mén)相關(guān),如安裝配置基本使用等。 基于 Swoole 開(kāi)發(fā) PHP 擴(kuò)展 Swoole-1.9.7 增加了一個(gè)新特性,可以基于 Swoole 使用 C++ 語(yǔ)言開(kāi)發(fā)擴(kuò)展模塊,在擴(kuò)展模塊中可以注冊(cè) PHP 內(nèi)置函數(shù)和類(lèi)。現(xiàn)在可以基于 Swoole 來(lái)編寫(xiě) PHP ...
摘要:?jiǎn)栴}介紹同一個(gè)瀏覽器登錄后臺(tái),再打開(kāi)前臺(tái)頁(yè)面,前臺(tái)有輪訓(xùn)請(qǐng)求數(shù)據(jù),會(huì)出現(xiàn)后臺(tái)莫名其妙登出。問(wèn)題排查檢查日志沒(méi)有發(fā)現(xiàn)問(wèn)題,檢查沒(méi)有發(fā)現(xiàn)問(wèn)題。 1.(環(huán)境介紹) laravel 5.3做的后臺(tái),5.1做的前臺(tái) 兩個(gè)網(wǎng)站項(xiàng)目放在一臺(tái)服務(wù)器上后臺(tái)使用8080端口,前臺(tái)使用80端口,后臺(tái)需要登錄前臺(tái)不需要登錄。2.(問(wèn)題介紹)同一個(gè)瀏覽器登錄后臺(tái),再打開(kāi)前臺(tái)頁(yè)面,前臺(tái)有js輪訓(xùn)請(qǐng)求數(shù)據(jù),會(huì)出現(xiàn)...
閱讀 3487·2023-04-25 20:41
閱讀 2660·2023-04-25 16:40
閱讀 1432·2021-09-23 11:44
閱讀 1252·2021-09-10 10:51
閱讀 1681·2021-09-07 09:59
閱讀 1642·2019-12-27 12:08
閱讀 551·2019-08-30 15:44
閱讀 3334·2019-08-30 11:08