我想实现一个功能,就是当一个用户登陆了以后,就不可以在其它的机器上登陆了,我本来想在数据表里加一个标志列用来记录用户的登陆状态,后来想到当用户关闭浏览器时不是这个标识列没有被改回来吗,这样此用户就下次无法登陆了?希望有更好的办法!还有一个问题,就是怎么限制用户的表单重复刷新操作导致数据重复增加或出错?请大家说得详细一点,最好是有源码的!谢谢大家的关注!本人的QQ:295894563.
ç±»:NameII æé:public
æ¹æ³:main æé:public
åæ°:name,password,denglu,i;
1.åæ°ä»ç»:
nameï¼æ°æ®ç±»å String ï¼ç¨æ¥åå¨ä¸ä¸ªä» input ä¸è·åçå¼ï¼å¨æ¬ç¨åºå½ä¸ç¨ä½ç¨æ·åçåæ¾ï¼
passwordï¼æ°æ®ç±»å String ï¼ç¨æ¥åå¨ä¸ä¸ªä» input ä¸è·åçå¼ï¼å¨æ¬ç¨åºå½ä¸ç¨ä½å¯ç çåæ¾ï¼
dengluï¼æ°æ®ç±»å booleanï¼ç¨æ¥åå¨é»è®¤è´¦æ·çç»å½ç¶æï¼true 表示ç»å½æåï¼false 表示å°æªç»å½ï¼
iï¼æ°æ®ç±»å int ï¼ç¨æ¥åå¨ä¸ä¸ªç¨æ·å°è¯ç»å½å¤±è´¥æ¬¡æ°çå¼ï¼
2.æ¹æ³åè½:
å¨æ§å¶å°è¾åºâ请è¾å
¥ç¨æ·åï¼âè¦æ±ç¨æ·ä»æ§å¶å°è¾å
¥ä¸ä¸ª String ç±»åçæ°å¼åæ¾å°nameå½ä¸ï¼
èåå¨æ§å¶å°è¾åºâ请è¾å
¥å¯ç ï¼âè¦æ±ç¨æ·ä»æ§å¶å°è¾å
¥ä¸ä¸ª String ç±»åçæ°å¼åæ¾å¨passwordå½ä¸ï¼
éªè¯ä»æ§å¶å°éè¿ input ä¸è·åçç¨æ·ååå¯ç æ¯å¦ä¸é»è®¤çç¨æ·ååå¯ç ä¸è´ï¼
å¦æä¸è´ï¼åè¾åºâç»å½æåâï¼å¹¶æ´æ¹ç¨æ·ç»å½ç¶æ denglu çå¼ä¸º true ï¼
å¦æä¸ä¸è´ï¼æéç¨æ·ç»å½å¤±è´¥ï¼å°ç¨æ·å°è¯ç»å½å¤±è´¥ç次æ°å 1ï¼å¹¶æéç¨æ·è´¦å·å©ä½çå°è¯ç»å½æ¬¡æ°ï¼
ç¨æ·å°è¯ç»å½å¤±è´¥ç次æ°è¾¾å°3次ï¼å¹¶æ示ç¨æ·åè´¦å·è¢«å»ç»ã
public class NameII {
public static void main (String []arge) {
boolean denglu = false;//声æä¸ä¸ª boolean æ°æ®ç±»åçåé denglu åå¨ç¨æ·åçç»å½ç¶æï¼é»è®¤å¼ä¸º false å°æªç»å½ï¼
int i = 0;//声æä¸ä¸ª int æ°æ®ç±»åçåé i åå¨ç¨æ·å°è¯ç»å½å¤±è´¥ç次æ°ï¼
java.util.Scanner input = new java.util.Scanner (System.in);
do{
System.out.println("请è¾å ¥ç¨æ·åï¼");
String name = input.next();//声æä¸ä¸ª String æ°æ®ç±»åçåé name åå¨ input ä¸è·åçç¨æ·åçå¼ï¼
System.out.println("请è¾å ¥å¯ç ï¼");
String password = input.next();//声æä¸ä¸ª String æ°æ®ç±»åçåé password åå¨ input ä¸è·åçå¯ç çå¼ï¼
//éªè¯ name ä¸çå¼å password ä¸çå¼æ¯å¦åç¨æ·ååå¯ç ä¸è´ï¼
if ("zhang".equals(name)&&"123".equals(password)){//å¦æä¸è´åæ§è¡ä»¥ä¸ä»£ç åï¼
System.out.println("ç»å½æå");//æ示ç¨æ·åç»å½æåï¼
denglu = true;//æ´æ¹ç¨æ·åç»å½ç¶æï¼
}else{//å¦æä¸ä¸è´åæ§è¡ä»¥ä¸ä»£ç åï¼
//æéç¨æ·ç»å½å¤±è´¥ï¼å°ç¨æ·å°è¯ç»å½å¤±è´¥ç次æ°å 1,并æéç¨æ·è´¦å·å©ä½çå°è¯ç»å½æ¬¡æ°ï¼
i++;
System.out.println("ç»å½å¤±è´¥ï¼æ¨è¿å¯ä»¥å¨å°è¯" + (3-i) +"次");
//ç¨æ·å°è¯ç»å½å¤±è´¥ç次æ°è¾¾å°3次ï¼å¹¶æ示ç¨æ·åè´¦å·è¢«å»ç»ï¼
if(i == 3){
System.out.println("è´¦å·æå¯ç é误ä¸æ¬¡ï¼è´¦å·å»ç»");
}
}
}while(i < 3 && !denglu);//满足 å°è¯ç»å½å¤±è´¥ç次æ°å°äºä¸æ¬¡çç¨æ· æ ç»å½æåçç¨æ·ï¼
}
}
提示他该账号已经有人在使用中.
然而这样有个问题很难解决,就是系统很难实时捕捉到该账号是否还在使用中,
如当用户非正常退出或者遇到停电等,系统只好等到Session超时后才能知道该账号已经下线.
在Session超时之前这段时间之内没有人使用账号但也没人再能登陆上去,只能干等着了.
我的解决方法是模仿QQ的被迫下线的功能。只要你QQ号和密码正确,随时都可以登陆上去,但是如果
该QQ号此前有人在使用的话那先前的人就会被挤下去。我们这样来实现系统防止用户重复登陆的话就可以轻松实现。关键就是在Application或数据库中记录下在线用户的SessionID,检测使用者的SessionID是否和Application中记录的该用户ID相对应的SessionID相同,若不相同则提示下线!
用户登陆成功时用户ID和SessionID写入Application中。
public void WriteToApplication( string UserID )
{
DataTable dtUserFlagList = new DataTable();
try
{
dtUserFlagList = (DataTable)Application["UserFlagList"];
}
catch
{
dtUserFlagList = null;
}
if( dtUserFlagList == null )
{
DataColumn dc0 = new DataColumn("UserID",typeof(System.String));
DataColumn dc1 = new DataColumn("SessionID",typeof(System.String));
dtUserFlagList.Columns.Add( dc0 );
dtUserFlagList.Columns.Add( dc1 );
dtUserFlagList.Columns.Add( dc2 );
DataRow drUser = dtUserFlagList.NewRow();
drUser["UserID"] = UserID; //写入用户ID
drUser["SessionID"] = Session.SessionID;//记录下SessionID
dtUserFlagList.Rows.Add( drUser );
}
else
{
int i = 1;
foreach( DataRow drUser in dtUserFlagList )
{
if( drUser["UserID"].ToString() == UserID )
{
drUser["SessionID"] = Session.SessionID;//如果在Application中存在当前用户ID,则把记录的SessionID值改为当前的SessionID
break;
}
i++;
}
if( i > dtUserFlagList.Rows.Count )
{
DataRow drUser = dtUserFlagList.NewRow();
drUser["UserID"] = UserID; //写入用户ID
drUser["SessionID"] = Session.SessionID;//记录下SessionID
dtUserFlagList.Rows.Add( drUser );
}
}
Application.Lock();
Application["UserFlagList"] = dtUserFlagList; //记录到Application中
Application.UnLock();
Session["UserID"] = UserID;//把相关登陆信息写入Session
}
下一步我们只要检测Application中记录的SessionID是否和当前的SessionID相同就可以了
我在这里写了一个页面的基类,每个页面继承这个类。这个类改写OnLoad()事件,加入检测SessionID值
public class PageBase : System.Web.UI.Page
{
public PageBase()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
if( ! IsPostBack )
{
if( Session["UserID"] == null )
{
Response.Redirect("Login.aspx");//没有登陆
return;
}
DataTable dtUserFlagList = (DataTable)Application["UserFlagList"];
foreach( DataRow drUser in dtUserFlagList )
{
if( drUser["UserID"].ToString() == Session["UserID"].ToString() )
{
if( drUser["SessionID"].ToString() == Session.SessionID )
break;//SessionID值相同,没有其他用户登陆
else
{
Session.Abandon();//SessionID不相同,有人在使用该账号,被迫下线
Response.Redirect("ShowError.aspx?action=该账号已在别处登陆",false);
}
}
}
}
}
}
当用户正常退出系统或非正常退出Session超时,在Application中清除该账号的记录
以下代码写在Global.asax.cs文件Session_End方法中
protected void Session_End(Object sender, EventArgs e)
{
if( Session["UserID"] == null )
return;
DataTable dtUserFlagList = (DataTable)Application["UserFlagList"];
foreach( DataRow drUser in dtUserFlagList )
{
if( drUser["UserID"].ToString() == Session["UserID"].ToString() && drUser["SessionID"].ToString() == Session.SessionID )
{
//当UserID和SessionID都和退出用户的值相等时才清除记录。
drUser.Delete();
break;
}
}
dtUserFlagList.AcceptChanges();
Application.Lock();
Application["UserFlagList"] = dtUserFlagList; //将更改记录到Application中
Application.UnLock();
}
以上方法已经在我的系统中实现,在我的系统可以设定某个账号同时登陆多少人,只是在记录中多了一个字段amount。
这个方法可能不好的地方就是每访问一个页面都要检测是否SessionID值相等,本回答被提问者采纳
其实用cookie感觉更好。一般网站都用cookie吧,因为cookie安全性好点。还可以方便地设置有效期。
关闭浏览器时也监控就可以了.可用js来实现.
只要session失效就执行数据库操作,相当一个监听器的效果.