Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

In-depth explanation of Session and Cookie in Tomcat

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/02 Report--

Preface

HTTP is a stateless communication protocol, each request is independent of each other, the server can not recognize the request that has come before. For Web applications, its activities depend on a certain state, such as user login. Using HTTP at this time requires its ability to provide login information for subsequent requests after a login request. This article was first released in the official account epiphany source code.

The solution is to use Cookie, which is returned by the server to the browser, which caches and submits the cookie data to the server on each request. Cookies transmits in clear text in the request, and the size is limited to 4KB. Obviously, it is unreliable to save all state data in the browser. The mainstream practice is:

When the browser makes the first request, the server assigns a unique identifier to the user, returns and stores it in the browser's Cookies, maintains a global request status library inside the server, and uses the generated unique identifier to correlate the status information of each request subsequent requests made by the browser submit the unique identifier to the server in order to obtain the previously requested status information

For ease of management, the server calls the entire process a session and abstracts it into a Session class that identifies and stores information or state about the user.

Next, we will analyze the source implementation of Tomcat through the parsing and generation of session identifiers, the creation, destruction and persistence of Session. The version uses 6.0.53.

1. Parse session identifier

Cookie, as the most commonly used session tracking mechanism, is supported by all Servlet containers, and Tomcat is no exception. In Tomcat, the standard name for cookie that stores session identifiers is JSESSIONID.

If the browser does not support Cookie, you can also record the identifier by using the following methods:

URL rewrite: include in url as a path parameter, such as / path;JSESSIONID=xxxURL request parameter: add the session unique ID as a query parameter to all links on the page, such as / path?JSESSIONID=xxxFORM hidden field: a hidden field is used in the form to store the unique value, which is submitted to the server with the form

Tomcat implements the extraction of JSESSIONID from the URL rewrite path and Cookie. Before analyzing the source code, first take a look at the key information about the header domain of setting Cookie responses and requests with Cookie:

/ / set CookieHTTP/1.1 200OKServer: Apache-Coyote/1.1Set-Cookie: JSESSIONID=56AE5B92C272EA4F5E0FBFEFE6936C91; Path=/examplesDate: Sun, 12 May 2019 01:40:35 GMT// submit CookieGET / examples/servlets/servlet/SessionExample HTTP/1.1Host: localhost:8080Cookie: JSESSIONID=56AE5B92C272EA4F5E0FBFEFE6936C91

1.1 rewrite path from URL

A URL that contains the session ID path parameter is as follows:

Http://localhost:8080/examples/SessionExample;JSESSIONID=1234;n=v/?x=x

Simply look for the JSESSIONID between the matching semicolon and the last slash, which is also true, except that Tomcat operates on bytes and the core code is in the CoyoteAdapter.parsePathParameters () method, which is not posted here.

1.2 from the Cookie header domain

The method call that triggers Cookie resolution is as follows:

CoyoteAdapter.service (Request, Response) └─ CoyoteAdapter.postParseRequest (Request, Request, Response, Response) └─ CoyoteAdapter.parseSessionCookiesId (Request, Request) └─ Cookies.getCookieCount () └─ Cookies.processCookies (MimeHeaders) └─ Cookies.processCookieHeader (byte [], int, int)

This processCookieHeader operates on bytes, and parsing does not look intuitive. Inside Tomcat, there is also a marked obsolete method of using string parsing, which is helpful to understand. the code is as follows:

