This article thoroughly understands what Cookie, Session, and Token are

> The author's writing skills are still shallow, if there is anything wrong, please point out generously, I will definitely be grateful

Cookie

洛:大爷,楼上322住的是马冬梅家吧?

大爷:马都什么?

夏洛:马冬梅。

大爷:什么都没啊?

夏洛:马冬梅啊。

大爷:马什么没?

夏洛:行,大爷你先凉快着吧。

Before understanding these three concepts, we must first understand that HTTP is a stateless web server. What is statelessness? Like the classic dialogue scene in Charlotte's Annoyance above, one dialogue completes and the next one has absolutely no idea what happened to the last one. If it is only used to manage static files in the Web server, it doesn't matter who the other party is, just read the file from the disk and send it out. But with the continuous development of the network, for example, the shopping cart in e-commerce can only perform the next series of actions after remembering the user's identity. So at this point we need our stateless server to remember a few things.

So how does a web server remember something? Since the Web server can't remember things, we try to remember things externally, which is equivalent to the server attaching a small note to each client. The above records some information returned by the server to us. Then the server sees this little note and knows who we are. So Cookiewho produced it? Cookies are generated by the server. Next, we describe Cookiethe process of generating

  1. When the browser accesses the server for the first time, the server must not know his identity at this time, so create a unique identity data in the format key=value, put it into the Set-Cookiefield, and send it to the browser along with the response message.
  2. After the browser sees the Set-Cookiefield, it knows that this is the identity ID given by the server, so it saves it, and the next time the request is made, it will automatically put this key=valuevalue into the Cookiefield and send it to the server.
  3. After the server receives the request message, it finds Cookiethat there is a value in the field, and can identify the user's identity based on this value and provide personalized services.

Next, we use the code to demonstrate how the server is generated. We build a background server by ourselves. Here I use SpringBoot to build, and the code written into SpringMVC is as follows.

@RequestMapping("/testCookies")
public String cookies(HttpServletResponse response){
    response.addCookie(new Cookie("testUser","xxxx"));
    return "cookies";
}
 

After the project is started, we enter the path http://localhost:8005/testCookiesand then view the request sent. You can see that the image below makes the request sent when we access the server for the first time, and you can see that there are Set-Cookiefields in the response returned by the server. The value inside is the key=valuevalue set in our server.

Next, we refresh the page again to see that the Cookiefield has been set in the request body, and our value has also been passed. This way the server can Cookieremember our information based on the value in .

Next, what about another request? Will it Cookiebe brought over as well? Next we enter the path http://localhost:8005request. We can see that the Cookiefields are still being carried over.

So where is the browser Cookiestored? If you are using a Chromebrowser, you can follow the steps below.

  1. open on computerChrome
  2. In the top right corner, click the 更多icon once ->设置
  3. At the bottom, click高级
  4. Below 隐私设置和安全性, click Site Settings
  5. Click Cookie-> View allCookie和网站数据

CookieThe managed data can then be searched by domain name . So it is the data that the browser manages for you Cookie. If you switch to Firefoxanother browser at this time, because it Cookiewas stored in Chromeit just now, the server is confused again. I don’t know who you are, and I will Firefoxpost it again . Put a small note on it.

Parameter settings in cookies

At this point, you should know that the Cookieserver entrusts the browser to store some data in the client, and these data usually record the key identification information of the user. Therefore , it is Cookienecessary to use some other means to protect and prevent leakage or theft. These means are Cookiethe attributes.

parameter name effect Backend setup method
Max-Age Set the expiration time of the cookie, in seconds cookie.setMaxAge(10)
Domain Specifies the domain name to which the cookie belongs cookie.setDomain("")
Path Specifies the path to which the cookie belongs cookie.setPath("");
HttpOnly Tell the browser that this cookie can only be transmitted by the browser's Http protocol, and other methods of access are prohibited cookie.setHttpOnly(true)
Secure Tell the browser that this cookie can only be transmitted in the Https security protocol, if it is Http, the transmission is prohibited cookie.setSecure(true)

Below I will briefly demonstrate the usage and phenomenon of these parameters.

Path

Set to cookie.setPath("/testCookies"), next we visit http://localhost:8005/testCookies, we can see that the path on the left is the same as the path we specified, so Cookieit appears in the request header, then we visit http://localhost:8005, we find that there is no Cookiefield, this is Paththe path of control.

Domain

