session 订阅
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。有关使用Session 对象的详细信息,请参阅“ASP应用程序”部分的“管理会话”。注意会话状态仅在支持cookie的浏览器中保留。 展开全文
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。有关使用Session 对象的详细信息,请参阅“ASP应用程序”部分的“管理会话”。注意会话状态仅在支持cookie的浏览器中保留。
信息
外文名
Session
应用学科
软件 网络通信
中文名
时域
属    性
用户与交互系统通信的时间间隔
sessionICE中间件自定义Session机制的远程监控系统
为了满足实时远程监测系统的需求,服务器需要实时监测客户端的连接状态。为此利用ICE中间件的优点设计了一种基于面向对象ICE中间件自定义Session机制的解决方案。 [1]  Session直接翻译成中文比较困难,一般都译成时域。在计算机专业术语中,Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间。以及如果需要的话,可能还有一定的操作空间。需要注意的是,一个Session的概念需要包括特定的客户端,特定的服务器端以及不中断的操作时间。A用户和C服务器建立连接时所处的Session同B用户和C服务器建立连接时所处的Session是两个不同的Session。session的工作原理:(1)当一个session第一次被启用时,一个独一的标识被存储于本地的cookie中。(2)首先使用session_start()函数,PHP从session仓库中加载已经存储的session变量。(3)当执行PHP脚本时,通过使用session_register()函数注册session变量。(4)当PHP脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session库中,这个路径可以通过php.ini文件中的session.save_path指定,下次浏览网页时可以加载使用。那什么是Session的解决方案呢?用户访问一个网站时往往需要浏览许多网页。Session的使用在不同的语言中的使用方法特点不尽相同。对于一个通过PHP构筑的网站来说,用户在访问的过程中需要执行许多的PHP脚本。然而由于HTTP协议自身的特点,用户每执行一个PHP脚本都需要和Web服务器重新建立连接。又由于无状态记忆的特点,此次连接无法得到上次连接的状态。这样,用户在一个PHP脚本中对一个变量进行了赋值操作,而在另外一个PHP脚本中却无法得到这个变量的值。例如,用户在负责登录的PHP脚本中设置了$user="wind",却无法在另一个PHP脚本中通过调用$user来获得“wind”这个值。也就是说,在一次HTTP请求中,PHP无法将已经赋值的参数传递给下一次http请求的脚本。因此,每个PHP脚本中所定义的变量都是只在本次HTTP请求内有效,本次HTTP请求结束,PHP就会释放掉这些为这些变量分配的内存。Session解决方案,就是要提供在PHP脚本中定义全局变量的方法,使得这个全局变量在同一个Session中对于所有的PHP脚本都有效。提到了,Session不是一个简单的时间概念,一个Session中还包括了特定的用户和服务器。因此更详细地讲,在一个Session定义的全局变量的作用范围,是指这个Session所对应的用户所访问的所有PHP。例如A用户通过Session定义了一个全局变量$user=“wind”中,而B用户通过Session定义的全局变量$user=“jane”。那么在A用户所访问的PHP脚本中,$user的值就是wind。 [1]  Session 是 用于保持状态的基于Web服务器的方法。Session允许通过将对象存储在Web服务器的内存中在整个用户会话过程中保持任何对象。Session通常用于执行以下操作存储需要在整个用户会话过程中保持其状态的信息,例如登录信息或用户浏览Web应用程序时需要的其它信息。存储只需要在页面重新加载过程中或按功能分组的一组页之间保持其状态的对象。Session的作用就是它在Web服务器上保持用户的状态信息供在任何时间从任何设备上的页面进行访问。因为浏览器不需要存储任何这种信息,所以可以使用任何浏览器,即使是像Pad或手机这样的浏览器设备。持久性方法的限制随着越来越多用户登录,Session所需要的服务器内存量也会不断增加。访问Web应用程序的每个用户都生成一个单独的Session对象。每个Session对象的持续时间是用户访问的时间加上不活动的时间。如果每个Session中保持许多对象,并且许多用户同时使用Web应用程序(创建许多Session),则用于 Session持久性的服务器内存量可能会很大,从而影响了可伸缩性。 [1] 
收起全文
精华内容
下载资源
问答
  • Session 千次阅读
    2018-07-07 21:03:07

    什么是Session

    当人们去医院就诊时,就诊病人需要办理医院的就诊卡,该卡上只有卡号,而没有其它信息。但病人每次去该医院就诊时,只要出示就诊卡,医务人员便可根据卡号查询到病人的就诊信息。Session技术就好比医院发放给病人的就医卡和医院为每个病人保留病例档案的过程。
    当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,其中,Session对象就相当于病历档案,ID就相当于就诊卡号。当客户端后续访问服务器时,只要将标识号传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之对应的Session对象为其服务。
    需要注意的是,由于客户端需要接收、记录和回送Session对象的ID,因此,通常情况下,Session是借助Cookie技术来传递ID属性的。

    验证码为什么要使用Session

    1. 验证码的生成和登录时验证码的校验 属于多次请求,request无法完成!

    2. Cookie是有大小和个数的限制的,Session存到服务器端的技术,没有大小和个数的限制.

    3. Cookie相对于Session来讲不安全.


    Session是与每个请求消息紧密相关的,为此,HttpServletRequest定义了用于获取Session对象的getSession()方法,该方法有两种重载形式,具体如下。

    public HttpSession getSession(boolean create)

    public HttpSession getSession()

    上面重载的两个方法都用于返回与当前请求相关的HttpSession对象。

    区别:


    第一个getSession()方法根据传递的参数来判断是否创建新的HttpSession对象,如果参数为true,则在相关的HttpSession对象不存在时创建并返回新的HttpSession对象,否则不创建新的HttpSession对象,而是返回null。


    第二个getSession()方法则相当于第一个方法参数为true时的情况,在相关的HttpSession对象不存在时总是创建新的HttpSession对象。

    要想使用HttpSession对象管理会话数据,不仅需要获取到HttpSession对象,还需要了解HttpSession对象的相关方法。

    HttpSession接口中定义的操作会话数据的常用方法。

    HttpSession接口中的常用方法

    方法声明功能描述
    String getId()用于返回与当前HttpSession对象关联的会话标识号
    long getCreationTime()返回Session创建的时间,这个时间是创建Session的时间与1970年1月1日00:00:00之间时间差的毫秒表示形式
    long getLastAccessedTime()返回客户端最后一次发送与Session相关请求的时间,这个时间是发送请求的时间与1970年1月1日00:00:00之间时间差的毫秒表示形式
    void setMaxInactiveInterval(int interval)用于设置当前HttpSession对象可空闲的以秒为单位的最长时间,也就是修改当前会话的默认超时间隔
    boolean isNew()判断当前HttpSession对象是否是新创建的
    void invalidate()用于强制使Session对象无效
    ServletContext getServletContext()用于返回当前HttpSession对象所属于的WEB应用程序对象,即代表当前WEB应用程序的ServletContext对象
    void setAttribite(String name,Object value)用于将一个对象与一个名称关联后存储到当前的HttpSession对象中
    String getAttribute()用于从当前HttpSession对象中返回指定名称的属性对象
    void removeAttribute(String name)用于从当前HttpSession对象中删除指定名称的属性

    小结常用的api:

    1. request.getSession(); // session的获取

    2. session.setAttribute(key,value);// session 存储数据

    3. session.getAttribute(key);// session 获取存储对应的数据

    4. session.invalidate(); // session对象销毁

    5. session.removeAttribute(key);// 将目标对象从session中移除

    Session的使用场景

    1. 保存购物车数据 
    2. 保存用户浏览器记录数据 
    3. 保存用户登录信息数据 

    4. 保存验证码  


    Session入门开发

    开发步骤分解

    1. 创建一个servlet: AServlet.java
    2. 通过ASequest对象获取session对象,保存相关数据
    3. 浏览器不关闭时,我们新建另一个servlet: BServlet.java

    4. Bservlet获取Aservlet保存的session数据

    代码实现:

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

            HttpSession   session = request.getSession();//  获取session实例api
            //  服务器端创建session 自动发送会话级别Cookie   JSESSIONID   value  : session.getId()
            //  存储数据  setAttribute
            session.setAttribute("heimasession","你好 session");//  服务器内存 session保存用户数据
            session.setAttribute("tom","你好 tom");//  服务器内存 session保存用户数据
            session.setAttribute("marry","你好 marry");//  服务器内存 session保存用户数据
            //  只要浏览器不关闭, 多次请求 可以获取唯一session对象,获取session 存储的值
            System.out.println("---session 保存数据完成。。。");

        }

    获取session存储数据
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            HttpSession session = request.getSession();//  获取session实例api
    //        if(jessionId==null){
    //            create
    //        }else {
    //            jessessionid== sessi.getId(){
    //                return session
    //            }else{
    //                create
    //            }
    //        }
            //   浏览器访问服务器 自动发送所有的cookie   request.getSession();
            //  判断 sessionId ==  JESSIONID VALUE是否相同  如果相同 :找到session对象
            //  如果  sessionId !=  JESSIONID VALUE  服务器端重新创建session对象
            //  获取session保存数据
            //  手动 代码销毁session对象
    //        session.invalidate();//  销毁session对象
            String heimasession = (String)session.getAttribute("heimasession");
            String tom = (String) session.getAttribute("tom");
            String marry = (String) session.getAttribute("marry");
            System.out.println("session value = "+heimasession+   "   "+tom+"    "+marry);
        }
        
    注意  浏览器不要关闭! 因为cookie丢失,找不到服务器端的session对象

    session默认销毁时间:30分钟!


    Session的生命周期

    session的创建

    session默认的时间

    session的销毁












    更多相关内容
  • 前端网络基础 - Session

    千次阅读 2022-03-09 18:53:44
    根据sid到session_store中查询是否有对应session let session = SESSION[sid] // 如果session_store没有对应session 或者 session_store有对应session,但是已经失效,则需要重新生成新的sid和session,并且需要重新...

    目录

    Cookie的安全性

    Cookie真的安全吗

    Cookie内容为什么不能是用户名和密码

    Session

    Session的实现

    session存储在内存中的优缺点

    session存储在数据库中的实践

    session存储在数据库中的优缺点

    session和cookie对比

    跨站请求与cookie禁用时的session


    Cookie的安全性

    cookie由于保存在浏览器端,即用户个人电脑上,所以非常容易受到各种恶意攻击,而导致用户cookie被盗用·,为此浏览器为cookie设置了一些安全属性来限制对于cookie的操作以及cookie的发送。

    • httponly
    • secure
    • samesite

    httponly限制了cookie只能用于HTTP请求时携带,而不能使用javascript操作,如document.cookie操作cookie,这样可以有效保护cookie不被XSS的注入js脚本盗取。

    secure限制了cookie只能用于HTTPS请求时携带,这样保护了cookie不会在网络中明文传输,即避免了网络传输被截获后,黑客可以直接得到明文cookie。

    samesite默认限制了cookie在大部分HTTP请求中只能用于同站发送,比如浏览器网页请求的:

    1. 服务器接口的IP地址和cookie的domain设置的IP地址相同,则cookie可以发送
    2. 服务器接口的域名和cookie的domain设置的域名相同,则cookie可以发送
    3. 服务器接口的域名是cookie的domain设置的域名的子域名,则cookie可以发送

    只有少部分情况时,比如a标签超链接跳转GET请求,form表单GET请求,这种导航跳转式的GET请求才可以跨站发送cookie。

    所以samesite可以有效保障cookie不会被跨站请求伪造CSRF利用。

    Cookie真的安全吗

    可能大家觉得cookie有了上面三个安全属性控制,已经很安全了,但其实不然,举个很容易理解的例子:

    小明去网吧上网,登录某网站,并手贱地勾选了七天免登录,使用完后,小明直接关闭了浏览器,而没有清除浏览器cookie缓存。

    然后,小王又使用了这台电脑,翻看了浏览器历史记录,然后点击了小明曾登录的网站,意外地发现可以免登录,且当前登录用户是小明,而小王又是一个程序员,他熟练地打开浏览器的cookie窗口,并发现了cookie中有类似于username和password的密文信息,于是它试着对username和password进行了破译,最终成功破译得到了明文的用户名和密码。

    上面这个例子,小明用户名密码的泄漏原因并非来自于网络上的攻击,而是来自于网络外的攻击,由于小明的不良使用习惯,对cookie没有安全意识,导致了cookie泄漏,而这里的cookie内容又是用户名密码,进一步增加了用户名密码泄漏的风险。

    所以,cookie不安全的根本原因是cookie将用户身份认证信息保存在了客户端主机上,而客户端主机没有像服务器主机一样的双重防护,即网络外的安全规范的人为操作 + 网络内的安全严谨的技术保障。虽然浏览器尽力在为客户端主机提供安全的技术保障,但是却无法强制每个用户都能进行安全规范的操作。

    Cookie内容为什么不能是用户名和密码

    上面例子中,cookie的内容是用户名和密码,那必然决定了服务器获取到cookie后会基于解析出的用户名和密码进行身份认证。这产生了两个严重的安全问题:

    • cookie有效期无意义
    • cookie可能被破译出明文的用户名和密码

    为什么cookie有效期无意义了呢?

    由于服务器是根据cookie解析出的用户名和密码进行身份认证的,所以有了cookie中的用户名和密码在任何时候都可以用于身份认证。

    另外浏览器端支持手动修改cookie有效期,这可能导致cookie有效期被篡改而长期有效。

    Cookie身份认证机制中,服务器端不需要记录生成cookie的有效期,cookie有效期的管理全权交给了浏览器,但是浏览器请求服务器时只会发送cookie内容,而不会发送cookie有效期属性,这导致了服务器无法验证cookie的有效期。

    Session

    那么如何基于Cookie进行安全的身份认证呢?

    首先,服务器不能将用户名和密码作为cookie交给浏览器保存,其次服务器需要记录生成cookie的有效期,不能依赖于浏览器管理cookie的有效期。

    所以基于Cookie,产生了Session身份认证技术。

    Session身份认证技术脱胎于Cookie,它主要是解决Cookie上述两个安全隐患,所以Session工作流程如下:

    1. 浏览器发送登录请求到服务器,服务器基于登录请求中的用户名和密码进行身份认证,认证成功后,将用户名和密码保存在服务器本地内存或硬盘上,并为其创造一个随机唯一串作为查询索引,我们将随机唯一串称为sessionid。
    2. 服务器将sessionid作为响应头中Set-Cookie的值交给浏览器保存
    3. 浏览器再次请求服务器,自动携带保存的cookie(即sessionid)到请求头Cookie中
    4. 服务器受到请求,解析出请求头Cookie值(即sessionid),并基于sessionid到本地内存或硬盘上查询对应的用户名和密码进行身份认证,认证成功,则继续业务处理。

    这里我们将保存在服务器端的用户登录状态数据称为session。

    可以分析出,浏览器端不再保存实际的登录状态数据,只是保存了一个无业务意义的随机串sessionid,所以Session技术的安全性要比Cookie强。

    sessionid的作用是,作为凭据交给浏览器端保存,解决了浏览器端cookie被破解后暴露出明文用户名密码的安全问题。sessionid还有一个作用就是,在服务器端,和session组成键值对,也可以理解为查找session的索引值。

    Session的实现

    Session技术实际上就是将登录状态数据从浏览器端转移到服务器端保存,即需要在服务器端考虑登录状态数据session的管理,具体管理行为可以参照浏览器端cookie的管理:

    • cookie的设置:浏览器自动将服务器HTTP响应set-cookie的值保存到内存或硬盘中,当cookie有效期为会话时,它将被缓存在内存中,当cookie有效期为指定时间时,它将被持久化在硬盘中。
    • cookie的获取:浏览器发送HTTP请求给服务器时,自动添加对应服务器域名domain和资源路径path下的,expires/max-age处于有效的,httpOnly,secure,samesite符合要求的cookie
    • cookie的清除:当cookie有效期到达后,浏览器自动清除它。

    所以服务器端也需要对session考虑以上管理行为

    • session保存在哪?
    • session如何获取?
    • session何时清除?

    服务器端既可以将session缓存在内存中,也可以将session持久化在硬盘中。但是缓存在内存中的session的生命周期不一定是会话级别的,持久化在硬盘中的session也可能是会话级别的。

    为什么会这样呢?我们需要先了解会话生命周期的概念:

    cookie的会话生命周期指的是:从浏览器请求服务器得到cookie开始,到浏览器关闭为止。

    会话级别的cookie一定是保存在浏览器内存中的,而会话结束,意味着cookie要失效清除,同时会话结束,也意味着浏览器关闭,浏览器关闭会释放自身内存,此时内存中的cookie也会被清除,这就是会话级别cookie保存在浏览器内存中的原因。

    类比可得,保存在服务器上的session会话生命周期指的是:从服务器接收浏览器请求生成session开始,到服务器关闭为止。

    而服务器不会轻易关闭,这会导致session的会话生命周期很长,影响安全性。同时服务器也不会为了控制会话时间跨度而关闭自身。session理论上不存在会话生命周期。

    但是一般我们可以设定固定时间为一个会话周期,比如20分钟为一次会话周期,20分钟到后,服务器强制清除对应session。

    所以服务器端将session生命周期和其保存位置无关。

    服务器端在保存session时,会生成一个sessionid,该sessionid是一个随机唯一的字符串,作用是作为在服务器端查询session的索引,和在浏览器端作为免登录的凭证。

    所以服务器端获取session靠的是sessionid。

    无论是cookie还是session,理论上都应该在其失效时清除,而不同的是清除手段。对于cookie而言,如果存储在内存中,则可以通过关闭浏览器释放内存来间接清除,如果存储在硬盘中,则需要浏览器内部代码逻辑清除。对于session,存储位置与生命周期无关,所以都只能通过代码清除,清除时,需要检查对应的session的有效期。

    下面是基于express和cookie-parser开发的session中间件

    const uuid = require('uuid').v1
    
    module.exports = function(options = {}){
      // session store
      const SESSION = {}
    
      return function(req, res, next) {
        // 获取浏览器请求中的cookie:sessionid值,若首次访问,则sid为undefined,若非首次访问,则sid有值
        let sid = req.cookies.sessionid
        // 由于并不是每次浏览器请求都需要服务器响应set-cookie头,所以使用一个needCookie标识
        let needCookie = false
        // 根据sid到session_store中查询是否有对应session
        let session = SESSION[sid]
        
        // 如果session_store没有对应session 或者 session_store有对应session,但是已经失效,则需要重新生成新的sid和session,并且需要重新set-cookie给浏览器
        if(!session || (+session.expires <= Date.now())) {
          delete SESSION[sid]
          sid = uuid()
          needCookie = true
          session = SESSION[sid] = Object.create(null)
        }
        
        // 由于session有效期要与cookie:sessionid的有效期保持一致,所以只能以服务器端设置的有效期为准,且只能使用有效日期,而不是存活时间maxAge
        let expires
     
        if(options.maxAge) {
          expires = new Date(Date.now() + options.maxAge)
          delete options.maxAge
          options.expires = expires
        } else if(options.expires) {
          expires = options.expires
        } else {
          expires = new Date(Date.now() + 20 * 60 * 1000)
        }
    
        session.expires = expires
    
        // 提供修改session有效期的入口,方便实现七天免登录这样的功能
        session.setExpires = function(exp) {
          session.expires = exp
          options.expires = exp
          needCookie = true
        }
    
        // 提供删除session的入口,方便实现注销登录的功能
        session.destory = function(){
          delete SESSION[sid]
        }
    
        req.session = session
        if(needCookie) {
          res.cookie('sessionid', sid, options)
        }
        next()
      }
    }
    

    实现session身份认证机制-Node.js文档类资源-CSDN文库

    以上是0积分可下载的示例项目链接。

    session存储在内存中的优缺点

    优点:

    • 获取session速度快
    • session存放在内存中,比存放在硬盘中更安全

    缺点:

    • 占用服务器内存,特别是当大量用户登录时,会产生大量session,占用大量服务器内存,严重时会导致服务器内存溢出。
    • 每当服务器重启时,服务器都会释放自身内存,导致内存中存储的session被清除,进而导致浏览器端存储的sessionid失效。
    • 对于分布式部署到多个服务器的项目而言,每个服务器内存中的session都是私有的,无法直接共享给其他服务器的,所以当用户被负载均衡分配到A服务器进行登录,但是又被负载均衡分配到B服务器进行其他业务时,会因为B服务器没有同步A服务器该用户的登录session数据导致业务无法进行。

    session存储在数据库中的实践

    前面说过session既可以存储在服务器内存中,也可以存储在服务器本地硬盘中。常见的存储在服务器本地硬盘的形式有:文件和数据库。

    其中数据库可以更好地管理数据,所以我们一般选择将session存储在数据库中。

    下面是基于node express框架开发的将session存储进Mongodb数据库的中间件代码

    const uuid = require('uuid').v1
    const mongoose = require('mongoose')
    
    const sessionSchema = new mongoose.Schema({
      sessionid: {
        type: String,
        required: true
      },
      expires: {
        type: Date,
        default: new Date(Date.now() + 20 * 60 * 1000)
      },
      user: Object
    })
    
    const Session = mongoose.model('session', sessionSchema, 'session')
    
    Session.prototype.setExpires = function(exp, res) {
      this.expires = exp
      res.setHeader('set-cookie', `sessionid=${this.sessionid};expires=${exp.toUTCString()};path=/;`)
    }
    
    Session.prototype.destory = async function(){
      await this.deleteOne()
    }
    
    module.exports = function(options = {}) {
      return async function(req, res, next) {
        let sid = req.cookies.sessionid
        let needCookie = false
    
        let session = await Session.findOne({sessionid:{$eq:sid}})
    
        if(!session || (+session.expires <= Date.now())) {
          if(session){
            await session.deleteOne()
          }
          
          if(options.maxAge) {
            options.expires = new Date(Date.now() + options.maxAge)
            delete options.maxAge
          }
    
          session = new Session({
            sessionid: uuid(),
            expires: options.expires
          })
    
          await session.save()
    
          sid = session.sessionid
          needCookie = true
        }
    
        req.session = session
        if(needCookie) {
          res.cookie('sessionid', sid, options)
        }
        next()
      }
    }
    

    session存储到数据库实践-Node.js文档类资源-CSDN文库

    0积分可下载的实践项目

    session存储在数据库中的优缺点

    优点

    • session不会因为服务器的重启而被清除,因为session被持久化到了数据库上
    • 分布式部署到多个服务器的项目可以共用同一个session数据库,这样就不需要担心session同步问题

    缺点

    • session获取速度变慢
    • session数据库需要注意安全防护,防止被黑客入侵

    session和cookie对比

    概念

    session和cookie都是用户登录状态数据

    工作流程

    cookie由服务器生成,通过响应头Set-Cookie传递给浏览器,cookie由浏览器保存,每次请求服务器时,浏览器都会通过请求头Cookie将对应的cookie传递给服务器,服务器基于请求头Cookie信息进行身份认证。

    session由服务器生成,并且保存在服务器,服务器在生成session的同时会生成与之一一对应的sessionid,sessionid有两个作用,一是在服务器端作为查找session的索引,二是作为登录凭据通过响应头Set-Cookie传递给浏览器,并保存在浏览器端。浏览器每次请求服务器都会通过请求头Cookie将sesionid传递给服务器,服务器通过sessionid查询到服务器端保存的session,并基于session进行身份认证。

    安全性

    在身份认证实践中,session比cookie更加安全,因为session机制会将用户登录状态数据保存在服务器端,浏览器端只有一个无意义字串sessionid。而cookie机制将用户登录状态数据保存在浏览器端。黑客盗取浏览器保存的cookie,要比盗取服务器保存的session,容易的多。

    同时,cookie机制中,服务器无法验证cookie有效期,cookie有效期完全由浏览器管理,同时浏览器具备多种入口篡改cookie有效期,这可能导致cookie有效期被故意篡改导致长期有效。

    而session机制中,服务器端可以在生成session时,保持session的有效期和作为cookie的sessionid的有效期一致,并且以服务器端保存的session的有效期为准,这保障了即使cookie:sessionid在浏览器端被篡改的长期有效,但是服务器端session的有效期却无法被篡改。

    管理难度

    cookie保存在浏览器端,浏览器已经有了一套成熟的管理机制:

    保存:自动将服务器HTTP响应头中Set-Cookie信息保存在浏览器内存或硬盘中

    获取:自动将保存在浏览器内存或硬盘中的cookie取出作为HTTP请求头Cookie发生给服务器

    清除:自动清除内存或硬盘中失效的cookie

    而session保存在服务器端,服务器本身没有内置管理session的机制,需要第三方工具或者人为开发管理代码

    性能方面

    另外cookie是将每个用户的登录状态数据分散保存在用户个人电脑上,对于服务器来说内存友好,性能友好。

    session是将每个用户的登录状态数据集中保存在服务器内存或服务器连接的数据库中,对于服务器来说内存不友好,性能也不友好。

    跨站请求与cookie禁用时的session

    大部分跨站请求时,浏览器是禁止HTTP请求携带目的站点cookie的。

    而session是基于cookie工作的,所以发生跨站请求时,session也是无法工作的。

    另外浏览器提供了cookie禁用设置渠道,所以一旦用户禁用了cookie,那么session也是无法工作的。

    node第三方模块express-session

    express-session是express推荐的用于服务器端session管理的模块,下面是express-session使用示例

    在express服务器中引入express-session模块,express-session模块对外暴露一个函数,如上图const session = require('express-session')中的session就是一个函数,该函数:

    • 入参:配置对象
    • 返回:express中间件

    我们将该函数返回的express中间件注册到express服务器实例app上,则在服务器定义的HTTP请求对象req上会挂载一个session对象,我们可以通过req.session来操作服务器端session。

    下面介绍一下入参配置对象的属性,及其作用

    name可选属性,用于指定保存在浏览器cookie中的sessionid的名字,默认为'connect.sid'
    secret必选属性,用于指定保存在浏览器cookie中的sessionid的加密密钥,用于签名,检查sessionid是否被篡改,可以是一个字符串,或者一个数组,如果是一个数组,则选择数组第一个元素作为secret,secret需要尽可能地复杂,难以猜测,这样才能保障sessionid的安全
    resave可选属性,默认值为true,表示强制将session保存回session store,即使session并没有发生改变。但是每次强制将session保存回session store会造成并行情况下的竞争,比如同一时刻,发生了两条请求,一条修改了session,一条没有修改session,则此时很难预测session store中的session是否会被发生改变。所以当前resave默认true的设定已经被废弃,我们需要考虑自己的session store是否实现了touch方法,是否为session设定了过期时间,然后才可以决定是否可以将resave设置为false
    saveUninitialized可选属性,默认值为true,表示强制将未初始化的session保存到session store。但是目前默认值true已经被废弃
    cookie

    可选属性,值是一个配置对象,用于指定保存在浏览器端cookie:sessionid的属性domain,path,maxAge,expires,httponly,secure,samesite

    rolling

    可选属性,默认值为false,当设置为true时,表示每次服务器响应时都会携带cookie:sessionid,且sessionid的有效期被重置为初始maxAge值,服务器端session也会被重置为初始maxAge值。

    需要注意的是,当rolling设置为true,但是saveUninitialized被设置为false,未初始化的响应则不会携带cookie。

    store可选属性,用于指定session store,默认的session store为服务器内存,此时需要注意服务器内存是否可能被撑爆,所以建议不要使用服务器内存作为session store。建议选择数据库作为session store,如redis,mongodb,mysql等,目前npm社区也很对express-session开发了上述数据库的接口,如connect-mongo,connect-redis,express-mysql-session
    genid可选属性,用于指定生成sessionid的函数,该函数的返回值将作为存放在浏览器端cookie中的sessionid的原始值,默认采用uid-safe
    proxy

    可选属性,在设置secure cookie时信任反向代理(通过“x - forward - proto” 头)

    默认值为undefined,表示使用express的“信任代理”设置

    可选值true,表示将使用x-forward-proto

    可选值false,表示忽略所有头,只有tls/ssl传输是是安全的

    unset

    可选属性,默认值为keep,可选值为destroy。

    当unset为destory时,表示每次响应结束都会删除session.

    当unset为keep时,表示session会被保留在session store中。

    其中常用的有secret,name,cookie,rolling,store。

    上面配置中name被指定为sessionid,所以在浏览器端存储的cookie的名称就是sessionid

    浏览器端保存的cookie:sessionid的值为

    s:HYm7whqjvhQ1CQVFCItHTNVTi_47CroP.t7ytiOOMSYIsLww5afl1dKXlTr0nh9bgEPZuhxmrDQo

     发现该值被:和.分为了三段,可以猜测第一段值:s,可能是指定签名算法,第二段是sessionid的值,即存入session store的_id的值,第三段就是根据secret和指定签名算法对sessionid值进行加密的签名,这保证了第二段sessionid值一旦被篡改,服务器端可以通过第三段签名值判断出来。

    另外从session store存储的session信息可以分析

    {

      "_id" : "HYm7whqjvhQ1CQVFCItHTNVTi_47CroP",

      "expires" : ISODate("2022-03-23T11:57:21.390Z"),

      "session" : "{\"cookie\":{\"originalMaxAge\":604800000,\"expires\":\"2022-03-23T11:57:21.135Z\",\"httpOnly\":true,\"path\":\"/\"},\"user\":{\"name\":\"qfc\",\"pass\":\"123456\"}}"

    }

    _id就是sessionid值,

    expires是session有效期,

    session分为cookie和user,其中cookie就是cookie:sessionid的属性,user就是登录状态数据

    req.session可以用来操作session store,比如增删改查session store中的session信息。

    req.session.destroy(callback)删除当前req.session在session store中的值
    req.session.reload(callback)从session store中重载session对象到req.session上
    req.session.save(callback)将req.session保存会session store,但是通常该方法不需要调用,因为在服务器响应前,都会自动调用该方法。
    req.session.regenerate(callback)重新生成一个sessionid和session,并且会重载session到req.session上
    req.session.touch()该方法用于更新session的maxAge,通常不需要调用,由其他中间件调用
    req.sessionID只读属性,获取当前请求对应的sessionid
    req.session.idreq.sessionID的别名
    req.session.cookie.maxAge重置session以及cookie:sessionid的存活时间,单位为毫秒数
    req.session.cookie.expires重置session以及cookie:sessionid的有效日期,值为Date类型
    req.session.cookie.originalMaxAge用于设置session以及cookie:sessionid的默认存活时间

    展开全文
  • 面试考点:session和cookie

    千次阅读 多人点赞 2022-03-25 16:07:49
    文章目录一、关于 cookie 的前言概括二、session 工作原理三、常用的方法3.1 getSession()3.2 getAttribute()和setAttribute()四、关系总结图五、实操:实现登录功能并计算访问页面的次数5.1 登录页面实现(login....

    一、关于 cookie 的前言概括

    在之前的 HTTP 格式的介绍当中,有详细的介绍过 cookie 的相关用法。

    简单回顾总结就是:

    1. cookie 是让程序员能够在客户端持久存储数据的一种机制
    2. 存储的是程序员自己定义的键值对
    3. 通过服务器响应 set-cookie 这个 header 获取到 cookie 的值,并保存到本地
    4. 下一次请求就会带上 cookie ,发送给服务器

    用户输入账号密码登录后,再次登录不需要再次输入账号密码就可以直接的登录成功就是依靠 cookie 来实现的

    在这里插入图片描述

    但是有关于用户的信息实际上是非常多的,比如访问网站的浏览记录,上次访问网站的时间等等,这么多的信息在服务器客户端之间传输来又去的非常浪费带宽。更何况 cookie 的存储容量又是有限的,一个站点最多保留20个 cookie,这么多的用户信息没有办法单纯的依靠 cookie 来保存在客户端,因此将数据保存到服务器端才是比较科学的做法。

    二、session 工作原理

    因为要将信息存储在服务器端,就引入了会话机制 session

    session是服务端存储的一个对象,主要用来存储所有访问过客户端网页的用户信息(也可以存储其他信息),从而实现保持用户会话状态。但是服务器重启时,内存会被销毁,存储的用户信息也就消失了。

    面试题:详述 session 工作原理

    1. 当客户端登录完成后,就会在服务器端产生一个 session,,实际上是一个键值对,key 是 sessionId(随机唯一的字符串),value 保存的就是身份信息(HttpSession 对象)。服务器端将这些键值对形式的会话通过hash 表的形式管理起来
    2. 此时服务器端就会将 sessionId返回到客户端浏览器。
    3. 客户端将 sessionId 存储在浏览器的 cookie
    4. 当用户再次登录的时候,就会拥有对应的 sessionId ,就将该 sessionId 发送到服务器端请求登录
    5. 服务器端在内存中找到对应的 sessionId 就完成登录,如果找不到,说明还没有登录(每个用户登录都会生成一个会话),就返回登录页面让用户进行登录

    session 工作原理和校园卡差不多,校园卡中实际上并没有保存太多的内容,但是有着它在学校中拥有的唯一的信息——学号。因此你(客户端)拎着这张卡,通过学号(相当于sessionId)就可以在系统中(服务器)搜索到有关于你的相关具体学生信息,就可以凭借卡进出宿舍大门,在图书馆借书,在食堂吃饭等等。

    三、常用的方法

    3.1 getSession()

    这是 HttpServletRequest 类中的方法,作用是在服务器中获取会话。

    HttpSession session = req.getSession(true);
    HttpSession session = req.getSession(false);
    

    参数为true

    1. 查看请求中是否有 sessionId ,并判断其合法性
    2. 如果有 sessionId 且合法,就根据该 sessionId 找到对应的 HttpSession对象
    3. 如果没有 sessionId,就生成一个唯一的 sessionId,创建一个HttpSession 对象,把这一组键值对插入到服务器管理 session 的 hash 表中,把 sessionId 通过 Set-Cookie 在响应中返回给客户端

    参数为false

    1. 查看请求中是否有 sessionId ,并判断其合法性
    2. 如果有 sessionId 且合法,就根据该 sessionId 找到对应的 HttpSession对象
    3. 如果没有 sessionId,就直接返回 null

    通常用法就是前者用于登录,后者用于查看登录的情况。

    3.2 getAttribute()和setAttribute()

    HttpSession 对象中就保存着我们需要保存的身份信息,这些身份信息的存储方式也是键值对的形式

    **1. Object getAttribute(String name) **

    该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返返回 null

    int num = (Integer)session.getAttribute("number");
    //通过number这个key来找对应的value,找的对象是int类型,需要进行强制类型转换
    

    2. void setAttribute(String name, Object value)

    该方法使用指定的名称绑定一个对象到该 session 会话

    session.setAttribute("users",user);//将user是value; users是key
    

    简单来说,就是 HttpSession 对象中的键值对,通过 key 来获取 value 的值的方法就是getAttribute,根据 key 来设置 value 的值的方法就是 setAttribute

    四、关系总结图

    在这里插入图片描述

    可以看见Cookie,session,HttpSession 对象中的值都是键值对的形式,其中的关系需要理清。

    五、实操:实现登录功能并计算访问页面的次数

    5.1 登录页面实现(login.html)

    <body>
        <form action="login" method="post">
            <input type="text" name="userName"><br>
            <input type="text" name="passWord"><br>
            <input type="submit" value="提交">
        </form>
    </body>
    

    通过的 form 表单简单的构造一个登录页面

    1. action=“login” 中,login是处理 post 请求的 Servlet 程序,用于判断用户登录是否成功

    2. method="post"指的是请求的方法时POST

    3. form 表单默认的body格式是 x-www-form-urlencoded ,因此构造的请求 body为 userName=xxx&passWord=xxx

    5.2 判断是否登录成功 Servlet 程序(LoginServlet)

    class User {
        public String userName;
        public String passWord;
    }
    @WebServlet("/login")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html;charset=utf8");//设置字符集
            //1.获取到body中的数据
            String userName = req.getParameter("userName");
            String passWord = req.getParameter("passWord");
            //2.验证登录数据的合法性,为null或者为空字符串都为不合法
            if(userName == null||userName.equals("")||passWord == null||passWord.equals("")) {
                resp.sendRedirect("login.html");
                //不合法就重定向到login.html继续用户名及密码的输入
                return;
            }
            //3.核对信息的正确性(在这里假定用户名字为Peter,用户的密码为123)
            if(!userName.equals("Peter")||!passWord.equals("123")) {
                resp.getWriter().write("用户名或者密码错误,登陆失败");
                return;
            }
            //到这儿登录成功啦,就可以创建会话了
            User user = new User();
            user.userName = userName;
            user.passWord = passWord;//构造一个 User 对象
            HttpSession session = req.getSession(true);
            //如果会话中不存在该用户就创建一个新的sessionId
            session.setAttribute("user",user);//设置属性
            session.setAttribute("index",0);//代表访问次数,最初为0
            resp.sendRedirect("index");
            //重定向到index路径,实现访问次数的计数
        }
    }
    

    流程总结:

    1. 读取到用户提交的用户名和密码
    2. 对用户名及密码的合法性进行校验
    3. 判断是否登录成功
    4. 创建会话,在 HttpSession 对象中保存一些信息
    5. 重定向到指定页面

    5.3 显示访问次数 Servlet 程序(IndexServlet)

    @WebServlet("/index")
    public class IndexServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html;charset = utf8");
            //1.首先需要通过session判断一下,是否已经登录成功了
            HttpSession session = req.getSession(false);
            //此时去找记录的时候,如果没有存档就返回null
            if(session == null) {
                //说明没有登录过,重定向到 login.html 页面进行登录
                resp.sendRedirect("login.html");
                return;
            }
            //到这里说明已经登录过了
            User user = (User)session.getAttribute("user");
            int visitCount = (Integer)session.getAttribute("index");
            //获取用户 user 和 设置的访问次数 index,首次访问时为0
            visitCount ++;//访问次数增加
            session.setAttribute("index",visitCount); //将值设置回去
            StringBuilder str = new StringBuilder();
            str.append(user.userName);
            str.append("访问次数: ");
            str.append(visitCount);
            resp.getWriter().write(str.toString());
        }
    }
    

    5.4 结果验证与展示

    首次登录请求:

    请求:

    在这里插入图片描述

    可以查看到form表单中接收请求的对象以及 body 部分

    响应:

    在这里插入图片描述

    状态码 302Location:index,说明重定向到 index 路径进行访问次数的显示了

    由于登录成功,服务器通过 Set-Cookie 的Header向客户端传送 sessionId,该sessionId 的 key 为JSESSIONID ,后面跟着的一长串字符串就是 sessionId 的值(唯一的)

    此时服务器端就保存了 sessionId

    第二次请求:

    这次请求服务器就会带着 sessionId ,服务器根据这来找到 HttpSession 对象,取出里面 index 对应的值,自增,在写回去,同时页面显示访问次数结果

    浏览器本地查看的 Cookie 内容:

    在这里插入图片描述

    第二次请求的请求:

    在这里插入图片描述

    第二次请求的响应:

    在这里插入图片描述

    页面结果:

    在这里插入图片描述

    之后的继续访问,原理同上

    总体效果展示:

    在这里插入图片描述

    当服务器进行重启,内存中的 session 数据就会没有,此时客户端拿着之前的 sessionId 是没有办法在服务器端找到 HttpSession 对象的,就会返回 null ,进行重新登录。

    完!

    展开全文
  • Spring Session 详解

    千次阅读 2021-03-01 14:24:52
    1.SpringSession简介 1.1 Session 会话管理及带来的问题 HTTP协议本身是无状态,的为了保存会话信息,浏览器Cookie通过SessionID标识会话请求,服务器以SessionID为key来存储会话信息。 在 Web 项目开发中, Session...

    1.SpringSession简介

    1.1 Session 会话管理及带来的问题

    HTTP协议本身是无状态,的为了保存会话信息,浏览器Cookie通过SessionID标识会话请求,服务器以SessionID为key来存储会话信息。 在 Web 项目开发中, Session 会话管理是一个很重要的部分, 用于存储与记录用户的状态或相关的数据。

    • 通常情况下 session 交由容器(tomcat) 来负责存储和管理, 但是如果项目部署在多台tomcat 中, 则 session 管理存在很大的问题
    • 多台 tomcat 之间无法共享 session, 比如用户在 tomcat A 服务器上已经登录了, 但当负载均衡跳转到 tomcat B 时, 由于 tomcat B 服务器并没有用户的登录信息,session 就失效了, 用户就退出了登录
    • 一旦 tomcat 容器关闭或重启也会导致 session 会话失效因此如果项目部署在多台 tomcat 中, 就需要解决 session 共享的问题

    1.2 SpringSession的特性

    使用框架的会话管理工具,也就是我们要介绍的 Spring session,这个方案既不依赖 tomcat 容器, 又不需要改动代码, 由 Spring session 框架为我们提供, 可以说是目前非常完美的 session 共享解决方案。Spring Session 是 Spring 家族中的一个子项目, 它提供一组 API 和实现, 用于管理用户的 session 信息.它把 servlet 容器实现的 httpSession 替换为 spring-session, 专注于解决 session 管理问题, Session 信息存储在 Redis 中, 可简单快速且无缝的集成到我们的应用中;

    Spring Session 的特性:

    • 提供用户 session 管理的 API 和实现
    • 提供 HttpSession, 以中立的方式取代 web 容器的 session, 比如 tomcat 中的session
    • 支持集群的 session 处理, 不必绑定到具体的 web 容器去解决集群下的 session共享问题

    2.入门案例

    2.1 创建项目

    (1)创建一个Maven的web module,名字为01-springsession-web
    在这里插入图片描述(2)完善Maven项目的结构

    • 在main目录下,创建java目录,并标记为Sources Root
      在这里插入图片描述
    • 在main目录下,创建resources目录,并标记为Resources Root
      在这里插入图片描述
    • 导入依赖
    <!--servlet依赖-->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
        </dependency>
        <!--SpringSession redis 集成依赖-->
        <dependency>
          <groupId>org.springframework.session</groupId>
          <artifactId>spring-session-data-redis</artifactId>
          <version>1.3.1.RELEASE</version>
        </dependency>
        <!--Spring Web 模块依赖-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>5.2.10.RELEASE</version>
        </dependency>
    

    2.2 代码开发

    (1) 创建向 session 放数据的 servlet

    package session.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet(urlPatterns = "/setSession")
    public class SetSessionServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.getSession().setAttribute("url","http://www.baidu.com");
            resp.getWriter().write("OK");
        }
    }
    

    (2) 创建从 session 中获取数据的 servlet

    package session.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet(urlPatterns = "/getSession")
    public class GetSessionServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String url= (String) req.getSession().getAttribute("url");
            resp.getWriter().write(url==null?"NO Session":url);
        }
    }
    

    (3)部署访问测试(目前无法实现 session 共享)

    • 配置tomcat9100 服务器,给 tomcat 服务器取名,并修改端口号,并将项目部署到tomcat9100 上

    在这里插入图片描述

    • 配置tomcat9200服务器,操作步骤同上

    可以在9100端口的服务器上访问/setSession,再在9200端口的服务器上访问 /getSession
    这个时候我们通过测试会发现两个Tomcat服务器之间是无法共享session数据的

    2.3 SpringSession 集成配置

    • 在resources目录下创建如下两个配置文件在这里插入图片描述
    • applicationContext.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <import resource="classpath:springsession.xml"/>
    </beans>
    
    • springsession.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--
            启动Spring的注解支持,因为SpringSession中使用到了Spring的相关注解,因此需要启动Spring的注解,这一步是可以省略的
            通常工作时我们会使用 <context:component-scan base-package="com"/>来进行包扫描,这个标签中的功能就包含了
            <context:annotation-config/>的功能,因此实际工作时这个步骤是可以省略
         -->
        <context:annotation-config/>
    
        <!--
             定义一个用于配置SpringSession的bean标签配置
             只配置RedisHttpSessionConfiguration 的Bean 就可以实现同域名同项目的Session共享
             适合于我们的Nginx集群模式下的P2P项目部署
        -->
        <bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
            <!--配置Session的最大生命周期 单位 秒 默认值为1800 表示30分钟 -->
            <property name="maxInactiveIntervalInSeconds" value="1800"/>
        </bean>
    
    
        <!-- 配置 jedis 连接工厂, 用于连接 redis
             可选配置步骤,如果当前工程已经配置过了redis,那么这个过程可以省略
        -->
        <bean id="jedisConnectionFactory"
              class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
              <!--分别为主机名、redis端口号、redis密码-->
            <property name="hostName" value="127.0.0.1"/> 
            <property name="port" value="6379"/>
            <property name="password" value="123456" />
        </bean>
    </beans>
    
    • 点击 config 将这两个配置文件进行关联
      在这里插入图片描述

    这次通过上面已经介绍过的测试方法,我们可以发现session数据可以在端口号分别为9100和9200的两个不同的Tomcat服务器上实现共享了


    • 在浏览器(这里我使用的谷歌浏览器)上检查页面元素会发现两个页面上存储的cookie中存储的Session ID属性值和redis中相同。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • 上面的HASH文本框中便是redis上存储的Session ID值
    • lastAccessTime:最后一次访问时间
    • sessionAttr:session对象中存储数的属性
    • maxIntactiveInterval:session的最大生命周期,默认是30分钟
    • creationTime:session的创建时间

    3.同域名下不同项目的session共享

    3.1 案例

    1. 在 Deployment 选项卡下,设置本地 tomcat9100的Application context 为/p2p
    2. 在 Deployment 选 项卡下 ,设置本地 tomcat9200的Application context 为/shop
    3. 在idea中重新启动本地的两台 tomcat 服务器
    4. 在浏览器中访问 tomcat9100(p2p), 设置 session
      在这里插入图片描述
      session设置成功

    5. 在浏览器中访问 tomcat9200(shop),获取 session
      在这里插入图片描述
      获取不到session

    6. 分析 Session 共享失败原因
    • 我们通过浏览器提供的开发人员工具可以发现,这两个请求的 cookie 的路径(path)不一致(如下图),虽然我们已经加了Spring Session共享机制,但是后台服务器认为这是两个不同的会话(session),可以通过 Redis 客户端工具(Redis Destop Mananger) 查看,先清空,然后访问,发现是维护了两个不同的 session,所以不能实现共享。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • 同样redis中也存储了两个不同的session对象,其中一个session对象中没有sessionAttr属性。
      在这里插入图片描述
      在这里插入图片描述
    1. 解决方案:设置Cookie路径为根/上下文在springsession.xml文件中,加如下配置:
    <bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
            <!--配置Session的最大生命周期 单位 秒 默认值为1800 表示30分钟 -->
            <property name="maxInactiveIntervalInSeconds" value="1800"/>
            <!--注入一个Cookie的序列化规则对象 -->
            <property name="cookieSerializer" ref="defaultCookieSerializer"/>
    </bean>
    
        <!--配置一个Cookie序列化规则对象 用于改变Cookie的存放规则 -->
    <bean id="defaultCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
            <!--指定SpringSession的SessionId存放在域名的根路径下,用于实现同域名不同项目的Session共享 -->
            <property name="cookiePath" value="/" />
    </bean>
    
    1. 重新进行测试发现两个不同项目的session数据也能实现共享,且两个请求的cookie路径(path)相同均为" / "。且此时redis中也只有一个session对象。
      在这里插入图片描述

    3.同根域名不同二级子域名下的项目实现Session 共享

    同一个根域名,不同的二级子域名,比如北京和武汉的58同城域名:
    武汉的58同城
    在这里插入图片描述

    3.1案例

    添加域名映射: 找到C:\Windows\System32\drivers\etc路径下的hosts文件,在文件末尾加上:
    127.0.0.1 p2p.myweb.com
    127.0.0.1 shop.myweb.com

    • 通过测试发现这是无法实现两个服务器上session数据的共享
    • 原因:我们通过浏览器提供的开发人员工具可以发现,虽然这两个cookie 的路径(path)都设置为了“/”,但是这两个cookie的域名不一致,虽然我们已经加了Spring Session共享机制,但是后台服务器同样认为这是两个不同的会话(session),可以通过 Redis 客户端工具(Redis Destop Mananger)查看,先清空,然后访问,发现是维护了两个不同的session,所以不能实现共享,也就是说后台区分是否同一个 session 和路径和域名有关。
      在这里插入图片描述
      在这里插入图片描述
    • 解决方案:设置Cookie的域名为根域名 web.com,在 applicationContext-session.xml 文件中, 加如下配置:
      注意:域名要和 hosts 文件中配置的域名后面一样
    <!--配置一个Cookie序列化规则对象 用于改变Cookie的存放规则 -->
        <bean id="defaultCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
            <!--指定SpringSession的SessionId存放在域名的根路径下,用于实现同域名不同项目的Session共享 -->
            <property name="cookiePath" value="/" />
            <!--指定SpringSession的SessionId存放在根域名下,用于实现同根域名不同二级子域名下的Session共享
                适合应用在Nginx的虚拟主机的多城市站点部署
             -->
            <property name="domainName" value="myweb.com"/>
        </bean>
    
    • 经过测试,发现可以实现session共享
      在这里插入图片描述
      在这里插入图片描述
      此时两次请求的Session ID都是存放在.myweb.com域名下
    展开全文
  • 退出页面自动清除session技巧

    热门讨论 2015-08-01 15:18:14
    退出页面自动清除session技巧
  • 借csrf理解session原理

    万次阅读 2021-04-16 22:31:28
    CSRF xss利用站点内的信任用户,csrf通过伪装成受信任用户请求受信任的网站,即攻击者利用目标用户的身份,以目标用户的名义执行某些非法操作 ...session 是以文本形式存储到服务端的,php 自动修改 sessi
  • 本文按照代码运行的顺序,一步步分析了session的创建,保存到redis,将sessionid交由cookie托管的过程。分析完源码之后,我们知道了session的创建和保存到redis主要是由RedisOperationsSessionRepository类来完成。...
  • tomcat-redis-session-manager支持tomcat7

    千次下载 热门讨论 2014-12-20 10:15:42
    因tomcat7使用redis共享session,其他的包存在问题,自己编译后处理通过。 该包是在https://github.com/jcoleman/tomcat-redis-session-manager 将源码编译后的包。
  • Session原理

    万次阅读 多人点赞 2019-06-18 08:35:21
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~...开发工具与关键技术:Java,HTTP协议,session原理 撰写时间:2019-06-17 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~...
  • 38.状态保持之Session详解

    千次阅读 多人点赞 2021-09-06 22:39:12
    引言——上文讲的是cookie,但是cookie的键和值都是明文的形式存储在客户端浏览器上,很不安全! 那有没有更好些的来存储登录状态的方式...存储方式包括cookie,session,会话一般指session对象。 使用cookie,所有数据.
  • spring security的session管理

    千次阅读 2021-01-24 15:49:59
    1 spring security的session管理 spring security关于认证session的逻辑处理在接口SessionAuthenticationStrategy的onAuthentication方法中,先看看这个接口和其实现类。 1.1 SessionAuthenticationStrategy接口 ...
  • Django cookie 与 session

    万次阅读 2020-09-09 10:23:52
    文章目录Django cookie 与 sessionCookiesDjango 中 Cookie ...Django cookie 与 session Cookie 是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。 识别返回用户包括三个步骤: 服务器脚本向浏览器发送一组
  • Session认证机制

    千次阅读 2022-03-28 09:26:20
    不同开发模式下的身份认证: (1)服务端渲染推荐使用Session认证机制; (2)前后端分离推荐使用JWT认证机制。
  • 【Laravel笔记】16. Cookie和Session

    千次阅读 2021-02-09 12:32:44
    16.2 使用Session 16.1 使用Cookie 1、首先,获取Cookie 有两种方法,具体如下: //使用request()->cookie 获取解密后的cookie 信息 return request()->cookie('laravel_session'); //使用Cookie::也可以获取,...
  • 使用 Redis 实现 Session 共享 1 什么是 Session 由于 HTTP 协议是无状态的协议,因而服务端需要记录用户的状态时,就需要用某种机制来识具体的用户。Session 是另一种记录客户状态的机制,不同的是 Cookie 保存在...
  • Spring全家桶之SpringSession

    万次阅读 多人点赞 2019-09-15 20:11:52
    SpringSession和SpringSession MongoDB相关的实用知识的整理 ,希望能够帮助更多人~~~
  • 前言 上一篇我们介绍了SpringSessionSession的保存过程,今天我们接着来看看Session的读取过程。相对保存过程,读取过程相对比较简单。 读取过程的时序图 ...
  • 【什么是session?什么是cookie?session和cookie有什么区别?】 每篇分享文从 【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】 八个方面深度解析前端知识/...
  • Spring-Session基于Redis管理Session

    万次阅读 2018-11-13 14:33:01
    在上文Tomcat Session管理分析介绍了使用tomcat-redis-session-manager来集中式管理session,其中一个局限性就是必须使用tomcat容器;本文介绍的spring-session也能实现session的集中式管理,并且不局限于某种容器;...
  • shiro——session会话管理

    万次阅读 2019-08-23 18:02:53
    1.1 Session 接口 1.2 SessionManager 会话管理 1.3 SessionListener 会话监听 2. 会话持久化 2.1 SessionDAO接口 2.2AbstractSessionDAO类 2.3 CachingSessionDAO 类 2.4 EnterpriseCacheSessionDAO 类 2.5...
  • 什么是session

    千次阅读 2019-03-11 09:43:23
    最近在学习node.js 的express框架,接触到了关于session方面的内容。翻阅了一些的博客,学到了不少东西,发现一篇博文讲的很好,概念内容摘抄如下: Session是什么 Session一般译作会话,牛津词典对其的解释是进行...
  • 会话技术:cookie和session

    千次阅读 2021-11-17 15:19:45
    一.会话技术 会话:会话指的是多次请求和多次响应,客户端在第一次给服务器发送请求时会话...方式:客户端会话技术(cookie)和服务器端会话技术(session) 二.客户端会话技术 客户端会话技术采用cookie实现: ...
  • 4G EPS Session与5G PDU Session

    千次阅读 多人点赞 2019-10-19 19:48:00
    4G EPS Session与5G PDU Session什么叫Session?移动通信网络的Session 什么叫SessionSession,这个是一个非常广的概念,需要在特定的领域里加以限定,但即便是通信领域,Session也会因为适用于不同的通信场景而...
  • 本篇开始学习Spring-Session相关的一些知识学习整理,让我们开始吧! Spring-Session介绍 Spring-Session使用的场景? HttpSession是通过Servlet容器进行创建和管理的,在单机环境中。通过Http请求创建的...
  • sqlalchemy 中 session 是什么, scoped_session 又是什么 ? sqlalchemy 中的 session , scoped_session 的区别 摘要 : 本文 主要讲解 Session 是什么, scopedsession sqlalchemy 中的 session , scoped_session 的...
  • tomcat-redis-session

    热门讨论 2016-07-25 16:37:28
    使用tomcat-redis-session-manager开源框架实现使用Redis存储Nginx+Tomcat负载均衡集群的Session所需要的3个jar:tomcat-redis-session-1.0-SNAPSHOT.jar、jedis-2.7.2.jar、commons-pool2-2.0.jar
  • 文章目录快速入门 Spring Session + RedisSpring Session 原理 快速入门 Spring Session + Redis Spring Session 原理 Spring Session 主要是利用过滤器,偷梁换柱,实现session储存无感知的切换。 Spring ...
  • cookie、session与token的真正区别

    万次阅读 多人点赞 2019-05-09 11:21:24
    后来有个叫Memcached的支了招:把session id 集中存储到一个地方, 所有的机器都来访问这个地方的数据, 这样一来,就不用复制了, 但是增加了单点失败的可能性, 要是那个负责session 的机器挂了, 所有人都得重新...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,838,109
精华内容 735,243
关键字:

session

友情链接: RuoYi-fast.rar