Javaweb重要知识点总结(三)Cookie 和 Session

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Javaweb重要知识点总结(三)Cookie 和 Session

1. Cookie 和Session 的区别


Cookie 是 web 服务器发送给浏览器的一块信息,浏览器会在本地一个文件中给每个 web 服务器存储 cookie。以后浏览器再给特定的 web 服务器发送请求时,同时会发送所有为该服务器存储的 cookie。

Session 是存储在 web 服务器端的一块信息。session 对象存储特定用户会话所需的属性及配置信息。当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。

Cookie和session的 不 同 点 :

1、无论客户端做怎样的设置,session 都能够正常工作。当客户端禁用 cookie 时将无法使用 cookie。

2、在存储的数据量方面:session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象。

2. session 共享怎么做的(分布式如何实现 session 共享)?


问题描述:一个用户在登录成功以后会把用户信息存储在 session 当中,这时 session 所在服务器为 server1,那么用户在 session 失效之前如果再次使用 app,那么可能会被路由到 server2,这时问题来了,server 没有该用户的session,所以需要用户重新登录,这时的用户体验会非常不好,所以我们想如何实现多台 server 之间共享 session, 让用户状态得以保存。

1、服务器实现的 session 复制或 session 共享,这种类型的共享 session 是和服务器紧密相关的,比如 webSphere 或 JBOSS 在搭建集群时候可以配置实现 session 复制或 session 共享,但是这种方式有一个致命的缺点,就是不好扩展和移植,比如我们更换服务器,那么就要修改服务器配置。

2、利用成熟的技术做session 复制,比如12306 使用的gemfire,比如常见的内存数据库如redis 或memorycache, 这类方案虽然比较普适,但是严重依赖于第三方,这样当第三方服务器出现问题的时候,那么将是应用的灾难。

3、将 session 维护在客户端,很容易想到就是利用 cookie,但是客户端存在风险,数据不安全,而且可以存放的数据量比较小,所以将 session 维护在客户端还要对 session 中的信息加密。

我们实现的方案可以说是第二种方案和第三种方案的合体,可以利用 gemfire 实现 session 复制共享,还可以将session 维护在 redis 中实现 session 共享,同时可以将 session 维护在客户端的 cookie 中,但是前提是数据要加密。这三种方式可以迅速切换,而不影响应用正常执行。我们在实践中,首选 gemfire 或者 redis 作为 session 共享的载体, 一旦 session 不稳定出现问题的时候,可以紧急切换 cookie 维护session 作为备用,不影响应用提供服务。

这里主要讲解 redis 和 cookie 方案,gemfire 比较复杂大家可以自行查看 gemfire 工作原理。利用 redis 做

session 共享,首先需要与业务逻辑代码解耦,不然 session 共享将没有意义,其次支持动态切换到客户端 cookie 模式。redis 的方案是,重写服务器中的 HttpSession 和 HttpServletRequest,首先实现HttpSession 接口,重写session 的所有方法,将 session 以 hash 值的方式存在 redis 中,一个 session 的 key 就是 sessionID,setAtrribute 重写之后就是更新 redis 中的数据,getAttribute 重写之后就是获取 redis 中的数据,等等需要将 HttpSession 的接口一一实现。

实现了 HttpSesson,那么我们先将该 session 类叫做 MySession(当然实践中不是这么命名的),当 MySession 出现之后问题才开始,怎么能在不影响业务逻辑代码的情况下,还能让原本的 request.getSession()获取到的是

MySession,而不是服务器原生的session。这里,我决定重写服务器的HttpServletRequet,这里先称为MyRequest, 但是这可不是单纯的重写,我需要在原生的 request 基础上重写,于是我决定在 filter 中,实现 request 的偷梁换柱, 我的思路是这样的,MyRequest 的构建器,必须以 request 作为参数,于是我在 filter 中将服务器原生的 request(也有可能是框架封装过的 request ) , 当做参数 new 出来一个 MyRequest , 并且 MyRequest 也实现了HttpServletRequest 接口,其实就是对原生 request 的一个增强,这里主要重写了几个 request 的方法,但是最重要的是重写了 request.getSession(),写到这里大家应该都明白为什么重写这个方法了吧,当然是为了获取 MySession,于是这样就在filter 中,偷偷的将原生的request 换成MyRequest 了,然后再将替换过的request 传入chan.doFilter(), 这样

filter 时候的代码都使用的是 MyRequest 了,同时对业务代码是透明的,业务代码获取 session 的方法仍然是request.getSession(),但其实获取到的已经是 MySession 了,这样对 session 的操作已经变成了对 redis 的操作。这样实现的好处有两个,第一开发人员不需要对 session 共享做任何关注,session 共享对用户是透明的;第二,filter 是可配置的,通过 filter 的方式可以将 session 共享做成一项可插拔的功能,没有任何侵入性。

