注:以下内容基于以tomcat作为web服务器
session是http协议无状态问题的常见解决方案之一 ,用户登录成功之后,把用户信息保存到session(默认储存在服务端的内存)。对于浏览器发起的HTTP请求,可以根据session中是否存在用户信息判断用户是否登录,也方便业务逻辑中获取当前会话用户信息。
服务端创建session时,会生成JSESSIONID作为唯一标识,并将一个key为"JSESSIONID"的cookie返回给前端(前提是浏览器支持cookie),之后,根据浏览器发起请求时携带的JSESSIONID判断用户身份。
tomcat的JSESSIONID生成的机制是一个随机数加时间加上jvm的id值,jvm的id值会根据服务器的硬件信息计算得来,因此不同jvm的id值都是唯一的。
当后端显式调用request.getSession()或request.getSession(true)时,会创建session(注意:需要显式调用,spring或tomcat不会自动生成)
request.getSession()有个重载方法request.getSession(boolean create)
create为true表示,若可以根据前端cookie中的JSESSIONID找到对应的session,则返回该session,否则重新创建一个session,并把新的JSESSIONID返回给前端。
create为false表示,若可以根据前端cookie中的JSESSIONID找到对应的session,则返回该session,否则返回null。
request.getSession()等价于request.getSession(true)
session是http协议无状态问题的常见解决方案之一,但在用户量大,或者分布式系统等场景下,该方案有许多弊端。
1.session默认储存在服务端内存,用户量大时占用内存多
2.需要处理session共享,用户在一台服务器登录后,集群内其他机器没有该用户的session,需要用某些方式实现session共享,并保持一致性,即同步修改所有机器的session
3.同样的数据保存在多台服务器,数据冗余
4.如果使用cookie发送JSESSIONID到服务端,则不支持跨域请求
5.如果浏览器cookie被禁用,就需要用其余方式保存JSESSIONID
6.如果session没有持久化,重启服务器后session就没了
修改负载均衡策略为按ip负载(即同一个ip只访问同一台机器),这样就绕开了session共享的问题(默认策略一般是轮询)
弊端
按ip负载策略和轮询策略,本质上是按用户负载和按请求负载,这两种策略的区别在于, 按请求负载更加均衡 ,比如A、B服务器都有20个用户,A服务器的20个用户相比B服务器更加活跃,那么A服务器的压力就更大。
集成spring-session-redis(网上很多教程),先集成redis,然后在启动类加上@EnableRedisHttpSession注解,这样操作session时,会自动把数据持久化到redis集群
tomcat 配置session复制(未做了解)
同时使用token+session,token用于接口鉴权,session用于保存用户信息。
增加一个拦截器,在找不到session时,根据token反解析出用户信息,然后存入session。
(一般公司会有统一的用户中心,提供校验token并返回用户身份的接口)
严格来说,本方案不算是session共享方案,因为不同服务端的session id不一致,每次请求不同服务器,带上来的session id在本服务器找不到,就产生新的session,直到有效期到期才销毁,严重浪费内存
1.最常见的方式: cookie
2.如果cookie被禁止,可以用URL重写技术,把session id拼接到URL中
3.在表单添加隐藏字段,提交表单时把session id传到服务端
先说结论:如果服务器是集群,且没有配置会话保持,同一个浏览器窗口的JSESSIONID就会变化
用户在A服务器登录成功后,A服务器把key为JSESSIONID的cookie返回给用户,然后携带该JSESSIONID请求B服务器,B服务器找不到该JSESSIONID对应的session,就会创建新的session,把新的JSESSIONID返回给用户。
取决于JSESSIONID的保存方式
如果保存在cookie,要看cookie有没有设置有效期,如果没设有效期,重启浏览器cookie就没了,如果设了有效期,重启浏览器cookie还在。
如果使用URL重写或表单隐藏字段的方式,要看JSESSION具体保存在哪
对于单机应用,JSESSIONID可以用于校验接口(类似于token),后端如果能根据JSESSIONID获取到对应session(即request.getSession(false)不为空),说明该请求有效。但是服务器一旦重启,用户登录就失效了,因为session放在内存中。
如果使用token做接口校验,不仅可以适用于分布式应用,后端重启也不会影响用户的登录态。
session是存储在服务器端的,cookie是存储在客户端的,所以session的安全性要高于cookie。再者,我们获取的session里的信息是通过存放在会话cookie里的sessionId获取的。
因为session是存放在服务器里的,所以session里的东西不断增加会增加服务器的负担,我们会把一些重要的东西放在session里,不太重要的放在客户端cookie里。
cookie分为两大类,一个是会话cookie和持久化cookie,他们的生命周期和浏览器是一致的,浏览器关了会话cooki也就消失了,而持久化会存储在客户端硬盘中。
Session存储在服务器的内存中。
浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。它存储在服务器的内存中,tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,Redis等。
客户端只保存sessionid到cookie中,而不会保存session,session销毁只能通过invalidate或超时,关掉浏览器并不会关闭session。
session机制
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识——称为session id,如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个)。
如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。
以上内容参考 百度百科--session(计算机术语)
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)