PHP怎么做到手机端第一坊无限制账号共享同一个账号不能同时登录

--一步,二步,三步,N步,二行脚印
张映 发表于
分类目录:
标签:, , , ,
以前考虑过这个问题,今天实现了一下,挺快的,从研究到开发完成差不多4个小时。有点类似QQ,二台电脑登录,一台会把另一台挤掉线,并提示其他地点登录信息。
一,实现原理
1,用户在电脑A登录,session信息存放在redis当中,并将session_id存到mysql数据库中。
2,同一用户在电脑B登录,验证完用户名和密码后,将该用户信息从数据库读出,取得用户在电脑A登录的session_id,然后在到redis中验证session是否过期。
3,如果过期,不用openfire推送提示信息。如果没有过期,php利用openfire推送消息后,在将redis中用户在电脑A中登录的session删除掉,删除后,在将用户在电脑B登录的个人信息放到session中,并将电脑B登录的session_id更新到数据库中,在这里一定要先发送推送,然后在清空session,不然用户在电脑A收不到xmpp发过来的消息。
openfire是java cms的一种,自身有数据库,您创建的用户表根openfire自带的用户表之间要建立某种联系(如:手机号,邮箱等),方便信息推送。
同一session_id肯定是在相同媒介上登录的,这个时候,也不用更新数据库和推送消息
下面简单说一下安装过程,以及要注意的地方。
二,安装所用到的工具
# yum install php php-fpm nginx mysql mysql-server redis php-redis php-devel php-pdo php-mysql
修改session存储方式:
# vim /etc/php-fpm.d/www.conf
;php_value[session.save_handler] = files
//注释掉旧的
;php_value[session.save_path] = /var/lib/php/session
php_value[session.save_handler] = redis
//添加以下内容
php_value[session.save_path] = "tcp://127.0.0.1:6379"
启动服务后,如果以下内容说明,session存redis成功了
redis telnet查看session
openfire下载地址:http://www.igniterealtime.org/downloads/
# rpm -ivh ./*.rpm
//下载的是rpm安装包
openfire启动后,然后访问http://ip:9090,一步一步配置就成了,有一点要注意就是数据库的编码。
关于redis的php操作和命令行操作,请参考:
转载请注明作者:海底苍鹰地址:问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
我用PHP实现一个账号只能同时在同一个设备登录,注意,不是同一个IP。之前是在MYSQL的表中加了个显示是否登录了的字段,若登录了设置为1,退出设置为0.但后来发现,强行关闭浏览器的时候就没办法把这个字段设置为0了!想了很久没想出解决方案,后来在网上看到好像可以用redis来实现,于是这两天开始学redis。但发现这样学下去也没有什么思路啊。所以上来请教一下,请问有谁有经验的可以说一下怎么实现吗?谢谢!祝大家中秋节快乐!
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
如果是 Redis 的话, 可以使用 hash 结构来存储账户登入信息.
hash 的结构:
key field value
hash 相关使用命令
hash 结构中, 使用相同的 key field 写入数据时, 会覆盖掉历史数据
Redis& hset key field Test
Redis& hget key field
Redis& hset key field Run
Redis& hget key field
这样就能实现单个账户的需求, 指定一个 key 用来存储账户登入信息, field 就是每个账户的主键, 那么每次登录都会将上一次的登入信息清空, 之前的登入信息就失效了, 这样就能达到之前的登录状态失效.
如果考虑到不同设备的登录, 可以将 field 变为 devicename-uid 这种形式, 保证一个设备只能够有一个登录信息存在.
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
关于使用mysql的一种解决方法
如果不考虑效率,只需要在mysql中你原有的记录是否已登录的字段旁再增加过期时间和设备唯一标识符两个字段,将以前的判断是否登录的条件由“是否为1”变为“是否为1且未过期且设备唯一标识符一致”。每次用户有操作时都更新过期时间的值,如果一段时间没有操作,登录状态就可以“自动”过期,这样就可以解决你的“强行关闭浏览器的时候就没办法把这个字段设置为0了”的问题。
使用phpredis进行简单实现
如果你刚接触redis,且仅仅需要用redis做用户登录的控制,对于数据结构,你不是很了解,string类型即可满足你(如果可以,使用hash可能会更好)。
下面以提供的相关类作为背景,进行描述:
假设某一用户id为100的账户登录,向redis中记录登录设备信息
* 注册用户登录设备信息
* 登录后向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中设备信息的过期时间
* 延长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){
$redis-&setTimeout($cacheName, $timeout);
设备中用户账户退出时,需要清理redis中的该设备信息
* 销毁用户设备信息
* 用在执行登出操作时
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,你可以选择使用或。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
前段时间做的一个项目大概也有这么一个东西,大概目的是只能有一个终端在登录这个账号,即不能一个账号多处同时登录。
解决办法是在数据库中添加了一个字段token,每次登录根据时间戳加其他的生成一个新的token,在整个过程中不断检测token,如果发生改变了,那说明有用户在别处登录。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你要知道你需要什么?单点登录还是限制单设备单设备是同一台电脑多个浏览器?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
数据库加个字段:临时的token;等登录后,这个临时的token会随机生成,同时用户会根据这个token生成对应的sesssion;当另外一个设备登录后,临时的token更新了;原有设备的session无法匹配数据库的token;就会自动跳出!
同步到新浪微博
分享到微博?
你好!看起来你挺喜欢这个内容,但是你还没有注册帐号。 当你创建了帐号,我们能准确地追踪你关注的问题,在有新答案或内容的时候收到网页和邮件通知。还能直接向作者咨询更多细节。如果上面的内容有帮助,记得点赞 (????)? 表示感谢。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
扫扫下载 App问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
目前做的都是可以同时在线,改了密码之后不同设备登录的没有下线,如何保证改密码以后所有的session全部清空掉?以及有登录状态的就不能再登录或者前一个下线。像QQ这样说怎么实现的?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
qq 就是及时通讯.
如果是 php, 建议给登陆一个 token , 每次登陆这个 token 都会变. 这样旧的 session 里存的 token 就过期不存在了, 你就让另外一个登陆状态退出就行了.
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
大概就像楼上朋友说得那样。在redis中建个hash,key是用户id,value是token,更改密码后,更新这个value
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
补充下 他们提供的思路中少了一个心跳机制 每个客户端都要把当前的token发送给服务端 对比 过期的全部踢除
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
Redis里,用户的ID作为键,用户的密码哈希作为值.
这个密码哈希根据后端关系数据库用户计算出来,放到Redis缓存.
用户修改密码时,更新Redis的密码哈希.
这样cookie认证时,比对密码哈希,不一致自然cookie就是失效了.
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
login成功的时候,把sessionID存到数据库或者其它缓存,sessionId最多存在一个
判断用户是否登陆,依据就是这个sessionId
这样的话,产生第二次登陆,前一次登陆的session就会失效
同步到新浪微博
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
扫扫下载 App

我要回帖

更多关于 淘宝账号被限制登录 的文章

 

随机推荐