不一樣用戶和服務器之間由一個惟一的session來區分,可是通常狀況下不一樣的session對應的用戶model能夠是同一個。ajax
爲了實現只能同時在一個地方登錄,能夠在用戶的字段裏增長一個last_session來表示該用戶model最近登陸使用的session,每當用戶進行了一次登錄操做後,把last_session重置爲當前的session。而後增長一箇中間件,判斷每一個請求使用的session是不是最近登錄的session,若是不是,返回登陸頁面,表示你已經被踢了。同時頁面上也增長一個定時執行的ajax來判斷當前的登陸狀態是否還有效,若是被踢了,提示而且返回登陸頁面。json
1)重置last_session服務器
這是登陸時用的函數:session
protected function attemptLogin(Request $request) { if ($this->guard()->attempt($this->credentials($request), $request->has('remember'))){ return $this->guard()->attempt($this->credentials($request), $request->has('remember')); } }
登陸的函數在LoginController裏,可是在這個函數裏重置last_session是沒用的。函數
return時調用的attempt函數來自這裏:this
並且是一個只有聲明(???)沒有實現的函數(???)url
看一下它在哪些地方使用過:spa
打開第一個文件,找到這個函數:3d
注意到下面有個sendLoginResponse函數裏面執行了一個session的regenerate,猜想應該是這裏產生了一個新的session替換了登陸時使用的那個,因而把last_session的重置寫在這裏:code
Auth::user()->last_session=Session::getId();
Auth::user()->save();
成功了。
2)中間件
public function handle($request, Closure $next){ if (Session::getId()!=Auth::user()->last_session){ if ($request->ajax())return response()->json(['status'=>'guoqile']); else return redirect('login'); } return $next($request); }
3)頁面ajax(和一個讀取新消息的混在一塊兒了)
$(document).ready(function(){ setInterval("ajaxGetNotify()", 5000) }); //$(document).ready(ajaxGetNotify()); var title = document.title function ajaxGetNotify(){ $.ajax({ type: 'GET', url: 'notification_num', dataType: 'json', success: function(data){ var i=0; if (data['num'] != undefined) { if (data['num'] > 0) { setInterval(function test() { i++; if (i == 1) document.title = '【新消息】' + title; if (i == 2) document.title = '【 】' + title; if (i == 3) i = 0; }, 600); } } if (data['status'] != undefined) { if (data['status'] == 'guoqile') { alert('因爲帳號在另外一地點登陸,您已被迫下線。'); location.reload(); } } } }); }