理解 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";
}
==================================
ajax 调用过程中是否会附加cookie信息?
==================================
如果 web 应用通过 jquery ajax 调用后台 api url, 调用过程是否会附加cookie信息, 要看情况:
1. 如果是同域, ajax 请求会自动带上本域的cookie, 这台web服务器本身也有相应的 session 信息, 所以ajax请求自然能通过 session-cookie 完成身份验证, 整个过程非常自然.
2. 如果 ajax调用的api 是另一个域下的url, 因为不是同域, 需要手动在ajax调用时加上cookie, 可参考:https://blog.csdn.net/wzl002/article/details/51441704, 服务器端返回response也需要做相应的处理, 另外也需要引入分布式session存储.
==================================
SSO/JWT/Session/OAuth2和web项目安全检查的关系
==================================
1. OAuth2: 它是一个第三方认证机制, 适合To C的应用场景, 比如我们开发一个app, 可以借用微信/微博用户认证开放接口, 达到免注册登陆, 企业内部系统一般没必要引入该技术.
2. SSO: 有两个作用, 1: 保持登陆状态, 2: 识别 username
3. JWT: 它是一个 token 生成技术, 可以包含 username 等信息.
4. Session: Session 一般用在web application中, 用来识别访问者.
一般项目认证方式:
1. 对于 web application 项目, 一般使用 Session 来识别访问者, 开发容易, 可以采用普通的 Login form 登陆, 也可以采用SSO登陆.
SSO 登陆详细过程, 可参考张开涛博客<<shiro 单点登录>> https://www.vxzsk.com/1197.html
2. 对于微服务项目, 一般和 OAuth2/Session 无关, 多数基于 jwt 的无状态认证机制, 通过 jwt 来识别访问者, 不过还是推荐将jwt前移到api 网关较好, 微服务仅仅关注业务逻辑.
完整微服务认证过程是: SSO登陆验证通过后, SSO回调到统一auth服务来生成一个jwt token, 并传给客户端, 客户端可将 jwt token保存到本地(web 客户端可保存到 cookie 中), 每次客户端请求需要将 jwt token 加到 http Authorization header上, 服务器端仅需要 jwt 算法就可以完成验证(通常不会再查询数据库验证), 并能提取 username 信息.
详细过程和源码, 可参考下面几个文章:
张开涛博客<<shiro 无状态Web集成>>
https://www.vxzsk.com/1233.html
详细shiro jwt 构建无状态分布式鉴权体系
https://www.jianshu.com/p/0a5d3d07a151
https://www.jianshu.com/p/b0a577708a7b
Shiro+JWT+Spring Boot Restful简易教程
https://www.jianshu.com/p/f37f8c295057
理解 Web 中的Session的更多相关文章
- java web 中分布式 session 的实现
已经有现成的库现实现分布式的 session 管理: 1.memcached-session-manager. 2.tomcat-redis-session-manager. 3.spring-ses ...
- java web中的session属性范围和request属性范围
首先必需要了解client跳转和server端跳转的差别: client跳转: response.sendRedict(String path).地址栏发生改变. 不能传递request属性. ser ...
- Java Web Application使Session永不失效(利用cookie隐藏登录)
在做 Web Application 时,因为 Web Project 有 session 自动失效的问题,所以如何让用户登录一次系统就能长时间运行三个月,就是个问题. 后来,看到 session 失 ...
- 在web中使用shiro(会话管理,登出,shiro标签库的使用)
在shiro的主配置文件中配置,登出的请求经过的过滤器就可以了,在shiro的过滤器中有一个名称为logout的过滤 器专门为我们处理登出请求: 一.shiro会话管理器 shiro中也提供了类似于w ...
- 巨人大哥谈Web应用中的Session(session详解)
巨人大哥谈Web应用中的Session(session详解) 虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术. ...
- 【Web】关于Session过期/失效的理解
一直好奇关于Session的过期,一种说法是关闭浏览器即Session失效,另一种说法是可以设置Session的过期时间,时间到了自动过期. 这两种说法到底是怎么回事?Session过期跟Cookie ...
- C# Web中Session的使用
1. 关于使用之前要注意的: 在使用session之前,一定要注意继承自System.Web.UI.Page,或在使用session时加上System.Web.HttpContext.Current: ...
- C# asp.net IIS 在web.config和IIS中设置Session过期时间
有时候在web.config设置sessionState 或者类文件里设置Session.Timeout,在IIS里访问时每次都是达不到时间就超时,原因是因为在IIS中设置了Session的超时时间, ...
- 关于web会话中的session过期时间的设置
关于web会话中的session过期时间的设置 1.操作系统: 步骤:开始——〉管理工具——〉Internet信息服务(IIS)管理器——〉网站——〉默认网站——〉右键“属性”——〉主目录——〉配置— ...
随机推荐
- 比较两个slice、struct或者map是否相等
我们可以直接使用reflect.DeepEqual来比较两个slice.struct或者map是否相等 package main import ( "fmt" "refl ...
- Extending the Yahoo! Streaming Benchmark
could accomplish with Flink back at Twitter. I had an application in mind that I knew I could make m ...
- SpringIOC和AOP简单概述
Spring学习:主要学习两大块IOC AOP 一.IOC IOC:控制反转(也可以叫做依赖注入)的基本认识: 当某个Java对象(调用者)需要调用另一个Java对象(被依赖对象)的方法时 ...
- CentOS 7 安装Kubernetes(单机版)
一.关闭CentOS自带的防火墙服务 # systemctl disable firewalld # systemctl stop firewalld 二.安装etcd和Kubernetes软件( ...
- OpenCV 与 OpenGL 的关系是什么?
OpenCV是 Open Source Computer Vision LibraryOpenGL是 Open Graphics LibraryOpenCV主要是提供图像处理和视频处理的基础算法库,还 ...
- 014_浅说 XSS和CSRF
在 Web 安全领域中,XSS 和 CSRF 是最常见的攻击方式.本文将会简单介绍 XSS 和 CSRF 的攻防问题. 声明:本文的示例仅用于演示相关的攻击原理 XSS XSS,即 Cross Sit ...
- iframe 自适应
<iframe src="http://www.fulibac.com" id="myiframe" scrolling="no" o ...
- Web Storage和cookie
Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生; Web Storage的概念和cookie相似,区别是它是为了更大容 ...
- JAVA项目启动正常,无法访问
若是一般项目web.xml问题 springboot是静态资源问题
- json 百分比转化
NumberFormat number = NumberFormat.getPercentInstance(); number.setMaximumFractionDigits(0);//设置小数点后 ...