
- 外文名
- 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接口中的常用方法
方法声明 功能描述 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:
request.getSession(); // session的获取
session.setAttribute(key,value);// session 存储数据
session.getAttribute(key);// session 获取存储对应的数据
session.invalidate(); // session对象销毁
session.removeAttribute(key);// 将目标对象从session中移除
1. 保存购物车数据
2. 保存用户浏览器记录数据
3. 保存用户登录信息数据
4. 保存验证码
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被盗用·,为此浏览器为cookie设置了一些安全属性来限制对于cookie的操作以及cookie的发送。
- httponly
- secure
- samesite
httponly限制了cookie只能用于HTTP请求时携带,而不能使用javascript操作,如document.cookie操作cookie,这样可以有效保护cookie不被XSS的注入js脚本盗取。
secure限制了cookie只能用于HTTPS请求时携带,这样保护了cookie不会在网络中明文传输,即避免了网络传输被截获后,黑客可以直接得到明文cookie。
samesite默认限制了cookie在大部分HTTP请求中只能用于同站发送,比如浏览器网页请求的:
- 服务器接口的IP地址和cookie的domain设置的IP地址相同,则cookie可以发送
- 服务器接口的域名和cookie的domain设置的域名相同,则cookie可以发送
- 服务器接口的域名是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工作流程如下:
- 浏览器发送登录请求到服务器,服务器基于登录请求中的用户名和密码进行身份认证,认证成功后,将用户名和密码保存在服务器本地内存或硬盘上,并为其创造一个随机唯一串作为查询索引,我们将随机唯一串称为sessionid。
- 服务器将sessionid作为响应头中Set-Cookie的值交给浏览器保存
- 浏览器再次请求服务器,自动携带保存的cookie(即sessionid)到请求头Cookie中
- 服务器受到请求,解析出请求头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.id req.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 的相关用法。
简单回顾总结就是:
- cookie 是让程序员能够在客户端持久存储数据的一种机制
- 存储的是程序员自己定义的键值对
- 通过服务器响应 set-cookie 这个 header 获取到 cookie 的值,并保存到本地
- 下一次请求就会带上 cookie ,发送给服务器
用户输入账号密码登录后,再次登录不需要再次输入账号密码就可以直接的登录成功就是依靠 cookie 来实现的
但是有关于用户的信息实际上是非常多的,比如访问网站的浏览记录,上次访问网站的时间等等,这么多的信息在服务器客户端之间传输来又去的非常浪费带宽。更何况 cookie 的存储容量又是有限的,一个站点最多保留20个 cookie,这么多的用户信息没有办法单纯的依靠 cookie 来保存在客户端,因此将数据保存到服务器端才是比较科学的做法。
二、session 工作原理
因为要将信息存储在服务器端,就引入了
会话机制 session
。session是服务端存储的一个对象,主要用来存储所有访问过客户端网页的用户信息(也可以存储其他信息),从而实现保持用户会话状态。但是服务器重启时,内存会被销毁,存储的用户信息也就消失了。
面试题:详述 session 工作原理
- 当客户端登录完成后,就会在服务器端产生一个 session,,实际上是一个键值对,
key 是 sessionId
(随机唯一的字符串),value
保存的就是身份信息(HttpSession 对象
)。服务器端将这些键值对形式的会话通过hash 表
的形式管理起来 - 此时服务器端就会将
sessionId
返回到客户端浏览器。 - 客户端将 sessionId 存储在浏览器的
cookie
中 - 当用户再次登录的时候,就会拥有对应的 sessionId ,就将该 sessionId 发送到服务器端请求登录
- 服务器端在内存中找到对应的 sessionId 就完成登录,如果找不到,说明还没有登录(每个用户登录都会生成一个会话),就返回登录页面让用户进行登录
session 工作原理和校园卡差不多,校园卡中实际上并没有保存太多的内容,但是有着它在学校中拥有的唯一的信息——学号。因此你(客户端)拎着这张卡,通过学号(相当于sessionId)就可以在系统中(服务器)搜索到有关于你的相关具体学生信息,就可以凭借卡进出宿舍大门,在图书馆借书,在食堂吃饭等等。
三、常用的方法
3.1 getSession()
这是 HttpServletRequest 类中的方法,作用是在服务器中获取会话。
HttpSession session = req.getSession(true); HttpSession session = req.getSession(false);
参数为true
- 查看请求中是否有 sessionId ,并判断其合法性
- 如果有 sessionId 且合法,就根据该 sessionId 找到对应的 HttpSession对象
- 如果没有 sessionId,就
生成一个唯一的 sessionId
,创建一个HttpSession 对象,把这一组键值对插入到服务器管理 session 的 hash 表中,把 sessionId 通过 Set-Cookie 在响应中返回给客户端
参数为false
- 查看请求中是否有 sessionId ,并判断其合法性
- 如果有 sessionId 且合法,就根据该 sessionId 找到对应的 HttpSession对象
- 如果没有 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 表单简单的构造一个登录页面
-
action=“login” 中,login是处理 post 请求的 Servlet 程序,用于判断用户登录是否成功
-
method="post"指的是请求的方法时POST
-
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路径,实现访问次数的计数 } }
流程总结:
- 读取到用户提交的用户名和密码
- 对用户名及密码的合法性进行校验
- 判断是否登录成功
- 创建会话,在 HttpSession 对象中保存一些信息
- 重定向到指定页面
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 部分
响应:
状态码
302
,Location: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:521.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 案例
- 在 Deployment 选项卡下,设置本地 tomcat9100的Application context 为/p2p
- 在 Deployment 选 项卡下 ,设置本地 tomcat9200的Application context 为/shop
- 在idea中重新启动本地的两台 tomcat 服务器
- 在浏览器中访问 tomcat9100(p2p), 设置 session
session设置成功
- 在浏览器中访问 tomcat9200(shop),获取 session
获取不到session
- 分析 Session 共享失败原因
- 我们通过浏览器提供的开发人员工具可以发现,这两个请求的 cookie 的路径(path)不一致(如下图),虽然我们已经加了Spring Session共享机制,但是后台服务器认为这是两个不同的会话(session),可以通过 Redis 客户端工具(Redis Destop Mananger) 查看,先清空,然后访问,发现是维护了两个不同的 session,所以不能实现共享。
- 同样redis中也存储了两个不同的session对象,其中一个session对象中没有sessionAttr属性。
- 解决方案:设置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>
- 重新进行测试发现两个不同项目的session数据也能实现共享,且两个请求的cookie路径(path)相同均为" / "。且此时redis中也只有一个session对象。
3.同根域名不同二级子域名下的项目实现Session 共享
同一个根域名,不同的二级子域名,比如北京和武汉的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:28CSRF xss利用站点内的信任用户,csrf通过伪装成受信任用户请求受信任的网站,即攻击者利用目标用户的身份,以目标用户的名义执行某些非法操作 ...session 是以文本形式存储到服务端的,php 自动修改 sessi -
SpringSession的源码解析(生成session,保存session,写入cookie全流程分析)
2020-04-12 23:57:57本文按照代码运行的顺序,一步步分析了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:591 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:4416.2 使用Session 16.1 使用Cookie 1、首先,获取Cookie 有两种方法,具体如下: //使用request()->cookie 获取解密后的cookie 信息 return request()->cookie('laravel_session'); //使用Cookie::也可以获取,... -
SpringBoot2.x集成spring session redis实现session共享
2020-02-10 08:44:23使用 Redis 实现 Session 共享 1 什么是 Session 由于 HTTP 协议是无状态的协议,因而服务端需要记录用户的状态时,就需要用某种机制来识具体的用户。Session 是另一种记录客户状态的机制,不同的是 Cookie 保存在... -
Spring全家桶之SpringSession
2019-09-15 20:11:52SpringSession和SpringSession MongoDB相关的实用知识的整理 ,希望能够帮助更多人~~~ -
SpringSession的源码解析(从Cookie中读取Sessionid,根据sessionid查询信息全流程分析)
2020-04-17 21:11:50前言 上一篇我们介绍了SpringSession中Session的保存过程,今天我们接着来看看Session的读取过程。相对保存过程,读取过程相对比较简单。 读取过程的时序图 ... -
什么是session?什么是cookie?session和cookie有什么区别?
2019-05-20 10:34:29【什么是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:531.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:004G EPS Session与5G PDU Session什么叫Session?移动通信网络的Session 什么叫Session? Session,这个是一个非常广的概念,需要在特定的领域里加以限定,但即便是通信领域,Session也会因为适用于不同的通信场景而... -
【第一篇】Spring-Session实现Session共享入门教程
2018-03-06 16:17:38本篇开始学习Spring-Session相关的一些知识学习整理,让我们开始吧! Spring-Session介绍 Spring-Session使用的场景? HttpSession是通过Servlet容器进行创建和管理的,在单机环境中。通过Http请求创建的... -
sqlalchemy 系列教程五-Session和scopedsession
2019-05-13 19:27:09sqlalchemy 中 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 - 使用Spring Session从零到一构建分布式session
2021-02-15 23:50:25文章目录快速入门 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 的机器挂了, 所有人都得重新...