最近在赶一个项目时用到了单点登录功能,一开始在百度和官网中搜了搜,得到的结果不是不我想要的,毕竟是一个小东西搞的太复杂了。所以自己想出了一个简单实现功能
要求是会员在不同的登录端登录时,退出其它已登录端。开发框架是用的Thinkphp5.1,先前想是直接用缓存实现,后面发现可以用Session和Cache一起更简单实现。
利用的是用户每次登录帐号时,先读取缓存记录单点登录的值并加1,并把此值同时记录到此登录用户信息的Session,在用户公公共类中判断,Session存的值与缓存中的值是否一致,如果不一致则为其它用户登录。则把此用户退出处理,
例如:
用户在谷歌浏览器第一次登录时:用户:ID=1、那么:SinglePoint_1 =1、Session=1,
如果为空那么赋值他为1,
用户在火狐浏览器第二次登录时:用户:ID=1、那么:SinglePoint_1 =2、Session=2,
则谷歌浏览器此时刷新是得到的值 SinglePoint_1=2、Session=1,所以被退出了
login.php (登录页)**********************************************
//以下代码只做实例功能演示,省略其它……
//获取登录状态
$_USER = Session::get('user');
//判断是否已登录,如果已是登录状态,则跳转到会员中心主页
if ($_USER['id']) {
return $this->redirect(url('home'));
}
//判断POST请求
if ($this->request->isPost()) {
$user=Db::name('user')->where(['username' => $post['username']])->find();
//缓存单点登录值
Cache::inc('SinglePoint_'.$user['id']);
$user['single_point']=Cache::get('SinglePoint_'.$res['id']);
//设置用户信息缓存
Session::set('user', $user);
//以下进行登录成功所跳转,等操作略过//
}else{
return $this->fetch();
}
common.php(这是一个公共类页面,会员登录成功后,会员页面的其它功能都继承着这个公共类)
//以下代码只做实例功能演示,省略其它……
//这里用到了控制器初始化,这是thinkphp主自定义的,其实和php中构造方法 __construct()其实是一样的,
protected static $_UID = null;
public function initialize() {
//获取登录状态
$_USER = Session::get('user');
//判断是否已登录,否则跳到登录页
if ($_USER['id']) {
$single_point=Cache::get('SinglePoint_'.$_USER['id']);
if(empty($single_point) || $_USER['single_point']!=$single_point){
return $this->logout();
}
self::$_UID = $_USER['id']; //用户ID
}else{
return $this->redirect(url('login'));
}
}
/**
* Notes: 退出登录
*/
public function logout() {
if(self::$_UID){
Cache::rm('SinglePoint_'.self::$_UID);
}
Session::delete('user');
$this->redirect(url('login'));
}