简单的防止重复登录实现
这个实现利用的是struts2的拦截器,大家也可以试着用filter+servlet来实现,原理都是一样的。
memcache的安装与拦截器的配置可以在我的文章里找到,我就不赘述了。
首先我们看下思路:
?我们看到多台web服务器共享一台memcache服务器,这个memcache就是存储用户登录信息的作用。
在memcached中以map(key,value)形式存储数据,我们就可以用登录名作key,每一个浏览器访问节点的sessionId作value,用户登录更新对应登录名的sessionId,这样用户在做与服务器通信的操作时查询一次memcache看其中存储的sessionId是不是与自己的对应,不对应就说明已经有人再另一个地方登陆了,这时就可以把此用户踢掉了。这个原理比较简单,仔细想想就明白了。
下面是一段登录的代码
// 用户名String usrName = request.getParameter(Constants.USER_NAME);// 密码String passwd = request.getParameter(Constants.USER_PASSWD);// 请求的类型String method = ServletActionContext.getRequest().getMethod();boolean isGet = "GET".equalsIgnoreCase(method);// 如果为GET// 如果是地址栏输入网址提交if (isGet)throw new LoginException("-1053");// 禁止get方式登录// 判断是否输入了用户名,密码if (StringUtils.hasText(usrName) && StringUtils.hasText(passwd)) {// 验证登陆boolean loginSuccess = loginService.login(usrName, passwd);// 登录成功if (loginSuccess) {// 存储登录信息至memcacheboolean putSuccess = MemcacheHelper.setMap(usrName, request.getSession().getId());if (putSuccess) {request.setAttribute(Constants.SUCCESS, "SUCCESS");request.setAttribute(Constants.PATH, path);return SUCCESS;} else {throw new LoginException("-1011");// 登录失败,请重试}}}throw new LoginException("-1001");// 用户名,密码必须输入!
?这段代码比较简单,就是把新登录的sessionId放到memcache里替换前面的。
关键在于连接器中对于sessionId的比对,拦截器代码:
// 此处去memcache查是否是正在使用用户String sessionId = (String) MemcacheHelper.getValue(user.getLoginName());String thisSessionId = request.getSession().getId();logger.debug("从memcache取值,session值:" + sessionId);/** 判断memcache是否有值 */if (!StringUtils.hasText(sessionId)) {logger.error("查询memcache失败");request.getSession().invalidate();// 返回登录页面if (isAjax) {response.sendError(1011, "登录信息获取失败,请重新登录");response.flushBuffer();} elsethrow new LoginException("-1011");}/** 判断服务器session是否有值 */if (!StringUtils.hasText(thisSessionId)) {logger.error("服务器登录信息获取失败");request.getSession().invalidate();if (isAjax) {response.sendError(1011, "登录信息获取失败,请重新登录");response.flushBuffer();} elsethrow new LoginException("-1011");}/** 当memcache中存储登录用户与此用户对应正确时 */if (!sessionId.equals(thisSessionId)) {logger.error("该用户已在其他地点登录");request.getSession().invalidate();if (isAjax) {response.sendError(1010, "该用户已在其他地点登录");response.flushBuffer();} elsethrow new LoginException("-1010");}
?判断memcache里存的值是不是该用户的,不是就踢了@_@
?