Private void processCookieHeader (String cookieString) {/ / multiple cookie values are separated by commas StringTokenizer tok = new StringTokenizer (cookieString, ";", false); while (tok.hasMoreTokens ()) {String token = tok.nextToken (); / / get the position of the equal sign int I = token.indexOf ("="); if (I >-1) {/ / get name and value and remove spaces String name = token.substring (0, I). Trim () String value= token.substring (iTun1, token.length ()). Trim (); / / RFC 2109 and bug removes the double quotation marks "value=stripQuote (value); / / gets a ServerCookie object ServerCookie cookie = addCookie () from the internal cookie cache pool; / / sets name and value cookie.getName (). SetString (name); cookie.getValue (). SetString (value);} else {/ / we have a bad cookie.... Just let it go}

After parsing, the next step is to iterate through the parseSessionCookiesId method and try to match the Cookie named JSESSIONID, and if it exists, set its value to the requestedSessionId of Request, which is associated with an internal Session object.

two。 Generate session Cookie

The Cookie related to the session is generated within Tomcat. When you use Request.getSession () to get the session object in Servlet, execution will be triggered, and the core code:

Protected Session doGetSession (boolean create) {. / / create Session instance if (connector.getEmptySessionPath () & & isRequestedSessionIdFromCookie ()) {/ / if the session ID comes from cookie, please reuse the ID, if it comes from URL, do not / / reuse the session ID to prevent possible phishing attacks session = manager.createSession (getRequestedSessionId ());} else {session = manager.createSession (null) } / / create a new session cookie if ((session! = null) & & (getContext ()! = null) & getContext (). GetCookies ()) {String scName = context.getSessionCookieName (); if (scName = = null) {/ / default JSESSIONID scName = Globals.SESSION_COOKIE_NAME;} / / New Cookie Cookie cookie = new Cookie (scName, session.getIdInternal ()); / / set path domain secure configureSessionCookie (cookie) / add to the response header domain response.addSessionCookieInternal (cookie, context.getUseHttpOnly ());} if (session! = null) {session.access (); return (session);} else {return (null);}}

Add to the response header field, which is generated based on the Cookie object, in the format described at the beginning.

3. Session

Session is an interface within Tomcat and a facade class of HttpSession, which is used to maintain state information between requests of specific users of web applications. The related class diagrams are designed as follows:

The functions of key classes or interfaces are as follows:

Manager-manages Session pools, different implementations provide specific functions, such as persistence and distributed ManagerBase-implements basic functions such as Session pools, unique ID generation algorithms, facilitates inheritance and extension of StandardManager-standard implementations, and provides simple session persistence when this component is restarted (for example, when the entire server is shut down and restarted Or when reloading a specific Web application) PersistentManagerBase-provides a variety of different persistent storage management methods, such as file and database Store-provides persistent storage and loading session and user information ClusterManager-cluster session management interface, responsible for session replication DeltaManager-incremental copy of session data to all members of the cluster BackupManager-copy data to only one backup node This node can be seen by all members of the cluster

This paper does not analyze the principle of cluster replication, but only analyzes the management of stand-alone Session.

3.1Create Session

The first time you use Request.getSession () to get a session object in Servlet, an instance of StandardSession is created:

Public Session createSession (String sessionId) {/ / returns new StandardSession (this) instance Session session = createEmptySession () by default; / / initialize properties session.setNew (true); session.setValid (true); session.setCreationTime (System.currentTimeMillis ()); / / set session validity time (in seconds), default is 30 minutes, negative value means never expire session.setMaxInactiveInterval ((Context) getContainer ()). GetSessionTimeout () * 60) If (sessionId = = null) {/ / generate a session ID sessionId = generateSessionId (); session.setId (sessionId); sessionCounter++; SessionTiming timing = new SessionTiming (session.getCreationTime (), 0); synchronized (sessionCreationTiming) {sessionCreationTiming.add (timing); sessionCreationTiming.poll ();} return (session);}

The key lies in the generation of the unique ID of the session. Let's take a look at the generation algorithm of Tomcat:

Randomly get 16 bytes and use MD5 to encrypt these bytes, then get a 16-byte array to traverse the new byte array, generate a hexadecimal character using the high and low bits of each byte, and finally get a 32-bit hexadecimal string.

The core code is as follows:

Protected String generateSessionId () {byte random [] = new byte [16]; String jvmRoute = getJvmRoute (); String result = null; / / the string StringBuffer buffer = new StringBuffer () that renders the result as a hexadecimal number; do {int resultLenBytes = 0; if (result! = null) {/ / repeat, regenerate buffer = new StringBuffer (); duplicates++;} / / sessionIdLength is 16 while (resultLenBytes

< this.sessionIdLength) { getRandomBytes(random);// 随机获取 16 个字节 // 获取这16个字节的摘要,默认使用 MD5 random = getDigest().digest(random); // 遍历这个字节数组,最后生成一个32位的十六进制字符串 for (int j = 0; j < random.length && resultLenBytes < this.sessionIdLength; j++) { // 使用指定字节的高低4位分别生成一个十六进制字符 byte b1 = (byte) ((random[j] & 0xf0) >

> 4); byte b2 = (byte) (random [j] & 0x0f); / / converted to hexadecimal numeric character if (b1)

< 10) {buffer.append((char) ('0' + b1));} // 转为大写的十六进制字符 else {buffer.append((char) ('A' + (b1 - 10)));} if (b2 < 10) {buffer.append((char) ('0' + b2));} else {buffer.append((char) ('A' + (b2 - 10)));} resultLenBytes++; } } if (jvmRoute != null) {buffer.append('.').append(jvmRoute);} result = buffer.toString(); } while (sessions.containsKey(result)); return (result);} 3.2 Session 过期检查 一个 Web 应用对应一个会话管理器,也就是说 StandardContext 内部有一个 Manager 实例。每个容器组件都会启动一个后台线程,周期的调用自身以及内部组件的 backgroundProcess() 方法,Manager 后台处理就是检查 Session 是否过期。 检查的逻辑是,获取所有 session 使用它的 isValid 判断是否过期,代码如下: public boolean isValid() { ... // 是否检查是否活动,默认 false if (ACTIVITY_CHECK && accessCount.get() >

0) {return true;} / / check whether the time expires if (maxInactiveInterval > = 0) {long timeNow = System.currentTimeMillis (); int timeIdle = (int) ((timeNow-thisAccessedTime) / 1000L); if (timeIdle > = maxInactiveInterval) {/ / if expired, perform some internal processing / / mainly to notify listeners expire (true) interested in expired events }} / / plural never expires return (this.isValid);}

3.3 Session persistence

Persistence is to serialize Session objects that are active in memory to a file or store them in a database. If the session management component conforms to and enables persistence, storage is performed in its lifecycle event stop method; loading is performed in the start method.

Persist to a file, and StandardManager also provides the ability to persist to a file, which writes all active sessions in the session pool to the CATALINA_HOME/work/Catalina///SESSIONS.ser file, with the code in its doUnload method.

FileStore also provides the ability to persist to a file, unlike StandardManager, which writes each session to a single file named .session.

Persist to the database, and store the session-related data in a table, including the serialized binary data. The table field information is as follows:

Create table tomcat_sessions (session_id varchar not null primary key, valid_session char (1) not null,-- is valid max_inactive int not null,-- maximum effective time last_access bigint not null,-- Last access time app_name varchar,-- Application name, format / Engine/Host/Context session_data mediumblob,-- binary data KEY kapp_name (app_name))

Note: you need to put the jar file of the database driver in the $CATALINA_HOME/lib directory so that the class loader inside Tomcat is visible.

4. Summary

This paper briefly analyzes the management of Session by Tomcat. Of course, it ignores a lot of details. If you are interested, you can go deep into the source code. Later, we will analyze the implementation of Tomcat cluster Session.

Summary

The above is the whole content of this article. I hope the content of this article has a certain reference and learning value for everyone's study or work. Thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report