如何通过session控制单点登录

 web服务器为每一个浏览器实例对应一个session。这个session有自己的一个独立id,这个id保存在浏览器的cookie中(这个cookie貌似随着这个浏览器实例的关闭而清除),访问web服务器的时候,web服务会根据你cookie中的sessionId来决定重新创建一个session还是使用已经存在的session。
如果使用桌面的ie图标打开一个IE窗口,这个窗口属于一个新的浏览器实例(其中不包含sessionid信息),这时候用这个IE访问web服务器的时候web服务器会为这个浏览器实例新创建一个httpsession,sessionId也是新的(sessionId保存到本地的cookie中),不会对你以前打开的窗口中的session产生覆盖,关闭ie窗口的时候cookie中的信息也就清除掉了。 
如果是在打开的ie窗口中按“ctrl+n”打开一个ie窗口,这个窗口于刚才的窗口是同一个实例,与刚才的窗口共用session,所有的同一个ie实例的窗口都关掉后,会清除掉sessionId。

补充一点,可以通过人为的输入参数sessionId通知web服务器你使用的是哪个session(如果服务器存在这个session的话)。

*****************************************************************************************************************************************

单点登录(有别于SSO:Single Sign On),首先解释一下对项目需求中的单点登录的理解:一个用户帐号成功登录后,在该次session还未失效之前,不能在其他机器上登录同一个帐号,这有点类似与QQ只能在同一台计算机上登录。好了,如何实现呢?现在分析一下:一次登录也就是一次会话(Session),那么我们可以很容易联想到通过控制session来实现单点登录,我的设想是这样的,登录后将用户信息保存到session中,如果此时在另外一台机器上一个相同的帐号请求登录,通过遍历Web服务中所有session并判断其中是否包含同样的用户信息,通过这样的判断,在另一台机器上登录该帐号是不成功的。
上面已经提到了,需要通过控制session,对web服务中所有session进行遍历操作,那么你肯定会想到application这个大对象了(当然你也可以采用缓存或者数据库),具体实现方法是这样的,首先在application中创建一个List<HttpSession>,用来保存每一次会话(session)对象,系统在验证用户登录请求时,通过遍历该list并加以判断,最后决定是否让该用户成功登录。OK,需求和设计都在上面了,接下来就是编码工作了哈。不过在这里还需要考虑几个问题:
1、如果登录后关闭了浏览器,想立即打开一个新的浏览器并登录将会失败,因为前一次登录后的session还没销毁,你需要等其销毁后方可再次登录成功,这种问题如何解决???哈哈,你是不是已经想到要用javascript处理一下下,即在关闭浏览器的时候触发一个事件,该事件就是通知来销毁当前session的。
2、第二个问题其实是接上一个问题而讨论的,用javascript触发浏览器关闭事件并不是一个好办法,因为有很多因素可能导致这个事件触发不成功,还有Firefox和IE这两个东东意见有时候并不统一,最后有一个比较可恶的问题就是,我在同一台机器上不能打开两个浏览器窗口去登录相同的帐号,因为一个浏览器对应一个session啊!这就是为什么我在文章一开始要引用一些基本知识。
既然问题很严重,那就动脑壳去想办法啊!我在这里自言自语了半天,我不打算用中文继续讲下去了,直接code上场吧:
login.jsp
Html代码
<form action="verifyLogin.do" method="post" name="form">  
<table>  
<tr align="center">  
<td colspan="6" align="left"><fieldset STYLE='border:0;padding:14px;filter:glow(color=#0080ff,strength=3);letter-spacing:2px;'><font STYLE='font:12px/14px;color:#ffffff;font-weight:bold;'>请输入帐号和密码:</font></fieldset>  
</td>      
</tr>  
<tr>  <td align="right">用户名:</td>  <td><input type="text"  name="name" style="{ width: 100px;height: 15px;}" ></td>  <td align="right">&nbsp;&nbsp;码:</td>  <td><input type="password" name="pwd" style="{ width: 100px;height: 15px;}"></td>         <td>  
<%--    <select name="authority" size="1">--%>  
<%--      <option value="11">管理员</option>--%>  
<%--      <option value="00">普通用户</option>--%>  
<%--    </select>--%>  <input type="hidden" name="authority" value="11" >  </td>  
</tr>  
<tr align="center">  
<td colspan="6" align="center">  
<input name="" type="button" value="提&nbsp;&nbsp;&nbsp;&nbsp;交" onMouseOver="this.style.backgroundColor='red';" onMouseOut="this.style.backgroundColor='';" class="button" onClick="check()">&nbsp;&nbsp;&nbsp;&nbsp;   
<input name="" type="reset" value="重&nbsp;&nbsp;&nbsp;&nbsp;置" onMouseOver="this.style.backgroundColor='red';" onMouseOut="this.style.backgroundColor='';" class="button">  
</td>      
</tr>  
</table>  
</form>  
VerifyLogin类处理请求:
Java代码
String name=request.getParameter("name");   String pwd=request.getParameter("pwd");   String ip = request.getRemoteHost();   //String Ip=request.getRemoteAddr();   
  User user=UserHelp.getUserByName(name);   String err="";   if(user!=null){   if (user.getPwd().equals(pwd)){   //out.println("验证成功!");   boolean flag = true;   List<HttpSession> sessions = (List<HttpSession>)application.getAttribute("sessionlist");   for(int i = 0;i<sessions.size();i++){   HttpSession ses = null;   try{   ses = sessions.get(i);   User usr = (User)ses.getAttribute("user");   String cuip = (String)ses.getAttribute("remoteHost");   if(null!=usr&&usr.getName().equals(user.getName())&&!ip.equals(cuip)){//login repeatly!   flag = false;   err="<center><font color='red'>对不起该用户已经有人登录,您不能重复登录!</font></center><br><br>";   out.println(err);   break;   }   }catch(Exception e){   sessions.remove(i);   }   }   if(flag){   session.setAttribute("user",user);   session.setAttribute("remoteHost",ip);   sessions.add(session);   application.setAttribute("sessionlist",sessions);   }   if(flag&&user.getAuthority().equals("11")){   response.sendRedirect("manageFrames2.htm");   }   if(flag&&user.getAuthority().equals("00")){   response.sendRedirect("manageFrames1.htm");   }   }   else{   err="<center>密码错误,请重新登录!</center><br><br>";   out.println(err);   }   }   else{   err="<center>无此用户,请重新登录!</center><br><br>";     out.println(err);   }  

 

转载于:https://www.cnblogs.com/lr393993507/p/5231395.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/272292.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Syncd - 开源自动化部署工具

官网地址&#xff1a;https://gitee.com/dreamans/syncd/issues syncd是一款开源的代码部署工具&#xff0c;它具有简单、高效、易用等特点&#xff0c;可以提高团队的工作效率. 目前只支持类Linux系统. 特性 Go语言开发&#xff0c;编译简单、运行高效 Web界面访问&#xff0…

嵌入式C语言基础(二)

指针是分类型的&#xff1a; 指针根据类型不同&#xff0c;偏移值也不同。指针和数组&#xff0c;如何让指针指向数组&#xff1f; ①用数组名 &#xff1a;int array[10],int* p,parray ②用第一个元素的地址&#xff1a;int array[10],int* p,p&array[0] 注意&#xff1a…

Linus中帮助命令man

使用方法&#xff1a;man 可以查看想要使用命令的详细使用方法 man 命令

大牛是怎么思考设计SQL优化方案的?

作者&#xff1a;惨绿少年https://www.cnblogs.com/clsn/p/8214048.html在进行MySQL的优化之前&#xff0c;必须要了解的就是MySQL的查询过程&#xff0c;很多查询优化工作实际上就是遵循一些原则&#xff0c;让MySQL的优化器能够按照预想的合理方式运行而已。图-MySQL查询过程…

嵌入式C语言基础(三)

字符串的定义方式及输出&#xff1a; #include <stdio.h> #include <stdlib.h> void strPrint(char* data,int size) {int i;for(i0;i<size;i){printf("函数打印数组&#xff1a;%c\n",*data);}putchar(\n); } int main() {int i0;int a[3]{1,2,3};c…

web.config配置数据库连接

第一种&#xff1a;获取连接字符串 首先要定义命名空间 system.configuration 1. string connstr string constr ConfigurationManager.AppSettings["connstring"]; web.config文件:加在<appsettings>和</appsettings> 之间 <appsettings> <a…

用 Git 和 Github 提高效率的 10 个技巧!

Git 和 GitHub 都是非常强大的工具。即使你已经使用他们很长时间&#xff0c;你也很有可能不知道每个细节。我整理了 Git 和 GitHub 可能提高日常效率的10个常用技巧。GitHub1、快捷键: t 和 w在你的源码浏览页面&#xff0c;按 t 可以快速进入模糊文件名搜索模式&#xff1a;在…

docker显示镜像的摘要信息

显示镜像的摘要信息 docker images --digests

嵌入式C语言基础(四)

为什么要用结构体&#xff1f; 在实际问题中&#xff0c;一组数据往往具有不同的数据类型。例如&#xff0c;在学生登记表中&#xff0c;姓名应为字符型;学号可为整型或字符型&#xff1b;年龄应为整型&#xff1b;性别应为字符型&#xff1b;成绩可为整型或实型。显然不能用一…

命令行分析java线程CPU占用

1.使用top命令找出占用cpu最高的JAVA进程pid号 2. 找出占用cpu最高的线程&#xff1a; top -Hp pid -d 1 -n 1 3. 打印占CPU最高JAVA进程pid的堆栈信息 jstack pid > /tmp/stacktrace.log 4. 把占CPU最高线程号码换算成16进制到stacktrace.log中寻找相应线程16进制值找到…

docker搜索镜像

docker search 要下载的 OFFICIAL 为ok的表示是官方镜像

C#操作HttpClient工具类库

using System; using System.Collections.Generic; using System.Net.Http; using System.Windows.Forms; using System.Configuration; using System.IO; using Newtonsoft.Json; namespace Dcflow { public class HttpHelper { //获取Configuration对象 public static string…

docker从仓库找镜像

docker search -s 数量 要下载的 数量表示仓库start数

bzoj 1911: [Apio2010]特别行动队 2011-12-26

1911: [Apio2010]特别行动队 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 892 Solved: 359[Submit][Status][Discuss] DescriptionInputOutputSample Input4 -1 10 -20 2 2 3 4 Sample Output9HINT Source _________________________________________ 很简单的动规方程&a…

嵌入式C语言基础链表

什么是链表&#xff1f; 链表其实就是一种数据结构&#xff0c;所谓的数据结构就是数据存放的思想。 数组、链表优缺点&#xff1a; 增加一个元素或者删除一个元素都很难&#xff0c;因为地址是连续的&#xff0c;删除一个元素可能会挪动多个元素&#xff0c;不灵活。但是对于链…

docker pull 从仓库拉取镜像

docker pull 要拉取的镜像名 等价于 docker pull 要拉取的镜像名:lastest 拉取固定的镜像&#xff1a;docker pull 要拉取的镜像名:版本号 省略lastest表设计就是拉取的最新的

理解js中的原型链,prototype与__proto__的关系

说到prototype&#xff0c;就不得不先说下new的过程。 我们先看看这样一段代码&#xff1a; 1<script type"text/javascript">2 var Person function () { };3 var p new Person();4</script>很简单的一段代码&#xff0c;我们来看看这个new究竟做了什…

C#抓取网页HTML内容

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Net; using System.Text; using System.IO; using System.Text.RegularExpressions; namespace Web { /// <summary> /// 公共方法类 /// </summary> p…

项目一感应垃圾桶(Wemos)

硬件材料&#xff1a; Wemos D1、SG90舵机、HC-SR04、杜邦线若干、蜂鸣器3.3V&#xff08;可有可无&#xff09; 软件材料&#xff1a; arduino IDE编译器、USB转串口驱动 Wemos D1&#xff1a; 特性&#xff1a; 基于ESP-8266EX及arduino做的一个融合arduino兼容&#xff0…