牛骨文教育服务平台(让学习变的简单)
博文笔记

实现只能同时一个人登陆管理后台

创建时间:2016-11-11 投稿人: 浏览次数:871

功能:实现后台管理系统,同一个账号,只能有一个在线,如果另一个人使用了该账号在别的浏览器登录,那么先前那个登录的人就会被挤下线。

这里分为两种情况,第一种是使用laravel框架获取的情况;第二种是直接使用php提供的获取session的方法。

使用laravel框架实现的过程如下:

总体叙述,源代码:

use IlluminateSupportFacadesSession;

Route::get("/aaa", function () {
    dd(Session::getId()); //这种方式获取浏览器传过来的session_id
});

我具体的实现方式如下:

首先在登陆的时候,进行获取session_id并且把其存入数据库,然后在中间键中每次请求都检查传递上来的session_id和数据库中存储的是否一致,如果一致那么就进行业务实现,如果不一致,则说明异地登录了,然后把前一个登陆的用户踢下线。

大致原理是: 浏览器每次请求服务器,其请求头信息中都会包含有一个session_id,该session_id有个特点就是:如果该浏览器没有关闭的情况下,并且session_id没有失效(如果失效,那么失效的原因就是因为长时间没有操作浏览器)的情况下,那么在同一个浏览器中每次请求的时候,session_id都是一样的,而不会发生变化。因此我们就可以基于此来进行判断,如果session_id发生变化了(变化的情况分为三种:

 1.同一台电脑上使用了同一个账号在不同浏览器去登录 。
 2.在另一台电脑上使用了同一个账号去登录。 
 3.长时间没有操作浏览器,导致session失效了 

),如果变化了,那么我们就把前一个登录的人给踢下线。

首先登录的方法如下所示:

use IlluminateSupportFacadesSession;
/**
* 处理登陆表单
* @param Request $request
*/
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]); //把登录的用户信息缓存到session里面
     $last_session = Session::getId(); //这个是laravel框架自带的获取浏览器传递上来的seession_id方法
     AdminUsers::where("id",$user->id)->update(["last_session"=>$last_session]);
     return redirect(url("ymzy/admin/")); //跳转到后台首页
 } else {
     //登录失败
     return $this->buildFailedValidationResponse($request, ["password" => "密码不正确"]);
 }
}

接下来就是定义一个中间键,在中间键中如下操作:

<?php

namespace AppHttpMiddleware;

use AppModelsAdminUsers;
use Closure;
use IlluminateSupportFacadesSession;

class AdminAuth
{
 /**
   * Handle an incoming request.
   * @param  IlluminateHttpRequest  $request
   * @param  Closure  $next
   * @return mixed
   */
  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_id和数据库中存储的进行比较
          session(["adminAuth"=>null]); //清除session
          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();//注意:需要打开服务端的session配置
$user->last_session = session_id(); //获取浏览器传递的session
$user->save(); //保存到数据库

if(session_id() != Auth::user()->last_session){ //进行比较每次请求传递来的和数据库存储的session_id是否一致
   Auth::logout(); //退出登陆(如果不一致则踢下线)
   return true;
}

然后这种方法剩下的实现方式就和laravel实现方式一样了,无非就是每次请求的时候在该请求所在的接口里面分别进行session_id() != Auth::user()->last_session判断即可。

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。