Set to cookie.setDomain("localhost"), then we visit and http://localhost:8005/testCookieswe find that Cookiethere are , but when we visit http://172.16.42.81:8005/testCookies, look at the right side of the figure below and we can see that there Cookieare no fields. This is the Domaincontrolled domain name sending Cookie.

The next few parameters will not be demonstrated one by one, I believe that everyone should Cookiehave some understanding here.

Session

> Cookie is stored on the client side, Session is stored on the server side, and the client only storesSessionId

What we learned above is Cookiethat since the browser has already Cookieimplemented the stateful requirement, why is there another one Session? Here we imagine that if some information of the account is stored Cookiein the account, once the information is intercepted, all our account information will be lost. So it appears Sessionthat in a session, important information is saved in Session, and the browser only records SessionIda SessionIdrequest corresponding to a session.

@RequestMapping("/testSession")
@ResponseBody
public String testSession(HttpSession session){
    session.setAttribute("testSession","this is my session");
    return "testSession";
}


@RequestMapping("/testGetSession")
@ResponseBody
public String testGetSession(HttpSession session){
    Object testSession = session.getAttribute("testSession");
    return String.valueOf(testSession);
}

Here we write a new method to test Sessionhow it is generated. We add it to the request parameter HttpSession session, and then enter it in the browser to access it. You can see that one is generated in http://localhost:8005/testSessionthe return header of the server . Then the browser remembers that it can take this Id with it when it next visits, and then it can find the information stored on the server based on this Id.CookieSessionIdSessionId

At this point, we access the path http://localhost:8005/testGetSessionand find that we get the information we stored in the above Session. So Sessionwhen does it expire?

  • Client: CookieConsistent with expiration, if it is not set, the default is to close the browser and it will be gone, that is, when the browser is opened again, the initial request header will not be there SessionId.
  • Server: The expiration of the server is really expired, that is, Sessionhow long the data structure stored on the server will be unavailable. The default is 30 minutes.

Now that we know that it Sessionis managed on the server side, maybe you have a few questions when you see this, Sessionwhere was it created? SessionWhat data structure is it stored in? Next, let's take a look at Sessionhow it is managed.

SessionThe management is managed in the container, what is the container? Tomcat, Jettyetc. are all containers. Next, let's take the most commonly used Tomcatexample to see Tomcathow to manage Sessionit. is used ManageBaseto createSessioncreate Session.


@Override
public Session createSession(String sessionId) {
    //首先判断Session数量是不是到了最大值,最大Session数可以通过参数设置
    if ((maxActiveSessions >= 0) &&
            (getActiveSessions() >= maxActiveSessions)) {
        rejectedSessions++;
        throw new TooManyActiveSessionsException(
                sm.getString("managerBase.createSession.ise"),
                maxActiveSessions);
    }

    // 重用或者创建一个新的Session对象,请注意在Tomcat中就是StandardSession
    // 它是HttpSession的具体实现类,而HttpSession是Servlet规范中定义的接口
    Session session = createEmptySession();


    // 初始化新Session的值
    session.setNew(true);
    session.setValid(true);
    session.setCreationTime(System.currentTimeMillis());
    // 设置Session过期时间是30分钟
    session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60);
    String id = sessionId;
    if (id == null) {
        id = generateSessionId();
    }
    session.setId(id);// 这里会将Session添加到ConcurrentHashMap中
    sessionCounter++;
    
    //将创建时间添加到LinkedList中,并且把最先添加的时间移除
    //主要还是方便清理过期Session
    SessionTiming timing = new SessionTiming(session.getCreationTime(), 0);
    synchronized (sessionCreationTiming) {
        sessionCreationTiming.add(timing);
        sessionCreationTiming.poll();
    }
    return session
}

At this point we understand Sessionhow to create it, and it Sessionwill be saved to one after it is created ConcurrentHashMap. You can see StandardSessionclasses.

protected Map<string, session> sessions = new ConcurrentHashMap&lt;&gt;();

Everyone should have Sessiona simple understanding of it here.

> Session is stored in the Tomcat container, so if there are multiple backend machines, the session cannot be shared between multiple machines. At this time, the distributed session solution provided by Spring can be used, which is to put the session in the in Redis.

Token

