副问题[/!--empirenews.page--]
HTTP 是一种无状态通讯协议,每个哀求之间彼此独立,处事器不能辨认曾经来过的哀求。而对付 Web 应用,它的勾当都是依靠某个状态的,好比用户登录,此时行使 HTTP 就必要它在一次登录哀求后,有为后续哀求提供已登录信息的手段。

办理步伐就是行使 Cookie,它由处事器返回给赏识器,赏识器缓存并在每次哀求时将 cookie 数据提交随处事器。Cookies 在哀求中以明文传输,且巨细限定 4KB,显然把全部状态数据生涯在赏识器是不靠谱的,主流做法是:
- 赏识器发出第一个哀求时,处事器为用户分派一个独一标识符,返回并存入赏识器的 Cookies 中
- 处事器内部维护一个全局的哀求状态库,并行使天生的独一标识符关联每个哀求的状态信息
- 赏识器后续发出的哀求,都将独一标识符提交给处事器,以便获取之前哀求的状态信息
为了利便打点,处事器把整个进程称为会话,并抽象成一个 Session 类,用于辨认和存储有关该用户的信息或状态。
接下来,将通过会话标识符的理会和天生,Session 的建设、烧毁和耐久化等题目,说明 Tomcat 的源码实现,版本行使的是 6.0.53。
1. 理会会话标识符
Cookie 作为最常用的会话跟踪机制,全部的 Servlet 容器都支持,Tomcat 也不破例,在 Tomcat 中,暗示存储会话标识符的 cookie 的尺度名字是 JSESSIONID。
假如假如赏识器不支持 Cookie,也可以行使以下步伐,记录标识符:
- URL 重写: 作为路径参数包括到 url 中,如 /path;JSESSIONID=xxx
- URL 哀求参数: 将会话独一标识作为查询参数添加到页面全部链接中,如 /path?JSESSIONID=xxx
- FORM 潜匿字段: 表单中行使一个潜匿字段存储独一值,随表单提交随处事器
Tomcat 就实现了从 URL 重写路径和 Cookie 中提取 JSESSIONID。在说明源码之前,起首看下配置 Cookie 的相应和带 Cookie 的哀求它们头域的要害信息:
- // 配置 Cookie
- HTTP/1.1 200 OK
- Server: Apache-Coyote/1.1
- Set-Cookie: JSESSIONID=56AE5B92C272EA4F5E0FBFEFE6936C91; Path=/examples
- Date: Sun, 12 May 2019 01:40:35 GMT
-
- // 提交 Cookie
- GET /examples/servlets/servlet/SessionExample HTTP/1.1
- Host: localhost:8080
- Cookie: JSESSIONID=56AE5B92C272EA4F5E0FBFEFE6936C91
1.1 从 URL 重写路径
一个包括会话 ID 路径参数的 URL 如下:
- http://localhost:8080/examples/SessionExample;JSESSIONID=1234;n=v/?x=x
简朴来看就是查找匹配分号和最后一个斜线之间的 JSESSIONID,究竟也是云云,只不外 Tomcat 操纵的是字节,焦点代码在 CoyoteAdapter.parsePathParameters() 要领,这里不在贴出。
1.2 从 Cookie 头域
触发 Cookie 理会的要领挪用如下:
- CoyoteAdapter.service(Request, Response)
- └─CoyoteAdapter.postParseRequest(Request, Request, Response, Response)
- └─CoyoteAdapter.parseSessionCookiesId(Request, Request)
- └─Cookies.getCookieCount()
- └─Cookies.processCookies(MimeHeaders)
- └─Cookies.processCookieHeader(byte[], int, int)
这个 processCookieHeader 操纵的是字节,理会看起来不直观,在 Tomcat 内部尚有一个被标志废弃的行使字符串理会的要领,有助于领略,代码如下:
- private void processCookieHeader( String cookieString ){
- // 多个 cookie 值以逗号支解
- StringTokenizer tok = new StringTokenizer(cookieString, ";", false);
- while (tok.hasMoreTokens()) {
- String token = tok.nextToken();
- // 获取等号的位置
- int i = token.indexOf("=");
- if (i > -1) {
- // 获取name 和 value 并去除空格
- String name = token.substring(0, i).trim();
- String value = token.substring(i+1, token.length()).trim();
- // RFC 2109 and bug 去除两端的双引号 "
- value=stripQuote( value );
- // 从内部 cookie 缓存池中获取一个 ServerCookie 工具
- ServerCookie cookie = addCookie();
- // 配置 name 和 value
- cookie.getName().setString(name);
- cookie.getValue().setString(value);
- } else {
- // we have a bad cookie.... just let it go
- }
- }
- }
理会完毕,接下来就是在 parseSessionCookiesId 要领遍历并实行匹配名称为 JSESSIONID 的 Cookie,假如存在,则将其值设为 Request 的 requestedSessionId,与内部的一个 Session 工具关联。
2. 天生会话 Cookie
(编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|