Session会话
session Session:在计算机中,尤其是在网络应用中,称为“会话”。 Session直接翻译成中文比较困难,一般都译成时域。在计算机专业术语中,Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间。 具体到Web中的Session指的就是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。因此从上述的定义中我们可以看到,Session实际上是一个特定的时间概念。 需要注意的是,一个Session的概念需要包括特定的客户端,特定的服务器端以及不中断的操作时间。A用户和C服务器建立连接时所处的Session同B用户和C服务器中建立连接时所处的Sessions是两个不同的Session。 那什么是Session的解决方案呢?我们知道,用户访问一个网站时往往需要浏览许多网页。对于一个通过PHP构筑的网站来说,用户在访问的过程中需要执行许多的PHP脚本。然而由于HTTP协议自身的特点,用户每执行一个PHP脚本都需要和Web服务器重新建立连接。 又由于无状态记忆的特点,此次连接无法得到上次连接的状态。这样,用户在一个PHP脚本中对一个变量进行了赋值操作,而在另外一个PHP脚本中却无法得到这个变量的值。例如,用户在负责登录的PHP脚本中设置了$user="wind",却无法在另一个PHP脚本中通过调用$user来获得“wind”这个值。也就是说,在PHP中无法设置全局变量。每个PHP脚本中所定义的变量都是只在这个脚本内有效的局部变量。 Session解决方案,就是要提供在PHP脚本中定义全局变量的方法,使得这个全局变量在同一个Session中对于所有的PHP脚本都有效。上面我们提到了,Session不是一个简单的时间概念,一个Session中还包括了特定的用户和服务器。因此更详细地讲,在一个Session定义的全局变量的作用范围,是指这个Session所对应的用户所访问的所有PHP。 例如A用户通过Session定义了一个全局变量$user=“wind”中,而B用户通过Session定义的全局变量$user=“jane”。那么在A用户所访问的PHP脚本中,$user的值就是wind。 在ASP和ASP.NET中 Session是用于保持状态的基于Web服务器的方法。Session允许通过将对象存储在Web服务器的内存中在整个用户会话过程中保持任何对象。 Session通常用于执行以下操作: 存储需要在整个用户会话过程中保持其状态的信息,例如登录信息或用户浏览Web应用程序时需要的其它信息。 存储只需要在页重新加载过程中或按功能分组的一组页之间保持其状态的对象。 Session的作用就是它在Web服务器上保持用户的状态信息供在任何时间从任何页访问。因为浏览器不需要存储任何这种信息,所以可以使用任何浏览器,即使是像PDA或手机这样的浏览器设备。 此持久性方法的限制 随着越来越多用户登录,Session所需要的服务器内存量也会不断增加。 访问Web应用程序的每个用户都生成一个单独的Session对象。每个Session对象的持续时间是用户访问的时间加上不活动的时间。 如果每个Session中保持许多对象,并且许多用户同时使用Web应用程序(创建许多Session),则用于Session持久性的服务器内存量可能会很大,从而影响了可伸缩性。 在JSP中 Jsp的session是使用bean的一个生存期限,一般为page,session意思是在这个用户没有离开网站之前一直有效,如果无法判断用户何时离开,一般依据系统设定,tomcat中设定为30分钟. 我们使用seesion功能,可以达到多个jsp程序从操作同一个javabean,那么这个javabean可以作为我们传统意义上的"全局变量池".(在java中我们可以使用static静态化一个变量和方法,使用singleton唯一化对象.) 在项目实践中,我们Jsp程序中很多参数需要从数据库中读取,有的参数实际读取一次就可以,如果设计成每个用户每产生一个页面都要读取数据库,很显然,数据库的负载很大,同时也浪费时间,虽然可能有数据库连接池优化,但是尽量少使用数据库是我们编程的原则. [编辑本段]php中的session使用详解 在PHP开发中对比起Cookie,session是存储在服务器端的会话,相对安全,并且不像Cookie那样有存储长度限制,本文简单介绍session的使用。 由于Session是以文本文件形式存储在服务器端的,所以不怕客户端修改Session内容。实际上在服务器端的Session文件,PHP自动修改session文件的权限,只保留了系统读和写权限,而且不能通过ftp修改,所以安全得多。PHPChina开源社区门户 对于Cookie来说,假设我们要验证用户是否登陆,就必须在Cookie中保存用户名和密码(可能是md5加密后字符串),并在每次请求页面的时候进行验证。如果用户名和密码存储在数据库,每次都要执行一次数据库查询,给数据库造成多余的负担。因为我们并不能只做一次验证。为什么呢?因为客户端Cookie中的信息是有可能被修改的。假如你存储$admin变量来表示用户是否登陆,$admin为true的时候表示登陆,为false的时候表示未登录,在第一次通过验证后将$admin等于true存储在Cookie,下次就不用验证了,这样对么?错了,假如有人伪造一个值为true的$admin变量那不是就立即取的了管理权限么?非常的不安全。 而Session就不同了,Session是存储在服务器端的,远程用户没办法修改session文件的内容,因此我们可以单纯存储一个$admin变量来判断是否登陆,首次验证通过后设置$admin值为true,以后判断该值是否为true,假如不是,转入登陆界面,这样就可以减少很多数据库操作了。而且可以减少每次为了验证Cookie而传递密码的不安全性了(session验证只需要传递一次,假如你没有使用SSL安全协议的话)。即使密码进行了md5加密,也是很容易被截获的。 当然使用session还有很多优点,比如控制容易,可以按照用户自定义存储等(存储于数据库)。我这里就不多说了。 session在php.ini是否需要设置呢?一般不需要的,因为并不是每个人都有修改PHP.ini的权限,默认session的存放路径是服务器的系统临时文件夹,我们可以自定义存放在自己的文件夹里,这个稍后我会介绍。 开始介绍如何创建session。非常简单,真的。 启动session会话,并创建一个$admin变量: //启动session session_start(); //声明一个名为admin的变量,并赋空值。 $_session["admin"]=null; ?> 如果你使用了Seesion,或者该PHP文件要调用Session变量,那么就必须在调用Session之前启动它,使用session_start()函数。其它都不需要你设置了,PHP自动完成session文件的创建。 执行完这个程序后,我们可以到系统临时文件夹找到这个session文件,一般文件名形如:sess_4c83638b3b0dbf65583181c2f89168ec,后面是32位编码后的随机字符串。用编辑器打开它,看一下它的内容: admin|N; 一般该内容是这样的结构: 变量名|类型:长度:值; 并用分号隔开每个变量。有些是可以省略的,比如长度和类型。 我们来看一下验证程序,假设数据库存储的是用户名和md5加密后的密码: //表单提交后... $posts=$_POST; //清除一些空白符号 foreach($postsas$key=>$value) { $posts[$key]=trim($value); } $password=md5($posts["password"]); $username=$posts["username"]; $query="SELECT`username`FROM`user`WHERE`password`='$password'"; //取得查询结果 $userInfo=$DB->getRow($query); if(!empty($userInfo)) { if($userInfo["username"]==$username) { //当验证通过后,启动session session_start(); //注册登陆成功的admin变量,并赋值true $_session["admin"]=true; } else { die("用户名密码错误"); } } else { die("用户名密码错误"); } 我们在需要用户验证的页面启动session,判断是否登陆: //防止全局变量造成安全隐患 $admin=false; //启动会话,这步必不可少 session_start(); //判断是否登陆 if(isset($_SESSION["admin"])&&$_session["admin"]===true) { echo"您已经成功登陆"; } else { //验证失败,将$_session["admin"]置为false $_session["admin"]=false; die("您无权访问"); } ?> 是不是很简单呢?将$_session看成是存储在服务器端的数组即可,我们注册的每一个变量都是数组的键,跟使用数组没有什么分别。 如果要登出系统怎么办?销毁session即可。 session_start(); //这种方法是将原来注册的某个变量销毁 unset($_session["admin"]); //这种方法是销毁整个session文件 session_destroy(); > Session能否像Cookie那样设置生存周期呢?有了Session是否就完全抛弃Cookie呢?我想说,结合Cookie来使用session才是最方便的。 Session是如何来判断客户端用户的呢?它是通过SessionID来判断的,什么是SessionID,就是那个Session文件的文件名,SessionID是随机生成的,因此能保证唯一性和随机性,确保Session的安全。一般如果没有设置Session的生存周期,则SessionID存储在内存中,关闭浏览器后该ID自动注销,重新请求该页面后,重新注册一个sessionID。 如果客户端没有禁用Cookie,则Cookie在启动Session会话的时候扮演的是存储SessionID和session生存期的角色。 我们来手动设置session的生存期: session_start(); //保存一天 $lifeTime=24*3600; setcookie(session_name(),session_id(),time()+$lifeTime,"/"); ?> 其实Session还提供了一个函数session_set_cookie_params();来设置Session的生存期的,该函数必须在session_start()函数调用之前调用: //保存一天 $lifeTime=24*3600; session_set_cookie_params($lifeTime); session_start(); $_session["admin"]=true; ?> 如果客户端使用IE6.0,session_set_cookie_params();函数设置Cookie会有些问题,所以我们还是手动调用setcookie函数来创建cookie。 假设客户端禁用Cookie怎么办?没办法,所有生存周期都是浏览器进程了,只要关闭浏览器,再次请求页面又得重新注册Session。那么怎么传递SessionID呢?通过URL或者通过隐藏表单来传递,PHP会自动将sessionID发送到URL上,URL形如:http://www.openphp.cn/index.php?PHPSESSID=bba5b2a240a77e5b44cfa01d49cf9669,其中URL中的参数PHPSESSID就是SessionID了,我们可以使用$_GET来获取该值,从而实现sessionID页面间传递。 //保存一天 $lifeTime=24*3600; //取得当前session名,默认为PHPSESSID $sessionName=session_name(); //取得sessionID $sessionID=$_GET[$sessionName]; //使用session_id()设置获得的sessionID session_id($sessionID); session_set_cookie_params($lifeTime); session_start(); $_session["admin"]=true; ?> 对于虚拟主机来说,如果所有用户的Session都保存在系统临时文件夹里,将给维护造成困难,而且降低了安全性,我们可以手动设置Session文件的保存路径,session_save_path()就提供了这样一个功能。我们可以将session存放目录指向一个不能通过Web方式访问的文件夹,当然,该文件夹必须具备可读写属性。 //设置一个存放目录 $savePath="./session_save_dir/"; //保存一天 $lifeTime=24*3600; session_save_path($savePath); session_set_cookie_params($lifeTime); session_start(); $_session["admin"]=true; ?> 同session_set_cookie_params();函数一样,session_save_path()函数也必须在session_start()函数调用之前调用。 我们还可以将数组,对象存储在session中。操作数组和操作一般变量没有什么区别,而保存对象的话,PHP会自动对对象进行序列化(也叫串行化),然后保存于session中。下面例子说明了这一点: classperson { var$age; functionoutput(){ echo$this->age; } functionsetAge($age){ $this->age=$age; } } ?> setage.PHP session_start(); require_once"person.PHP"; $person=newperson(); $person->setAge(21); $_session['person']=$person; echo"checkheretooutputage"; ?> output.PHP //设置回调函数,确保重新构建对象。 ini_set('unserialize_callback_func','mycallback'); functionmycallback($classname){ $classname.".PHP"; } session_start(); $person=$_session["person"]; //输出21 $person->output(); ?> 当我们执行setage.php文件的时候,调用了setage()方法,设置了年龄为21,并将该状态序列化后保存在session中(PHP将自动完成这一转换),当转到output.php后,要输出这个值,就必须反序列化刚才保存的对象,又因为在解序列化的时候需要实例化一个未定义类,所以我们定义了以后回调函数,自动包含person.PHP这个类文件,因此对象被重构,并取得当前age的值为21,然后调用output()方法输出该值。 [编辑本段]asp中的session使用方法详解 Session是什么呢?简单来说就是服务器给客户端的一个编号。当一台WWW服务器运行时,可能有若干个用户浏览正在运正在这台服务器上的网站。当每个用户首次与这台WWW服务器建立连接时,他就与这个服务器建立了一个Session,同时服务器会自动为其分配一个SessionID,用以标识这个用户的唯一身份。这个SessionID是由WWW服务器随机产生的一个由24个字符组成的字符串,我们会在下面的实验中见到它的实际样子。 这个唯一的SessionID是有很大的实际意义的。当一个用户提交了表单时,浏览器会将用户的SessionID自动附加在HTTP头信息中,(这是浏览器的自动功能,用户不会察觉到),当服务器处理完这个表单后,将结果返回给SessionID所对应的用户。试想,如果没有SessionID,当有两个用户同时进行注册时,服务器怎样才能知道到底是哪个用户提交了哪个表单呢。当然,SessionID还有很多其他的作用,我们会在后面提及到。 除了SessionID,在每个Session中还包含很多其他信息。但是对于编写ASP或ASP.NET的程序与来说,最有用的还是可以通过访问ASP/ASP.NET的内置Session对象,为每个用户存储各自的信息。例如我们想了解一下访问我们网站的用户浏览了几个页面,我们可能在用户可能访问到每个的页面中加入: 通过以下这句话可以让用户得知自己浏览了几个页面: 可能有些有些读者会问:这个看似像是数组的Session(“..”)是哪里来的?需要我定义吗?实际上,这个Session对象是具有ASP解释能力的的WWW服务器的内建对象。也就是说ASP的系统中已经给你定义好了这个对象,你只需要使用就行了。其中Session(“..”)中的..就好像变量名称,Session(“..”)=$$中的$$就是变量的值了。你只需要写上句话,在这个用户的每个页面中都可以访问..变量中的值了。 其实ASP一共内建了7个对象,有Session、Application、Cookie、Response、Request、Server等。在其他的服务器端脚本语言如JSP、PHP等中也有其类似的对象,只是叫法或者使用方法上不太一样。 [编辑本段]ASPSession的功能的缺陷 目前ASP的开发人员都正在使用Session这一强大的功能,但是在他们使用的过程中却发现了ASPSession有以下缺陷: 进程依赖性:ASPSession状态存于IIS的进程中,也就是inetinfo.exe这个程序。所以当inetinfo.exe进程崩溃时,这些信息也就丢失。另外,重起或者关闭IIS服务都会造成信息的丢失。 Session状态使用范围的局限性:刚一个用户从一个网站访问到另外一个网站时,这些Session信息并不会随之迁移过去。例如:新浪网站的WWW服务器可能不止一个,一个用户登录之后要去各个频道浏览,但是每个频道都在不同的服务器上,如果想在这些WWW服务器共享Session信息怎么办呢? Cookie的依赖性:实际上客户端的Session信息是存储与Cookie中的,如果客户端完全禁用掉了Cookie功能,他也就不能享受到了Session提供的功能了。 鉴于ASPSession的以上缺陷,微软的设计者们在设计开发ASP.NETSession时进行了相应的改进,完全克服了以上缺陷,使得ASP.NETSession成为了一个更加强大的功能。 HIbernate中的Session Session是JAVA应用程序和Hibernate进行交互时使用的主要接口,它也是持久化操作核心API, 注意这里的Session的含义,它与传统意思上web层的HttpSession并没有关系,HibernateSession之与Hibernate,相当于JDBCConnection相对与JDBC。 Session对象是有生命周期的,它以Transaction对象的事务开始和结束边界 Session作为贯穿Hibernate的持久化管理器核心,提供了众多的持久化的方法,如save(),update,delete,find(Hibernate3中已经取消了此方法)等,通过这些方法我们可以透明的完成对象的增删改查(CRUD--createreadupdatedelete),这里所谓的透明是指,Session在读取,创建和删除影射的实体对象的实例时,这一系列的操作将被转换为对数据库表中数据的增加,修改,查询和删除操作。 Session有以下的特点 1,不是线程安全的,应该避免多个线程共享同一个Session实例 2,Session实例是轻量级的,所谓轻量级:是指他的创建和删除不需要消耗太多资源 3,Session对象内部有一个缓存,被称为Hibernate第一缓存,他存放被当前工作单元中加载的对象,每个Session实例都有自己的缓存。 org.hibernateInterfaceSession publicinterfaceSessionextendsSerializable:是一个Javaapplication和Hibernate之间主要的运行时接口,这是执行持久化服务的中心API 主要方法: publicTransactionbeginTransaction()throwsHibernateException:返回和当前Session对象相互联系的Transaction对象(表示在数据库中重新开始一个事务) publicTransactiongetTransaction():返回和当前session联系的Transaction对象 publicConnectionconnectionclose()throwsHibernateExcepton:结束当前的Session对象 publicvoidclear():清空Session,清除所有保存在当前Session缓存中的实体对象,终止所有正在执行的方法(eg:save(),update(),delete().....) publicSerializablesave(Objectobject)throwsHibernateException对当前参数指定的对象进行持久化(系统会首先赋予参数对象一个标识符OID),他相当于insert语句后面在详细介绍 publicConnectionconnection()throwsHibernateException得到当前Session中包含的Connection对象。 publicbooleancontains(Objectobject):判断参数给出的对象(持久化类)是否在当前Session的缓存中 publicvoidevict(Objectobject)throwsHibernateException:将参数给出的Object从当前Session对象类中删除,使这个对象从持久态变成游离态,这种状态的改变不会引起对数据库的同步,后面详细介绍 publicObjectload(Classtheclass,Serializableid)throwsHibernateException返回第一个参数指定类对应的表中,第二个参数指定的行(第二个参数就是要取得对象的OID,他对应表中主键列的值) publicvoidupdate(Objectobject)throwsHibernateException:更新一个对象到数据库中,后面在详细介绍 publicvoiddelete(Objectobject)throwsHibernateException:从数据库中删除和参数指定的对象对应的记录 publicObjectget(Classclass,Serializableid)throwsHibernateException:和load()方法一样区别在于,如果数据库表中没有对应的记录,get()方法返回null,load()方法将报异常 Transanction Transanction接口是Hibernate的数据库事务接口,用于管理事务,他对底层的事务作出了封装,用户可以使用Transanction对象定义自己的对数据库的原子操作,底层事务包括:JDBCAPI,JTA(JavaTransactionAPI)。。。。。 一个Transaction对象的事务可能会包括多个对数据库进行的操作 org.hibernateInterfaceTransaction publicinterfaceTransaction 常用方法: publicvoidcommit()throwsHibernateException刷新当前的Session以及结束事务的工作,这个方法将迫使数据库对当前的事务进行提交 publicvoidrollback()throwsHibernateException:强迫回滚当前事务 publicbooleanisActive()throwsHibernateException:这个事务是否存活 ---------------------------------------------------------------------------------------- Session:当中包含一个Connection对象 Connectionc=session.getConnection(); Session的缓存用于临时保存持久化的对象,等到一定时候,再将缓存中的对象保存到数据库中。 应用程序事务:如果一个Session中包含有多个Transaction(数据库事务),这些Transaction的集合称为应用程序事务 标准使用形式: Configurationconfig=newConfiguration().configure("hibernate.cfg.xml"); SessionFactorysessionfactory=config.buildSessionFactory(); Sessionsession=sessionfactory.openSession(); Transactiontx=session.beginTransaction(); try { session.save(); tx.commit(); } catch(Exceptione) { if(tx!=null)tx.rollback(); } finally { session.close(); } |