一个帐号同时只能在同一个设备上登录

一个帐号同时只能在同一个设备上登录

我用PHP实现一个帐号只能同时在同一个设备登陆,注意,不是同一个IP。
以前是在MYSQL的表中加了个显示是否登陆了的字段,若登陆了设置为1,退出设置为0.
但后来发现,强行关闭浏览器的时候就没办法把这个字段设置为0了!
想了好久没想出解决方案,后来在网上看到好像能够用redis来实现,因而这两天开始学redis。但发现这样学下去也没有什么思路啊。
因此上来请教一下,请问有谁有经验的能够说一下怎么实现吗?谢谢!祝你们中秋节快乐!php

  •  

5个回答

答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问html

采纳mysql

若是是 Redis 的话, 可使用 hash 结构来存储帐户登入信息.git

hash 的结构: key field valuegithub

hash 相关使用命令 http://redisdoc.com/hash/inde...redis

具体实现:sql

hash 结构中, 使用相同的 key field 写入数据时, 会覆盖掉历史数据数据库

Redis> hset key field Test
Redis> hget key field
"Test"
Redis> hset key field Run
Redis> hget key field
"Run"

这样就能实现单个帐户的需求, 指定一个 key 用来存储帐户登入信息, field 就是每一个帐户的主键, 那么每次登陆都会将上一次的登入信息清空, 以前的登入信息就失效了, 这样就能达到以前的登陆状态失效.segmentfault

若是考虑到不一样设备的登陆, 能够将 field 变为 devicename-uid 这种形式, 保证一个设备只可以有一个登陆信息存在.浏览器

答案对人有帮助,有参考价值1答案没帮助,是错误的答案,答非所问

关于使用mysql的一种解决方法

若是不考虑效率,只须要在mysql中你原有的记录是否已登陆的字段旁再增长过时时间设备惟一标识符两个字段,将之前的判断是否登陆的条件由“是否为1”变为“是否为1且未过时且设备惟一标识符一致”。每次用户有操做时都更新过时时间的值,若是一段时间没有操做,登陆状态就能够“自动”过时,这样就能够解决你的“强行关闭浏览器的时候就没办法把这个字段设置为0了”的问题。

使用phpredis进行简单实现

若是你刚接触redis,且仅仅须要用redis作用户登陆的控制,对于数据结构,你不是很了解,string类型便可知足你(若是能够,使用hash可能会更好)。

下面以phpredis扩展提供的相关类做为背景,进行描述:

假设某一用户id为100的帐户登陆,向redis中记录登陆设备信息

<?php
/**
 * 注册用户登陆设备信息
 * 
 * 登陆后向redis中写入登陆的设备标识信息,若是在此以前已经登陆了别的设备,以前登陆的设备将被强制下线
 */
function registerUserDevice()
{
    $userId = 100; // 假设用户id为100
    $redis = new Redis();
    $redisHost = '127.0.0.1';
    $redisPort = 6379;
    $redis->connect($redisHost, $redisPort);
    $cacheName = 'deviceUUID:user'.$userId; 
    $deviceUUID = getDeviceUUID(); // 假设有 getDeviceUUID() 函数用于获取/生成设备的惟一标识符
    $timeout = 600; // 用户10十分钟无操做自动下线
    $redis->set($cacheName, $deviceUUID);
    $redis->setTimeout($cacheName, $timeout);
}

设备每次执行其它操做前,都须要更新redis中设备信息的过时时间

<?php
/**
 * 延长redis中设备标识信息的生存时间
 *
 * 从新设置redis中用户设备标识信息的过时时间
 * @return bool true = 更新成功, false = 更新失败,当前设备须要从新登陆
 */
function extendDeviceInfoTTL()
{
    $userId = 100; // 假设用户id为100
    $redis = new Redis();
    $redisHost = '127.0.0.1';
    $redisPort = 6379;
    $redis->connect($redisHost, $redisPort);
    $cacheName = 'deviceUUID:user'.$userId; 
    $deviceUUID = getDeviceUUID(); // 假设有 getDeviceUUID() 函数用于获取/生成设备的惟一标识符
    $timeout = 600; // 用户10十分钟无操做自动下线
    $cachedDeviceUUID = $redis->get($cacheName);
    $isTimeout = false === $cachedDeviceUUID;
    $isTheRightDevice = $deviceUUID === $cachedDeviceUUID;
    if($isTimeout || !$isTheRightDevice){
        return false;
    }
    $redis->setTimeout($cacheName, $timeout);
    return true;
}

设备中用户帐户退出时,须要清理redis中的该设备信息

<?php
/**
 * 销毁用户设备信息
 * 
 * 用在执行登出操做时
 */
function delUserDevice()
{
    $userId = 100; // 假设用户id为100
    $redis = new Redis();
    $redisHost = '127.0.0.1';
    $redisPort = 6379;
    $redis->connect($redisHost, $redisPort);
    $cacheName = 'deviceUUID:user'.$userId; 
    $redis->delete($cacheName);
}

固然了,上面的使用string类型而不是散列类型来实现的解决方案在资源利用和效率上是不太合理的。若是你但愿对redis有更深的了解和运用推荐你阅读《Redis IN ACTION》这本书。具体到php中使用redis,你能够选择使用phpredis扩展predis

答案对人有帮助,有参考价值1答案没帮助,是错误的答案,答非所问

前段时间作的一个项目大概也有这么一个东西,大概目的是只能有一个终端在登陆这个帐号,即不能一个帐号多处同时登陆。

解决办法是在数据库中添加了一个字段token,每次登陆根据时间戳加其余的生成一个新的token,在整个过程当中不断检测token,若是发生改变了,那说明有用户在别处登陆。

  •  

答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问

你要知道你须要什么?
单点登陆仍是限制单设备
单设备是同一台电脑多个浏览器?

  •  

答案对人有帮助,有参考价值0答案没帮助,是错误的答案,答非所问

数据库加个字段:临时的token;等登陆后,这个临时的token会随机生成,同时用户会根据这个token生成对应的sesssion;当另一个设备登陆后,临时的token更新了;原有设备的session没法匹配数据库的token;就会自动跳出!

相关文章
相关标签/搜索