实现网页同时只能有一个账号登录
2017-05-10 07:45
696 查看
网上看了很多方法,个人也看了,自己也总结了几个比较常用的:
前提都是用session监听器,对session的创建与销毁进行监听
一、在用户登录时保存该用户的状态有这几种保存方式:
1、保存到内存中(application ,servletcontext ,个人也是推荐这种方式)
2、保存状态到数据库,至于具体的怎么保存你可以随意返回,如:0,1两种状态
3、保存到文件中,对文件的读写
以上是登录用户的状态,这对于大家来说都没有什么问题。
二、 这时如果同一用户登录了,你可以在登录成功后(保存信息之前)进入到上面的状态 中进行匹配判断,如果存在就提醒此用户你的账号已登录。
三、关键在于该用户的销毁
invliate(),调用这个方法,通过Session的监听器,进行对当前用户的删除。
Session过期,也会调用Session监听器。
讨论最多的就是在比如用户没有自己去注销session.invalidate()方法,而是直接关闭了 浏览器,这时怎么办?(浏览器关闭半个小时候,默认注销session,监听器这时才调用sessionDestroyed方法)。
首先要明确的一点,用户关闭浏览器,服务器端是无法得知的(因为web客户浏览器与服务器之间是无状态的),网上也有一些解决方案,比如通过js来判断用户是否关闭了浏览器,是的次方法可行,但是如果用户操作时,打开了多个窗口呢,这里也有方法:
1、一个方法还是比较好的,通过cokkie保存当前用户开了的页面数,如果页数为一的话,就可以触发js的注销Session了。
2、先把Session的生命期设置的短一点,用类似ajax这种异步请求方式周期不断的去请求后台,这样可以保证当前的这个Session有效,如果用户退出后,该Session也会很快的过期。
上面的两种方式都有些缺陷,如:
1、用户删除cokkie的话,就无法判断准确,这种可能应该不多吧(在访问当前网站时)
2、有延迟,服务器压力相对来说比较大
还有一种方式与上面的思考角度不一样(当然也要看需求了),如果有用户登录时,就注销之前已登录的同一用户。
实现方式与上面应该是差不多的,唯一不同之处在于,不用去刻意的想办法让用户退出了(注销Session)。
四、虽然像百度,CSDN等这些网站都没有这样做,当然也没有必要这要这样做。
但是在我们做企业内部应用的时候有时候可能会要求我们这样做(同一账号在统一时间只能在一个登录),下面是个例子
我们先定义两个Map对象需要用到,存放用户与HttpSession的关系和sessionId与用户的关系。用来记录当前登录的用户是否登录和当前session是否已经绑定了登录用户。
[java] view
plain copy
/**
* 用户和Session绑定关系
*/
public static final Map<String, HttpSession> USER_SESSION=new HashMap<String, HttpSession>();
/**
* seeionId和用户的绑定关系
*/
public static final Map<String, String> SESSIONID_USER=new HashMap<String, String>();
然后我们需要实现HttpSessionListener接口监听,主要是监听session的销毁事件。
[java] view
plain copy
public void sessionDestroyed(HttpSessionEvent se) {
String sessionId=se.getSession().getId();
//当前session销毁时删除当前session绑定的用户信息
//同时删除当前session绑定用户的HttpSession
USER_SESSION.remove(SESSIONID_USER.remove(sessionId));
}
接下来是关键,处理登录用户的唯一。
当用户登录进来的时候我们先把当前HttpSession绑定的用户和用户绑定的HttpSession关系删除。
再次我们删除当前登录的用户绑定的HttpSession关系,如果当前用户已经登录删除session和用户的关系、删除session中用户的信息、设置说明用户被挤下线了。
[java] view
plain copy
/**
* 用户登录时的处理
* 处理一个账号同时只有一个地方登录的关键
* @param request
*/
public static void userLoginHandle(HttpServletRequest request){
//当前登录的用户
String userName=request.getParameter("userName");
//当前sessionId
String sessionId=request.getSession().getId();
//删除当前sessionId绑定的用户,用户--HttpSession
USER_SESSION.remove(SESSIONID_USER.remove(sessionId));
//删除当前登录用户绑定的HttpSession
HttpSession session=USER_SESSION.remove(userName);
if(session!=null){
SESSIONID_USER.remove(session.getId());
session.removeAttribute("userName");
session.setAttribute("userMsg", "您的账号已经在另一处登录了,你被迫下线!");
}
}
用户登录的请求处理。先判断用户输入的登录信息是否合法,在判断用户输入的信息是否正确(登录是否成功),成功则调用单用户登录的处理方法,把当前登录的用户和当前session关联,session中保持当前登录用户的信息
[java] view
plain copy
/**
* 用户登录
*/
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String userName=request.getParameter("userName");
String password=request.getParameter("password");
if(userName!=null&&!"".equals(userName.trim())){
//登录成功
if(login(userName, password)){
HttpSession session=request.getSession();
//处理用户登录(保持同一时间同一账号只能在一处登录)
userLoginHandle(request);
//添加用户与HttpSession的绑定
USER_SESSION.put(userName.trim(), session);
//添加sessionId和用户的绑定
SESSIONID_USER.put(session.getId(), userName);
session.setAttribute("userName", userName);
session.removeAttribute("userMsg");
}
}
response.sendRedirect("index.jsp");
}
//对比用户输入的信息是否合法,从而判断是否登录成功
private boolean login(String userName,String password){
//////////////
return true;
}
对于,同一时间同一账户可以在两处乃至三处登录的处理类似上面的处理流程,可以建个队列来实现先进先出。
前提都是用session监听器,对session的创建与销毁进行监听
一、在用户登录时保存该用户的状态有这几种保存方式:
1、保存到内存中(application ,servletcontext ,个人也是推荐这种方式)
2、保存状态到数据库,至于具体的怎么保存你可以随意返回,如:0,1两种状态
3、保存到文件中,对文件的读写
以上是登录用户的状态,这对于大家来说都没有什么问题。
二、 这时如果同一用户登录了,你可以在登录成功后(保存信息之前)进入到上面的状态 中进行匹配判断,如果存在就提醒此用户你的账号已登录。
三、关键在于该用户的销毁
invliate(),调用这个方法,通过Session的监听器,进行对当前用户的删除。
Session过期,也会调用Session监听器。
讨论最多的就是在比如用户没有自己去注销session.invalidate()方法,而是直接关闭了 浏览器,这时怎么办?(浏览器关闭半个小时候,默认注销session,监听器这时才调用sessionDestroyed方法)。
首先要明确的一点,用户关闭浏览器,服务器端是无法得知的(因为web客户浏览器与服务器之间是无状态的),网上也有一些解决方案,比如通过js来判断用户是否关闭了浏览器,是的次方法可行,但是如果用户操作时,打开了多个窗口呢,这里也有方法:
1、一个方法还是比较好的,通过cokkie保存当前用户开了的页面数,如果页数为一的话,就可以触发js的注销Session了。
2、先把Session的生命期设置的短一点,用类似ajax这种异步请求方式周期不断的去请求后台,这样可以保证当前的这个Session有效,如果用户退出后,该Session也会很快的过期。
上面的两种方式都有些缺陷,如:
1、用户删除cokkie的话,就无法判断准确,这种可能应该不多吧(在访问当前网站时)
2、有延迟,服务器压力相对来说比较大
还有一种方式与上面的思考角度不一样(当然也要看需求了),如果有用户登录时,就注销之前已登录的同一用户。
实现方式与上面应该是差不多的,唯一不同之处在于,不用去刻意的想办法让用户退出了(注销Session)。
四、虽然像百度,CSDN等这些网站都没有这样做,当然也没有必要这要这样做。
但是在我们做企业内部应用的时候有时候可能会要求我们这样做(同一账号在统一时间只能在一个登录),下面是个例子
我们先定义两个Map对象需要用到,存放用户与HttpSession的关系和sessionId与用户的关系。用来记录当前登录的用户是否登录和当前session是否已经绑定了登录用户。
[java] view
plain copy
/**
* 用户和Session绑定关系
*/
public static final Map<String, HttpSession> USER_SESSION=new HashMap<String, HttpSession>();
/**
* seeionId和用户的绑定关系
*/
public static final Map<String, String> SESSIONID_USER=new HashMap<String, String>();
然后我们需要实现HttpSessionListener接口监听,主要是监听session的销毁事件。
[java] view
plain copy
public void sessionDestroyed(HttpSessionEvent se) {
String sessionId=se.getSession().getId();
//当前session销毁时删除当前session绑定的用户信息
//同时删除当前session绑定用户的HttpSession
USER_SESSION.remove(SESSIONID_USER.remove(sessionId));
}
接下来是关键,处理登录用户的唯一。
当用户登录进来的时候我们先把当前HttpSession绑定的用户和用户绑定的HttpSession关系删除。
再次我们删除当前登录的用户绑定的HttpSession关系,如果当前用户已经登录删除session和用户的关系、删除session中用户的信息、设置说明用户被挤下线了。
[java] view
plain copy
/**
* 用户登录时的处理
* 处理一个账号同时只有一个地方登录的关键
* @param request
*/
public static void userLoginHandle(HttpServletRequest request){
//当前登录的用户
String userName=request.getParameter("userName");
//当前sessionId
String sessionId=request.getSession().getId();
//删除当前sessionId绑定的用户,用户--HttpSession
USER_SESSION.remove(SESSIONID_USER.remove(sessionId));
//删除当前登录用户绑定的HttpSession
HttpSession session=USER_SESSION.remove(userName);
if(session!=null){
SESSIONID_USER.remove(session.getId());
session.removeAttribute("userName");
session.setAttribute("userMsg", "您的账号已经在另一处登录了,你被迫下线!");
}
}
用户登录的请求处理。先判断用户输入的登录信息是否合法,在判断用户输入的信息是否正确(登录是否成功),成功则调用单用户登录的处理方法,把当前登录的用户和当前session关联,session中保持当前登录用户的信息
[java] view
plain copy
/**
* 用户登录
*/
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String userName=request.getParameter("userName");
String password=request.getParameter("password");
if(userName!=null&&!"".equals(userName.trim())){
//登录成功
if(login(userName, password)){
HttpSession session=request.getSession();
//处理用户登录(保持同一时间同一账号只能在一处登录)
userLoginHandle(request);
//添加用户与HttpSession的绑定
USER_SESSION.put(userName.trim(), session);
//添加sessionId和用户的绑定
SESSIONID_USER.put(session.getId(), userName);
session.setAttribute("userName", userName);
session.removeAttribute("userMsg");
}
}
response.sendRedirect("index.jsp");
}
//对比用户输入的信息是否合法,从而判断是否登录成功
private boolean login(String userName,String password){
//////////////
return true;
}
对于,同一时间同一账户可以在两处乃至三处登录的处理类似上面的处理流程,可以建个队列来实现先进先出。
相关文章推荐
- Asp.net 实现只能允许一个账号同时只能在一个地方登录
- Asp.net 实现只能允许一个账号同时只能在一个地方登录
- php 实现同一个账号同时只能一个人登录
- php 实现同一个账号同时只能一个人登录
- 一个很简单的demo来演示一个账号只能同时被一个人使用(Java实现)
- asp.net mvc 简单实现一个账号只能在一个地方登录
- 保证同一个账号同时只能在一个设备上登录
- javaweb实现一个账号只能同时被一个人使用(Java实现)
- 2.如何让一个项目的用户目前只能是姓名登录,优化为增加一个字段为姓名和用户名同时都可以实现登录 ,并且用户名不能使中文?
- asp.net 使用application实现单点登录(一个账号只能在一个地方登录)
- 如何保证同一个账号同时只能在一个设备登录,账号自动登录
- java 实现 一个账号只能在一个地方登陆,其他地方被下线
- 用PHP实现同一个帐号不允许同时登陆,只允许一个帐号登录?
- Java+MySql+Servlet+Ajax实现单态登陆,说白了就是一个账号只能在一个浏览器中登陆。
- 限制一个账号同时只能在一处登陆
- SpringSecurity3.1.2控制一个账户同时只能登录一次
- 如何处理多人同时登录同一个账号以及如何统计在线人数和访问量?
- 用PHP实现同一个帐号不允许同时登陆,只允许一个帐号登录?
- 如何创建一个只允许使用sftp登录且只能访问特定目录的账号
- java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)