其他更多 java 基础文章: java 基础学习(目录) https://www.jianshu.com/p/43b55fd63b3f
一, 会话概述
1.1, 什么是会话?
会话可简单理解为: 用户开一个浏览器, 点击多个超链接, 访问服务器多个 web 资源, 然后关闭浏览器, 整个过程称之为一个会话其中不管浏览器发送多少请求, 都视为一次会话, 直到浏览器关闭, 本次会话结束.
其中注意, 一个浏览器就相当于一部电话, 如果使用火狐浏览器, 访问服务器, 就是一次会话了, 然后打开 google 浏览器, 访问服务器, 这是另一个会话, 虽然是在同一台电脑, 同一个用户在访问, 但是, 这是两次不同的会话.
1.2, 会话机制
Web 程序中常用的技术, 用来跟踪用户的整个会话. 常用的会话跟踪技术是 Cookie 与 Session.Cookie 通过在客户端记录信息确定用户身份, Session 通过在服务器端记录信息确定用户身份.
二, Cookie
Cookie 是客户端技术, 程序把每个用户的数据以 cookie 的形式写给用户各自的浏览器. 当用户使用浏览器再去访问服务器中的 Web 资源时, 就会带着各自的数据去. 这样, Web 资源处理的就是用户各自的数据了. 由于 cookie 是由客户端浏览器保存和携带的, 所以称之为客户端技术
2.1,Cookie 的工作流程
1)servlet 创建 cookie, 保存少量数据, 发送浏览器.
2)浏览器获得服务器发送的 cookie 数据, 将自动的保存到浏览器端.
3)下次访问时, 浏览器将自动携带 cookie 数据发送给服务器.
2.2,Cookie 特点
1)每一个 cookie 文件大小: 4kb , 如果超过 4kb 浏览器不识别
2)一个 Web 站点(Web 项目): 发送 20 个
3)一个浏览器保存总大小: 300 个
4)cookie 不安全, 可能泄露用户信息. 浏览器支持禁用 cookie 操作.
5) 默认情况生命周期: 与浏览器会话一样, 当浏览器关闭时 cookie 销毁的.--- 临时 cookie
- cookie.setMaxAge(expiry); // 设置 cookie 被浏览器保存的时间.
expiry: 单位秒, 默认为 - 1,
expiry=-1: 代表浏览器关闭后, 也就是会话结束后, cookie 就失效了, 也就没有了.
expiry>0: 代表浏览器关闭后, cookie 不会失效, 仍然存在. 并且会将 cookie 保存到硬盘中, 直到设置时间过期才会被浏览器自动删除,
expiry=0: 删除 cookie. 不管是之前的 expiry=-1 还是 expiry>0, 当设置 expiry=0 时, cookie 都会被浏览器给删除.
2.3,Cookie 操作
操作 cookie
1)创建 cookie:new Cookie(name,value)
2)发送 cookie 到浏览器: HttpServletResponse.addCookie(Cookie)
3)servlet 接收 cookie:HttpServletRequest.getCookies() 浏览器发送的所有 cookie
cookie API
getName() 获得名称, cookie 中的 key
getValue() 获得值, cookie 中的 value
setValue(java.lang.String newValue) 设置内容, 用于修改 key 对应的 value 值.
setMaxAge(int expiry) 设置有效时间[]
setPath(java.lang.String uri) 设置路径[]
setDomain(java.lang.String pattern) 设置域名 , 一般无效, 有浏览器自动设置, setDomain(".zyh.com")
www.zyh.com / bbs.zyh.com 都可以访问
a.b.zyh.com 无法访问
作用: 设置 cookie 的作用范围, 域名 + 路径在一起就构成了 cookie 的作用范围, 上面单独设置的 setPath 有用, 是因为有浏览器自动设置该域名属性, 但是我们必须知道有这么个属性进行域名设置的
isHttpOnly() 是否只是 http 协议使用. 只能 servlet 的通过 getCookies()获得, JavaScript 不能获得.
setComment(java.lang.String purpose) (了解) // 对该 cookie 进行描述的信息(说明作用), 浏览器显示 cookie 信息时能看到
setSecure(boolean flag) (了解) 是否使用安全传输协议. 为 true 时, 只有当是 https 请求连接时 cookie 才会发送给服务器端, 而 http 时不会, 但是服务端还是可以发送给浏览端的.
setVersion(int v) (了解) 参数为 0(传统 Netscape cookie 规范编译)或 1(RFC 2109 规范编译). 这个没用到, 不是很懂
注意事项
cookie 不能发送中文, 如果要发送中文, 就需要进行特别处理.
- Cookie cookie = new Cookie("country", URLEncoder.encode("中国", "UTF-8"));
- response.addCookie(cookie);
- // 经过 URLEncoding 就要 URLDecoding
- String value = URLDecoder.decode(cookies[i].getValue(), "UTF-8");
三, Session
在 Web 开发中, 服务器可以为每个用户浏览器创建一个会话对象(session 对象), 注意: 一个浏览器独占一个 session 对象(默认情况下)
因此, 在需要保存用户数据时, 服务器程序可以把用户数据写到用户浏览器独占的 session 中, 当用户使用浏览器访问其它程序时, 其它程序可以从用户的 session 中取出该用户的数据, 为用户服务.
3.1,Session 的原理
首先浏览器请求服务器访问 Web 站点时, 程序需要为客户端的请求创建一个 session 的时候, 服务器首先会检查这个客户端请求是否已经包含了一个 session 标识, 称为 SESSIONID
如果已经包含了一个 sessionid 则说明以前已经为此客户端创建过 session, 服务器就按照 sessionid 把这个 session 检索出来使用, 如果客户端请求不包含 session id, 则服务器为此客户端创建一个 session 并且生成一个与此 session 相关联的 session id,sessionid 的值应该是一个既不会重复, 又不容易被找到规律以仿造的字符串, 这个 sessionid 将在本次响应中返回到客户端保存, 保存这个 sessionid 的方式一般就是 cookie.
这样在交互的过程中, 浏览器可以自动的按照规则把这个标识发回给服务器, 服务器根据这个 sessionid 就可以找得到对应的 session, 又回到了步骤 1.
3.2,Session 的生命周期
常常听到这样一种误解 "只要关闭浏览器, session 就消失了". 其实可以想象一下会员卡的例子, 除非顾客主动对店家提出销卡, 否则店家绝对不会轻易删除顾客的资料. 对 session 来说也是一样的, 除非程序通知服务器删除一个 session, 否则服务器会一直保留, 程序一般都是在用户做 log off 的时候发个指令去删除 session. 然而浏览器从来不会主动在关闭之前通知服务器它将要关闭, 因此服务器根本不会有机会知道浏览器已经关闭, 之所以会有这种错觉, 是大部分 session 机制都使用会话 cookie 来保存 session id, 而关闭浏览器后这个 session id 就消失了, 再次连接服务器时也就无法找到原来的 session. 如果服务器设置的 cookie 被保存到硬盘上, 或者使用某种手段改写浏览器发出的 HTTP 请求头, 把原来的 session id 发送给服务器, 则再次打开浏览器仍然能够找到原来的 session.
恰恰是由于关闭浏览器不会导致 session 被删除, 迫使服务器为 seesion 设置了一个失效时间, 一般是 30 分钟, 当距离客户端上一次使用 session 的时间超过这个失效时间时, 服务器就可以认为客户端已经停止了活动, 才会把 session 删除以节省存储空间. Session 生成后, 只要用户继续访问, 服务器就会更新 Session 的最后访问时间, 无论是否对 Session 进行读写, 服务器都会认为 Session 活跃了一次, 重新开始计算失效时间.
我们也可以自己来控制 session 的有效时间:
session.invalidate()将 session 对象销毁
setMaxInactiveInterval(int interval) 设置有效时间, 单位秒
在 Web.xml 中配置 session 的有效时间:
- <session-config>
- <session-timeout>
- 30
- </session-timeout>
- 单位: 分钟
- <session-config>
所以, 讨论了这么久, session 的生命周期就是:
创建: Session 存储在服务器端, 一般放置在服务器的内存中 (为了高速存取),Sessinon 在用户访问第一次访问服务器时创建, 需要注意只有访问 JSP,Servlet 等程序时才会创建 Session, 只访问 html,IMAGE 等静态资源并不会创建 Session, 可调用 request.getSession(true) 强制生成 Session.
销毁:
1)超时, 默认 30 分钟
2)执行 API:session.invalidate()将 session 对象销毁, setMaxInactiveInterval(int interval) 设置有效时间, 单位: 秒
3)服务器非正常关闭(自杀, 直接将 JVM 马上关闭)
如果正常关闭, session 就会被持久化(写入到文件中, 因为 session 默认的超时时间为 30 分钟, 正常关闭后, 就会将 session 持久化, 等 30 分钟后, 就会被删除)
位置:D:\java\tomcat\apache-tomcat-7.0.53\work\Catalina\localhost\test01\SESSIONS.ser
3.3,session id 的 URL 重写
当浏览器将 cookie 禁用, 基于 cookie 的 session 将不能正常工作, 每次使用 request.getSession() 都将创建一个新的 session. 达不到 session 共享数据的目的, 但是我们知道原理, 只需要将 session id 传递给服务器 session 就可以正常工作的.
解决: 通过 URL 将 session id 传递给服务器: URL 重写
1)手动方式: url;jsessionid=....
2)API 方式:
encodeURL(java.lang.String url) 进行所有 URL 重写
encodeRedirectURL(java.lang.String url) 进行重定向 URL 重写
这两个用法基本一致, 只不过考虑特殊情况, 要访问的链接可能会被 Redirect 到其他 servlet 去进行处理, 这样你用上述方法带来的 session 的 id 信息不能被同时传送到其他 servlet. 这时候用 encodeRedirectURL()方法就可以了. 如果浏览器禁用 cooke,API 将自动追加 session id , 如果没有禁用, API 将不进行任何修改.
注意: 如果浏览器禁用 cookie,Web 项目的所有 url 都需进行重写. 否则 session 将不能正常工作.
当 cookie 禁用时:
四, Session 和 Cookie 的区别
4.1, 从存储方式上比较
Cookie 只能存储字符串, 如果要存储非 ASCII 字符串还要对其编码.
Session 可以存储任何类型的数据, 可以把 Session 看成是一个容器
4.2, 从隐私安全上比较
Cookie 存储在浏览器中, 对客户端是可见的. 信息容易泄露出去. 如果使用 Cookie, 最好将 Cookie 加密
Session 存储在服务器上, 对客户端是透明的. 不存在敏感信息泄露问题.
4.3, 从有效期上比较
Cookie 保存在硬盘中, 只需要设置 maxAge 属性为比较大的正整数, 即使关闭浏览器, Cookie 还是存在的
Session 的保存在服务器中, 设置 maxInactiveInterval 属性值来确定 Session 的有效期. 并且 Session 依赖于名为 JSESSIONID 的 Cookie, 该 Cookie 默认的 maxAge 属性为 - 1. 如果关闭了浏览器, 该 Session 虽然没有从服务器中消亡, 但也就失效了.
4.4, 从对服务器的负担比较
Session 是保存在服务器的, 每个用户都会产生一个 Session, 如果是并发访问的用户非常多, 是不能使用 Session 的, Session 会消耗大量的内存.
Cookie 是保存在客户端的. 不占用服务器的资源. 像 baidu,Sina 这样的大型网站, 一般都是使用 Cookie 来进行会话跟踪.
4.5, 从浏览器的支持上比较
如果浏览器禁用了 Cookie, 那么 Cookie 是无用的了!
如果浏览器禁用了 Cookie,Session 可以通过 URL 地址重写来进行会话跟踪.
4.6, 从跨域名上比较
Cookie 可以设置 domain 属性来实现跨域名
Session 只在当前的域名内有效, 不可夸域名
来源: https://juejin.im/post/5c160421e51d457e9f28a134