SessionIt stores the information to be verified on the server, and SessionIdcorresponds to the data, SessionIdwhich is stored by the client, and will be SessionIdcarried over when requested, thus realizing the correspondence of the state. InsteadToken , the server transmits the user information to the client after Base64Url encoding. Every time the user requests, it will bring this piece of information. Therefore, after the server gets this information and decrypts it, it knows who the user is. This The method is called JWT (Json Web Token).

> The advantage of Tokencomparison Sessionis that when there are multiple back-end systems, since the client directly carries the data when accessing, there is no need to do the operation of sharing the data.

Advantages of Token

  1. Concise: It can be sent through URL, POSTparameter or in the HTTPheader parameter, because the amount of data is small and the transmission speed is fast
  2. Self-contained: Because the string contains the information needed by the user, multiple database queries are avoided
  3. Because Token is stored on the client in the form of Json, JWT is cross-language
  4. No need to save session information on the server, especially suitable for distributed microservices

Structure of JWT

The actual JWT looks like the following, it is a very long string, which is .divided into three parts in the middle

JWT is composed of three parts

Header

is a Json object that describes the metadata of the JWT, usually as follows

{
  "alg": "HS256",
  "typ": "JWT"
}

In the above code, the alg attribute represents the signature algorithm (algorithm), the default is HMAC SHA256 (written as HS256); the typ attribute represents the type of the token (type), and the JWT token is uniformly written as JWT. Finally, convert the above JSON object into a string using the Base64URL algorithm.

> JWT is used as a token (token), which may be placed in the URL (such as api.example.com/?token=xxx) in some cases. Base64 has three characters +, / and =, which have special meaning in the URL, so they should be replaced: = is omitted, + is replaced by -, / is replaced by _. This is the Base64URL algorithm.

Payload

The Payload part is also a Json object, which is used to store the data that actually needs to be transmitted. JWT officially stipulates the following official fields for selection.

  • iss (issuer): Issuer
  • exp (expiration time): expiration time
  • sub (subject): subject
  • aud (audience): audience
  • nbf (Not Before): effective time
  • iat (Issued At): Issued At
  • jti (JWT ID): number

Of course, in addition to these officially provided fields, we can also define private fields by ourselves. The following is an example

{
  "name": "xiaoMing",
  "age": 14
}

By default, JWT is not encrypted, and anyone can read the information as long as it decodes Base64 on the Internet, so generally do not put secret information in this part. This Json object is also Base64URL converted into a string using an algorithm

Signature

The Signature part is to sign the data of the previous two parts to prevent data tampering.

First, you need to define a secret key. This secret key is only known to the server and cannot be leaked to the user. Then, use the signature algorithm specified in the Header (the default is HMAC SHA256). After calculating the signature, combine the three parts of Header, Payload and Signature into one Strings, each part .separated by , can be returned to the user.

> HS256 can create a signature for a given data sample with a single key. When the message is transmitted with the signature, the receiver can use the same key to verify that the signature matches the message.

How to use Token in Java

We have introduced some concepts about JWT above. How to use it next? First introduce the Jar package into the project

compile('io.jsonwebtoken:jjwt:0.9.0')

Then encode as follows

// 签名算法 ,将对token进行签名
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 通过秘钥签名JWT
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("SECRET");
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
Map<string,object> claimsMap = new HashMap&lt;&gt;();
claimsMap.put("name","xiaoMing");
claimsMap.put("age",14);
JwtBuilder builderWithSercet = Jwts.builder()
        .setSubject("subject")
        .setIssuer("issuer")
        .addClaims(claimsMap)
        .signWith(signatureAlgorithm, signingKey);
System.out.printf(builderWithSercet.compact());

It is found that the output Token is as follows

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwibmFtZSI6InhpYW9NaW5nIiwiYWdlIjoxNH0.3KOWQ-oYvBSzslW5vgB1D-JpCwS-HkWGyWdXCP5l3Ko

At this point, you can decode the information by simply looking for a Base64 decoding website on the Internet.

Summarize

I believe that everyone should have a certain understanding Cookieof this Session, Tokenand then review the important knowledge points.

  • Cookies are stored on the client side
  • Session is stored on the server and can be understood as a state list. Has a unique session ID SessionId. The stored information can be SessionIdqueried on the server side.
  • Session will cause a problem, that is, the problem of Session sharing when there are multiple machines in the backend. The solution can use the framework provided by Spring.
  • Token is similar to a token, stateless, the information required by the server is Base64 encoded and put into the Token, and the server can directly decode the data in it.

GitHub code address

Reference article

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324114331&siteId=291194637