先说说这个功能思路:
说明一点:现在是对单个的用户限定登录的个数,并不是限定最多多少个用户登录服务器,所以想用Session_OnEnd,Aplliction_onEnd的方法是行不通的,因为当发生了Session_OnEnd时用户的标识Session已经丢了,来不及把对应用户的登录信息做处理了……
新建一个表Login,记录用户的ID,和用户上线时间。做一个隐藏框架(高宽都是0),让它每隔一段时间向服务器提交一次数据,更新Login表中对应用户的“上线时间”。
这样用户登陆时,如果该用户名在Login表中无登录信息或登录信息不大于限定的最大登录数,说明用户可以登录,这时Login表里加一条记录表示这个用户名已经有一个用户登陆。如果这个用户登录时发现Login表里的该用户登录条数已经占满,再查看有没有“上线时间”过期的!如果“上线时间”有过期的,那此次登录就占用这条登录信息,并把上线时间刷新为当前时间。如果用户的登录条数已经占满且没有过期的用户那就返回登录失败。
-----------------------------------------------------------------
思路实现(ASP+MSSQL)
数据库里本身就有用户表了,为了写起来方便,这里只写本功能相关的字段及其内容:
user表:添加一个字段User_LoginSum,设定同一用户名允许同时在线的个数
User_ID,User_name,User_PWD,User_LoginSum
自动编号,用户名,用户密码,用户可登录的个数
Login表:新建表,保存用户的登陆信息
Login_ID,Login_UserID,Login_RefreshTime
自动编号,用户的ID,用户刷新时间
先来看用户登录时要做的处理:这里建立一个函数,如果用户名和密码正确的话所该用户的ID,和允许的登录个数传给这个函数,函数作处理后,如果登录成功把一个公共变量LoginTrue的值设为True,反之设为False
以下是代码片段:
<% public LogTrue '公共变量,用户是否能够登录
'判断同一账号同一时间登录的个数 function LoginSum(User_ID,User_LoginSum)
User_LoginSum=cint(User_LoginSum)
SQL="select * from Login where Login_UserID="&User_ID set RST=server.CreateObject("adodb.recordset") RST.Open SQL,conn,1,3
if RST.RecordCount < User_LoginSum then '登录用户数没有超过限定条数 SQL="insert into Login(Login_UserID,Login_RefreshTime) values("&User_ID&",'"&now&"')"
conn.execute(SQL) SQL="select top 1 * from Login order by Login_ID desc" '得到新添加的记录的ID set RST=server.CreateObject("adodb.recordset") RST.Open SQL,conn,1,3 Session("Login_ID")=RST("Login_ID") '添加一个session 识别是占用的哪条登陆信息 LogTrue=True else SQL="select top 1 * from Login where ('"&now&"' - Login_RefreshTime) > '0:09:00' and Login_UserID="&User_ID '当前时间减掉用户的刷新时间, '如果大于设定的刷新时间值说明原来占用这条信息的用户已经不在线了 '时间可以相加减,得到的结果还是标准的时间
set RST=server.CreateObject("adodb.recordset") RST.Open SQL,conn,1,3 if Not RST.eof then Login_ID=RST("Login_ID") Session("Login_ID")=Login_ID '添加一个session 识别是占用的哪条登陆信息 SQL="update Login set Login_RefreshTime='"&now&"' where Login_ID="&Login_ID conn.execute(SQL)
LogTrue=True else LogTrue=False '登录用户数已满,且用户在线时间没有过期的,返回登录失败 end if end if
end function %>
|
看一下隐藏框架页每隔一段时间自动刷新“上线时间”的代码,这里起的文件名为:sessionKeeper.asp
以下是代码片段:
<html> <head> <meta http-equiv="Refresh" content="500;url=sessionKeeper.asp"> <!-- 每隔500秒刷新一下自己,为了和服务器通讯一下,保持session不会丢 注意这个时间不能大于用户是否能登录的判断函数LoginSum()中的SQL="s elect top 1 * from Login where ('"&now&"' - Login_RefreshTime) > '0:09:00' and Login_UserID="&User_ID 中的"0:09:00" 这个时。这里是500秒,8分钟多一点……。为什么要这样,偶表达有限,自己去想…… --> <%
SQL="update Login set Login_RefreshTime='"&now&"' where Login_ID="& session("Login_ID") '刷新“在线时间”为当前时间,保持在线 conn.execute(SQL) %> </head> </html>
|
顺便看一下如果用户正常退出时清楚Session,并把自己的占用的登录信息的刷新时间改为一个绝对过期的时间。这里设为 "2000-01-01 0:0:0"
以下是代码片段: <%
SQL="update Login set Login_RefreshTime='2000-01-01 0:0:0' where Login_ID="&Session("Login_ID"),如果非法退出,比仿说掉电的话,那该用户虽然已经不在线了,可是还要等8分多钟才能再次登录。 conn.execute(SQL)
session("Login_ID")="" %>
|
当在编辑用户信息,或删除用户时把Login表中的所有的关于此用户的所有“登录时间”过期的记录删除
以下是代码片段:
<% conn.execute("Delete from Login where Login_AccountID="&session("AccountID")&" and ('"&now&"' - Login_RefreshTime) > '0:09:00') %>
|
发表于 @ 2008年02月26日 01:20:00|评论(loading...)|编辑