当前位置: 首页 > news >正文

理解 Web 中的Session

===================================
Session 工作原理是什么?
===================================
因为 http 协议是无状态的, 对于服务器端来讲, 如何为不同的访问用户提供不一样的体验呢? 比如邮箱系统, 只有登录用户才能收发邮件.
这就需要服务器能识别每一个客户端访问, 知道哪些访问是来自一个同一个客户端, 显然这个事情光靠服务器端是做不到的, 需要浏览器配合才行, 浏览器端 cookie 概念就这么产生了.
Session 工作原理:
(1) 当一个 Session 第一次被启动时, 服务器端先产生一个唯一的 session id, 并为该 session id 分配一个内存区, 用来保存该 session 相关的信息. 然后将该 id 存储到浏览器的 cookie 中, cookie name 为 JSESSIONID.
(2) 浏览器每次访问, 都会带上本域下所有的 cookie, 包括这个 JSESSIONID cookie(应该是放到 Http Header 上的), 服务器端通过对比 JSESSIONID 和服务器内存中的 session id, 就能识别哪些访问是来自同一个客户端.
(3) 服务器端在每次访问中, 都可以在 JSESSIONID 对应的 session 内存区中记录一些信息, 比如最后一次的访问时间, 比如访问 IP 值, 以满足业务需求.


===================================
Session 的用途有哪些?
===================================
1. 核心功能: 是识别每一个访问.
2. 基本功能: 做登录验证, 然后就能得到登录 id, 进而能完成权限验证.
核心功能和基本功能都由 Spring Web 框架提供, 或 Shiro 这样安全框架提供, 我们的代码不用直接处理这些事情.
3. 利用 Session, 可以衍生出更多的功能, 比如保存访客上次访问的 IP 和上次访问时间, 比如保存 user Id 和 user name, 这里稍微要多想一下:
(1). 这些数据既可以保存到 DB 中, 也可以保存到 Session 内存中, user id 和 user name 在 DB 中本来就保存着, 有必要在 session 中保存吗?
Session 的优点是访问速度快, 缺点是用户量大的情况下内存占用是个问题.
(2). 这些数据既可以保存到 cookie , 也可以保存到 Session 内存中, 哪个更适合?
Cookie 的优点是: 不占用服务器端内存, Session 占服务器内存并且重启后就没了, cookie 可以被js访问到, 常用的网页埋点就是把一些标记信息保存到cookie, 然后由js提交到埋点服务器中.
Cookie 的缺点是, cookie 数据如果较大, 会消耗较多的网络带宽; 用户随意修改 cookie 值, 这样的话, cookie的数据就不太可靠了; 另外, 用户换个浏览器或者浏览器清个缓存, 原有的cookie就没法用了.
这些问题都没有标准答案, 按照具体情形做选择吧.

 

===================================
JSESSIONID Cookie 是到底是在什么时候生成?
===================================
JSESSIONID Cookie 并不是在第一次访问网站时候立即生成的, 只有访问 url 对应视图函数中有 Session 相应操作时, 浏览器端才会创建 JSESSIONID cookie 的.
当然, 一般网站在首页访问的视图函数基本都会有 session 操作, 所以给我们的错觉是, 一旦新访问一个网站, JSESSIONID cookie 就自动产生了.

比如访问 http://localhost:8080/ 主页,  访问第一个测试代码的首页, 并不会创建 JSESSIONID cookie. 

// 该 url 请求没有任何与 session 相关的操作, 浏览器端不会创建该网站的 JSESSIONID cookie
@GetMapping("/")
public String index(HttpServletRequest request) throws SQLException {
    return "OK";
}

// 在 url 请求中, 有获取 session 对象的指令, 浏览器端会创建该网站的 JSESSIONID cookie
@GetMapping("/")
public String index(HttpServletRequest request) throws SQLException {
    request.getSession(); //获取 session 对象
    return "OK";
}    

// 在 url 请求中, 视图函数要注入 session 对象, 浏览器端会创建该网站的 JSESSIONID cookie
@GetMapping("/")
public String index(HttpSession session) throws SQLException {
    return "OK";
}   

===================================
JSESSIONID 的 ID 值会登录后会变化吗?
===================================
假设在登录之前, 浏览器端已经有了 JSESSIONID cookie. 现在问题来了, 在用户登录之后, 该 JSESSIONID ID 值是否变化?
答案是: 早期网站, 登录前后 JSESSIONID 是不变的, 但后来发现, 如果登录前后 JSESSIONID 不变, 会有中间人攻击风险. 所以现在的安全框架在登录完成后, 会自动修改 JSESSIONID 值. 我们开发网站不需要再专门修改 JSESSIONID.

