- 每一个HttpSession有一个唯一的标识SessionID,只要同一次打开的浏览器通过request获取到session都是同一个 。
- WEB容器默认的是用Cookie机制保存SessionID到客户端,并将此Cookie设置为关闭浏览器失效,Cookie名称为:JSESSIONID
- 每次请求通过读取Cookie中的SessionID获取相对应的Session会话
- HttpSession的数据保存在服务器端,所以不要保存数据量耗资源很大的数据资源,必要时可以将属性移除或者设置为失效
- HttpSession可以通过 setMaxInactiveInterval() 设置失效时间(秒)或者在 web.xml 中配置
<session-config> <!--单位:分钟--> <session-timeout>30</session-timeout></session-config>
session 的创建时机一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用 HttpServletRequest.getSession(true) 这样的语句时才被创建 。Session 何时被删除综合前面的讨论,session 在下列情况下被删除
- 程序调用 HttpSession.invalidate();
- 距离上一次收到客户端发送的 session id时 间间隔超过了session的超时设置;
- 服务器进程被停止(非持久session)
这个信息会被写回到客户端的 cookie 中,并且后续的请求都会携带 。
比如我测试时的 JSESSIONID:
Cookie: JSESSIONID=8AE65FE9AEB0AA6053FADF9ED7AEE544
可以发现实际上 JSESSIONID 是非常依赖客户端 cookie 的,那么问题来了,如果用户禁用了 cookie 怎么办?客户端禁用 cookiecookie 是用户自己的口袋,如果用户有一天把口袋全部封死也是有可能的 。
如果客户端禁用了 cookie,一般有两种解决方案 。
隐藏域我们将 JSESSIONID 的值传入到页面中,放入一个隐藏的 input 框中,每次请求带上这个参数 。
<form name="testform" action="/xxx"> <input type="hidden" name="jsessionid" value=https://www.isolves.com/it/cxkf/bk/2021-01-07/"8AE65FE9AEB0AA6053FADF9ED7AEE544"/>
后端通过 req.getParameter("jsessionid") 的方式获取到这个 jsessionid 信息 。URL 重写URL地址重写的原理是将该用户Session的id信息重写到URL地址中 。服务器能够解析重写后的URL获取Session的id 。
这样即使客户端不支持Cookie,也可以使用Session来记录用户状态 。
encodeURL() 方法在使用时,会首先判断Session是否启用,如果未启用,直接返回url 。
然后判断客户端是否启用Cookie,如果未启用,则将参数url中加入SessionID信息,然后返回修改的URL;如果启用,直接返回参数url 。
就像老马前面代码写的一样:
// 后端会根据页面是否禁用 cookie,选择是否将 sessionId 放在 url 后面String url = resp.encodeURL("/session/get");out.println("<a href=https://www.isolves.com/it/cxkf/bk/2021-01-07/'"+url+"'>获取 session 信息");
如果我们禁用 cookie,链接的地址就会变成:http://localhost:8080/session/get;jsessionid=3E2EEB9840F2566EDB3085BA392AE6CB
;jsessionid=3E2EEB9840F2566EDB3085BA392AE6CB 这个是 encodeURL 自己加上去的,这样我们就可以像原来一样处理 session id 了 。连锁店的机遇与挑战当目前为止,你作为一家店的老板已经可以轻松的掌握客户的信息了 。
哪怕用户把自己的口袋封死 。
随着你的生意越来越好,你的店从一家门面,变成了多家连锁店 。
新的问题又来了,一个用户去了其中的一家,当到另外一家店面的时候,如何得到用户对应的信息呢?
连锁店
这个就涉及到分布式系统的 session 共享问题 。
其实解决问题的思路也是从两个角度出发:
(1)用户的角度
在用户的口袋中放着验证信息 。
不过需要考虑信息被恶意修改等,这方面 JWT 做的比较优秀 。
可以参考:
分布式系统 session 共享解决方案 JWT 实战笔记
(2)服务者的角度
我们作为连锁店,只需要把各个店里的商户信息共享即可 。
至于共享到哪里,可以是 redis 也可以是数据库 。
这方面 spring session 设计的比较优秀,可以参考:
springboot整合redis实现分布式session
推荐阅读
- 2020年Web Apps用户界面发展趋势:组件统治一切
- Json Web Token 2020 攻击指南
- 论淘宝搜索推荐算法排序机制及2021年搜索变化的方向
- 用webpack创建vue项目/脚手架
- 华为防火墙配置:登录Web配置界面
- 小程序websocket开发指南
- 免越狱免签名苹果ioswebAPP打包配置实用工具
- 如何阻止对Web应用程序发起的DoS攻击?
- 一文秒懂Web框架基础之WSGI协议
- Web端非常有用的一个文件上传插件——FilePond