这个话题网上有了很多种做法,数据库里设字段、session记录等。但没有能完美解决问题的,问题关键在于网页关闭时如何使其登录状态为null,强制关闭浏览器,截任务管理器线程、意外客户端断电等,无法捕捉。
可以使用页面刷新向服务器发请求?服务器负荷会不会高?
另外我使用的是iframe框架,怎么进行定时刷新,谁有完整的代码(包括登录时设置无法重复登录,页面定时刷新,浏览器关闭时置登录状态为null)
可以使用页面刷新向服务器发请求?服务器负荷会不会高?
另外我使用的是iframe框架,怎么进行定时刷新,谁有完整的代码(包括登录时设置无法重复登录,页面定时刷新,浏览器关闭时置登录状态为null)
js里面有一个onunload事件,页面关闭的时候触发,在onunload事件中可以用ajax跟后台交互。
http://blog.csdn.net/java2000_net/archive/2011/06/22/6560509.aspx
唯一的方法是,写浏览器插件,浏览器客户端下载插件并安装后,该插件在客户端电脑开端口,定时向服务器端口发送数据证明其存在。服务器端判定,如果超过某些时间,未收到指定客户端的信息,则自动认为该客户端已关闭。
这种单点登陆的问题,很多地方都有实现,而且并不是楼上所说,各大网站都未实现。我在做产品时就遇到这个问题,交给C++开发人员写个ActiveX或ocx控件,完美实现。
http://blog.csdn.net/zxingchao2009/archive/2011/03/24/6274378.aspx
1 登录时,生成一个唯一的标识,然后和用户名关联。 标识保存到session或者cookie里面,用于下次访问。
2 下次访问时,判断标识与用户名关联的是否一样,如果不一样则判断重复登录了,本session自动注销。
<http>
...
<session-management>
<concurrency-control max-sessions="1" />
</session-management>
</http>
这是文档上说的,但我把其中的spring-security-core.jar以及spring-security-web.jar加入项目后,拿它的application-security.xml配置修改,但没成功。
18楼上说的“不要限制新登录的,而是让新登录的,把老的顶下去就行了。”还有你的思路能贴下代码么?
public class SignonFilter implements Filter {
private FilterConfig filterConfig; private String login_page = UserList.LOGIN_PAGE; public void destroy() {
this.filterConfig = null; } public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
//获取当前用户
SysUsersAssociators userVo = LoginHelper.getLoginVo((HttpServletRequest)request);
String servletPath= req.getServletPath();
String isGuest = new String();
if((String)req.getSession().getAttribute("guest")==null)
{
isGuest = "yes"; //前台用户登录 不需要单点控制 }
else
{
isGuest = "no"; //需要单点控制 }
//如果isGuest 为yes表示其为普通用户 if ((userVo!=null&&!userVo.getUsersAssId().equals("")) //登录页和登录action不判断 || servletPath.equals( "/" +"userAss.do")||servletPath.equals( "/" +"landing.jsp")||servletPath.equals( "/" +"loginout.jsp")
||isGuest.equals("yes"))
{
chain.doFilter(req, res);
} else {
String url = req.getContextPath() + "/" + login_page;
//返回主页面
res.setContentType("text/html;charset=GBK");
PrintWriter out = res.getWriter();
out.write("<script language=\"javascript\">\r\n");
out.println("alert('登录超时或该用户在别处登录,请您重新登录!');window.location.href =\"" + url + "\";");
out.write("</script>");
//返回当前页时使用。 // res.sendRedirect(url);
}
} public void init(FilterConfig config) throws ServletException {
this.filterConfig = config;
}
}
后来挤掉先前的:与用户关联一个sessonid的字段, 就是每次与服务器交互判断与服务器记录的session是否相同,不同就重新登录新的session替换原来的限制登录:与用户关联一个sessionid字段和时间字段,每次与服务器交互判断与服务器记录的sessionid是否相同,相同就把当前时间更新的时间字段,不同并且当前时间与系统存的时间在一定时间内(比如5分钟)就返回不让登录,如果系统sessionid和时间字段是空,就让登录。 另外在关闭网页事件上尽量控制清空sessionid和时间字段。 -------------此方法就是突然断电或者关闭进程5分钟内无法登录。
比喻用户admin
A君登陆了 那么就是自动生成admin1
B君登陆了 那么就生成admin2这样 可以限制一个账号同时登陆的个数 可以自己定2. 采用自制web框架,直接在浏览器中弹出新框架,给框架分配ID标识,最先得到标识的人可以登陆但是这个是你自己定
简单吧
1、A同志登录的时候 生成一串Guid标识 对应 用户名 放到 字典中(字典需要做成单例或者放到Cache中,这样每个人访问的才会是同一个对象,且Guid和用户名是一一对应的) ,这个时候 字典 中就存在了A用户的 一个登录票据Token,这个票据同时要保存一份到Session中。
2、B同志使用了和A同志同一个账号登录的时候,又生成了一串Guid标识 ,先到字典中根据用户名查找出对应的Guid标识,是否和B同志新生成的Guid标识对应,这里肯定是不会对应了,那么将旧的Guid删除,替换上新的Guid3、脚本派上用场了,在浏览器端做个Ajax轮询,具体要设置成几秒要看服务器压力了,这个轮询的主要目的就是要去检查 当前登录票据和在字典中的票据是否一致。这里模拟一下踢出的过程,这时A的浏览器会定时发出验证操作,去验证存储在Session中的票据的Guid 是否和字典中的票据是否一致,如果不一致了,被B给更新了,不一致的话,就把Session注销,完事!如果一致,就什么事都不做
先检查,如果存在就更新,不存在就添加,浏览器做ajax轮询验证
<filter>
<filter-name>sso</filter-name>
<filter-class>com.xxxx.util.SSO.SignonFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sso</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>sso</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<!-- 设置单点监听 -->
这是登录要做的事情,用户id绑定seesionId放入到applicatio中
application的生命周期是从服务器启动到服务器关闭ServletContext application = request.getSession().getServletContext(); //获取服务器对象
application.setAttribute(sua.getUsersAssId(),request.getSession().getId()); //用户id和其sessionid绑定
application.setAttribute("associators_info", sua); //用户登录放入服务器
session.setAttribute("guest","no"); //表示不是前台用户 受单点控制这个解决方案目前的缺点就是集群服务器下无效,楼主切记
application.setAttribute(用户id,账号,request.getSession().getId()); //用户id和其sessionid绑定
对于楼主的这个问题我不大清楚你需要什么样的效果,但是不管什么样的页面效果跳转也好,弹出也罢无非都是些js去操作,楼主请注意看这
String url = req.getContextPath() + "/" + login_page;
//返回主页面
res.setContentType("text/html;charset=GBK");
PrintWriter out = res.getWriter();
out.write("<script language=\"javascript\">\r\n");
out.println("alert('登录超时或该用户在别处登录,请您重新登录!');window.location.href =\"" + url + "\";");
out.write("</script>");
你当前要实现的页面效果以JS输出就OK了
“单点登录”的概念说的是,多个相关系统,登录其中一个后,再访问其他系统就不需要登录了。几个系统可以共享session。而不是这里讨论的这个问题吧。
可以加过滤器,在过滤器中判断未登录或是登录失效的,就跳转到一个中间页面。该页面就一句js脚本。
top.location="/**/login.htm";
这样中间页面先在iframe中存在,执行完脚本,主页面就跳到登录页面了。需要注意的是,如果过滤器拦截的是ajax发出的请求,该方法无效,需要单独处理。
回头我想了想,有时候你在用一些应用的时候,掉线了暂时上不去或者提示你用户正在线,也说明其实是实现思路跟这个都差不多。
希望对你有帮助··
1.使用session listener通知登录和登出,并进行帐号和sessionid之间的管理,建一个usermanagerment(问题:负载均衡时怎么办?放数据库中?)
2.页面关闭方法onunload中使用ajax通知服务器(问题:其他关闭情况怎么办?使用一个固定的页定时用ajax向服务器发送活动消息,并设置定时时间和判断超时时间)
3.限制同一个人重复登录,像csdn这样二周不用登录,使用cookie(如spring security所说,不要放用户和密码,最后时加密后留存到数据库中,把加密后的东西写到session中.)
4.是否踢出前一个,默认不踢出,可配置为踢出。不踢出时要有机制可以通知业务操作管理员投诉或取消锁定(另加功能呀)
不知可以否?
1 在数据库中保持每个用户的登录状态。这个我觉得可以保证一个用户在任何时候只能有一个人登录,但是有一个弊端,不知道怎样保证这个用户在另外一台机器上登录,然后把原来登录的机器自动下线。
2 判断session。这个只能保证同一用户在同一台机器上登录一次。
登录的时候,检查memcache中有无此用户登录状态,如果已经登录,就提示已经登录。
如果没有,就登录进去,然后在memcache里记下状态,再设置超时时间,一般一分钟就可以了。
唯一的缺点:上一个登录用户意外退出,有可能一分钟以后才可以再登录进去。
我在研究security的时候也是考虑到这个问题,security里面也提供里两种方式,一种是前者进去后者不能进,一种是前者进,后者把前者给挤出去,第二种方法才是王道,第一种方法security也不能完美解决,意外情况是不能捕捉到的,简单的说下security对于session的控制,他会在登录时候把session存到一个库里面,然后供验证匹配,大概思路就是这样,具体可以来我的博客参考我对security的研究
//注册身份令牌,uid参数是用户的账号
WebApplication1.Classes.TokenManagement.Register(uid, token);
HttpCookie tokenCookie = new HttpCookie("passport");
tokenCookie.Values.Add("uid", uid);
tokenCookie.Values.Add("token", token);
http://www.jjski.net
地址:http://blog.csdn.net/chenghui0317/article/details/9373345