和登录不一样, 登录退出 JSESSIONID 的 Id 值并不会改变.


===================================
Session 和 cookie 之间的关系?
===================================
前面已经提到为了标识同一个客户端访问, 光靠服务器端的 Session 是不够的, 还需要客户端 JSESSIONID Cookie 支持. 这体现了 Session 和 cookie 之间最重要的一个关系.
另外, 在 Web 开发中 Session 和 Cookie 有一些很类似的方法, 往往会引起混淆, 有必要区别一下.
1. Session:

  •  保存在服务器端内存中, 服务器重启所有的 session 都没了.
  • session.setAttribute() 是在服务端内存中保存一个属性, 并不会将它保存到浏览器端的 Cookie 中.
  • 可以在一个 session id 下新建多个属性.
  • session 的有效期是针对所有 session id 全局级别的, 不是单个 session id 级, 也不是属性级的.
  • Session 中 id 和对应的属性, 可以大致理解为从属关系, 这些属性属于一个 id.

2. Cookie:

  • 保存在浏览器本地存储中, 服务器重启并不会影响 cookie.
  • 一个网站下可以包含多个 cookie , 最重要的那个是 JSESSIONID Cookie. 新建一个 cookie 并不会在服务器端生成一个对应的属性.
  • 每个 cookie 都可以设置自己的有效期, 自己的 HttpOnly 属性.
  • 一个网站的 JSESSIONID Cookie 和其他 cookie 并没有从属关系

===================================
Spring 中 Session 和 cookie 的操作方式
===================================

Spring Session操作很简单:

  • //获取 session 对象, 或者视图函数中直接注入 HttpSession 对象
  • request.getSession()
  • //设置一个 session 属性
  • session.setAttribute()
  • //读取一个 session 属性
  • session.getAttribute()

 

1. 在视图函数中使用 @CookieValue 修饰形参, 可注入一个 cookie 属性值.

    @RequestMapping("/read")
    @ResponseBody
    public String read(@CookieValue(value = "foo", defaultValue = "hello") String fooCookie) {
        System.out.println(fooCookie);
        return fooCookie;
    }

2. 使用 HttpServletResponse.addCookie() 完成 cookie 的写入. 

    @RequestMapping("/write")
    @ResponseBody
    public String write(HttpServletResponse response) {
        Cookie foo = new Cookie("foo", "bar"); //bake cookie
        foo.setMaxAge(1000); //set expire time to 1000 sec
        response.addCookie(foo); //put cookie in response
        return "write done";
    }

 

相关文章:

  • bzoj3295: [Cqoi2011]动态逆序对
  • 北大、微软提出NGra:高效大规模图神经网络计算
  • SQL Server事务日志管理的进阶,第5级:在完全恢复模式下管理日志
  • zabbix3.4 端口和进程监控配置
  • Java 面试之技术框架
  • db cursor
  • Kubeflow 公布 1.0 路线图:2019 年实现 API 稳定
  • Finale
  • String不得不说的那些事
  • 利用React 16.6新特性优化应用性能
  • ajax的19道经典面试题
  • 大数据就业前景,分析的太到位了
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • 程序员的本质
  • matlab练习程序(直方图匹配)
  • codis proxy处理流程
  • HTML5新特性总结
  • Java方法详解
  • Java应用性能调优
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • js作用域和this的理解
  • magento2项目上线注意事项
  • nginx 负载服务器优化
  • SpiderData 2019年2月16日 DApp数据排行榜
  • Vue 2.3、2.4 知识点小结
  • vue-router 实现分析
  • Zepto.js源码学习之二
  • 多线程 start 和 run 方法到底有什么区别?
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 为视图添加丝滑的水波纹
  • 小而合理的前端理论:rscss和rsjs
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​​​​​​​​​​​​​​Γ函数
  • ​520就是要宠粉,你的心头书我买单
  • ​第20课 在Android Native开发中加入新的C++类
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • ###STL(标准模板库)
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #数学建模# 线性规划问题的Matlab求解
  • $.ajax()方法详解
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (12)目标检测_SSD基于pytorch搭建代码
  • (4.10~4.16)
  • (安卓)跳转应用市场APP详情页的方式
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (剑指Offer)面试题34:丑数
  • (三) diretfbrc详解
  • (五)关系数据库标准语言SQL
  • (学习日记)2024.01.09
  • (一)基于IDEA的JAVA基础1
  • (转)nsfocus-绿盟科技笔试题目
  • ./configure、make、make install 命令