这个时候已经实现了一套可插拔的 session 共享的框架了,但是我们想到如果 redis 服务出了问题,这时我们该怎么办呢,于是我们延续 redis 的想法,想到可以将 session 维护在客户端内(加密的 cookie),当然实现方法还是一样的,我们重写 HttpSession 接口,实现其所有方法,比如 setAttribute 就是写入 cookie,getAttribute 就是读取cookie,我们可以将重写的 session 称作 MySession2,这时怎么让开发人员透明的获取到 MySession2 呢,实现方法还是在 filter 内偷梁换柱,在 MyRequest 加一个判断,读取 sessionType 配置,如果 sessionType 是 redis 的,那么getSession 的时候获取到的是 MySession,如果 sessionType 是cookie 的,那么 getSession 的时候获取到的是MySession2,以此类推,用同样的方法就可以获取到 MySession 3,4,5,6 等等。

这样两种方式都有了,那么我们怎实现两种 session 共享方式的快速切换呢,刚刚我提到一个 sessionType,这是用来决定获取到session 的类型的,只要变换sessionType 就能实现两种session 共享方式的切换,但是sessionType 必须对所有的服务器都是一致的,如果不一致那将会出现比较严重的问题,我们目前是将 sessionType 维护在环境变量里,如果要切换 sessionType 就要重启每一台服务器,完成 session 共享的转换,但是当服务器太多的时候将是一种灾难。而且重启服务意味着服务的中断,所以这样的方式只适合服务器规模比较小,而且用户量比较少的情况,当服务器太多的时候,务必需要一种协调技术,能够让服务器能够及时获取切换的通知。基于这样的原因,我们选用

zookeeper 作为配置平台,每一台服务器都会订阅 zookeeper 上的配置,当我们切换 sessionType 之后,所有服务器都会订阅到修改之后的配置,那么切换就会立即生效,当然可能会有短暂的时间延迟,但这是可以接受的。

3. 在单点登录中,如果 cookie 被禁用了怎么办?


单点登录的原理是后端生成一个 session ID,然后设置到 cookie,后面的所有请求浏览器都会带上 cookie, 然后服务端从 cookie 里获取 session ID,再查询到用户信息。所以,保持登录的关键不是 cookie,而是通过

cookie 保存和传输的 session ID,其本质是能获取用户信息的数据。除了 cookie,还通常使用 HTTP 请求头来传输。但是这个请求头浏览器不会像 cookie 一样自动携带,需要手工处理。


著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
20天前
|
存储 安全 搜索推荐
理解Session和Cookie:Java Web开发中的用户状态管理
理解Session和Cookie:Java Web开发中的用户状态管理
41 4
|
23天前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
1月前
|
缓存 Java Spring
servlet和SpringBoot两种方式分别获取Cookie和Session方式比较(带源码) —— 图文并茂 两种方式获取Header
文章比较了在Servlet和Spring Boot中获取Cookie、Session和Header的方法,并提供了相应的代码实例,展示了两种方式在实际应用中的异同。
165 3
servlet和SpringBoot两种方式分别获取Cookie和Session方式比较(带源码) —— 图文并茂 两种方式获取Header
|
1月前
|
存储 安全 数据安全/隐私保护
Cookie 和 Session 的区别及使用 Session 进行身份验证的方法
【10月更文挑战第12天】总之,Cookie 和 Session 各有特点,在不同的场景中发挥着不同的作用。使用 Session 进行身份验证是常见的做法,通过合理的设计和管理,可以确保用户身份的安全和可靠验证。
22 1
|
2月前
|
存储 缓存 数据处理
php学习笔记-php会话控制,cookie,session的使用,cookie自动登录和session 图书上传信息添加和修改例子-day07
本文介绍了PHP会话控制及Web常用的预定义变量,包括`$_REQUEST`、`$_SERVER`、`$_COOKIE`和`$_SESSION`的用法和示例。涵盖了cookie的创建、使用、删除以及session的工作原理和使用,并通过图书上传的例子演示了session在实际应用中的使用。
php学习笔记-php会话控制,cookie,session的使用,cookie自动登录和session 图书上传信息添加和修改例子-day07
|
1月前
|
安全 Java 编译器
Java基础-知识点(二)
Java基础-知识点(二)
13 0
|
1月前
|
存储 缓存 安全
Java基础-知识点(一)
Java基础-知识点(一)
17 0
|
2月前
|
存储 前端开发 Java
JavaWeb基础7——会话技术Cookie&Session
会话技术、Cookie的发送和获取、存活时间、Session钝化与活化、销毁、用户登录注册“记住我”和“验证码”案例
JavaWeb基础7——会话技术Cookie&Session
|
2月前
|
存储 安全 NoSQL
Cookie、Session、Token 解析
Cookie、Session、Token 解析
62 0
|
3月前
|
存储 JavaScript 前端开发
Cookie 反制策略详解:Cookie加解密原理、Cookie和Session机制、Cookie hook、acw_sc__v2、jsl Cookie调试、重定向Cookie
Cookie 反制策略详解:Cookie加解密原理、Cookie和Session机制、Cookie hook、acw_sc__v2、jsl Cookie调试、重定向Cookie
210 1
下一篇
无影云桌面