功能:实现后台管理系统,同一个账号,只能有一个在线,如果另一个人使用了该账号在别的浏览器登录,那么先前那个登录的人就会被挤下线。
这里分为两种情况,第一种是使用laravel框架获取的情况;第二种是直接使用php提供的获取session的方法。
使用laravel框架实现的过程如下:
总体叙述,源代码:
use Illuminate\Support\Facades\Session;
Route::get('/aaa', function () {
dd(Session::getId());
});
我具体的实现方式如下:
首先在登陆的时候,进行获取session_id并且把其存入数据库,然后在中间键中每次请求都检查传递上来的session_id和数据库中存储的是否一致,如果一致那么就进行业务实现,如果不一致,则说明异地登录了,然后把前一个登陆的用户踢下线。
大致原理是: 浏览器每次请求服务器,其请求头信息中都会包含有一个session_id,该session_id有个特点就是:如果该浏览器没有关闭的情况下,并且session_id没有失效(如果失效,那么失效的原因就是因为长时间没有操作浏览器)的情况下,那么在同一个浏览器中每次请求的时候,session_id都是一样的,而不会发生变化。因此我们就可以基于此来进行判断,如果session_id发生变化了(变化的情况分为三种:
1.同一台电脑上使用了同一个账号在不同浏览器去登录 。
2.在另一台电脑上使用了同一个账号去登录。
3.长时间没有操作浏览器,导致session失效了
),如果变化了,那么我们就把前一个登录的人给踢下线。
首先登录的方法如下所示:
use Illuminate\Support\Facades\Session;
public function postLogin(Request $request)
{
$this->validate($request, ['name' => 'required',
'password' => 'required',
'captcha' => 'required|captcha'
], [], AdminUsers::getCustomAttributes());
$user = AdminUsers::where('name', $request->get('name'))->first();
if (empty($user)) return $this->buildFailedValidationResponse($request, ['name' => '用户不存在']);
$srt_des = Crypt::decrypt($user->password);
if ($request->password === $srt_des) {
session(['adminAuth' => $user->id]);
$last_session = Session::getId();
AdminUsers::where('id',$user->id)->update(['last_session'=>$last_session]);
return redirect(url('ymzy/admin/'));
} else {
return $this->buildFailedValidationResponse($request, ['password' => '密码不正确']);
}
}
接下来就是定义一个中间键,在中间键中如下操作:
<?php
namespace App\Http\Middleware;
use App\Models\AdminUsers;
use Closure;
use Illuminate\Support\Facades\Session;
class AdminAuth
{
public function handle($request, Closure $next)
{
if(is_null(session('adminAuth'))) return redirect(url('ymzy/admin/administrator/login'));
$id = session()->get('adminAuth');
$data = AdminUsers::where('id',$id)->first();
if(Session::getId() != $data->last_session){
session(['adminAuth'=>null]);
return redirect(url('ymzy/admin/administrator/login'));
}
return $next($request);
}
}
最后注意,在后台每次操作,调用数据的时候都应该首先经过该中间键,示例代码如下:
Route::group([
'prefix' => 'api/v1','namespace' => 'Admin','middleware'=>['auth.admin']
],function (){
Route::get('/', 'UserController@index');
});
});
第二种是使用普通方式或者是别的框架实现该功能的方法:
总体来说,我们可以使用如下代码来实现:
session_start();
$user->last_session = session_id();
$user->save();
if(session_id() != Auth::user()->last_session){
Auth::logout();
return true;
}
然后这种方法剩下的实现方式就和laravel实现方式一样了,无非就是每次请求的时候在该请求所在的接口里面分别进行session_id() != Auth::user()->last_session判断即可。