JWT practice and its similarities and differences with session

Time:2020-9-26

JSON web token is a standard of rfc7519, which uses JSON to transfer data to determine whether the user is logged in or not.

Before JWT, session was used for user authentication.

The following code is written in JavaScript.

The link to the original text can be found in Shanyue’s blog

session

The traditional way to log in is to use thesession + token

tokenIt refers to the use of token as the user status certificate in the client, and the browser is generally stored in thelocalStorageperhapscookieMedium.

sessionIt refers to using redis or SQL database on the server side to store user_ ID and token key value pair relationship, the basic working principle is as follows.

const sessions = {
  "ABCED1": 10086,
  "CDEFA0": 10010
}

//Get user through token_ ID, complete the authentication process
function getUserIdByToken (token) {
  return sessions[token]
}

If stored incookieThat’s what I often hearsession + cookieLogin scheme for. It’s stored incookielocalStorageeven to the extent thatIndexedDBperhapsWebSQLEach has its own advantages and disadvantages, and its core ideas are consistent.

aboutcookieas well astokenThe advantages and disadvantages are discussed in token authentication vs cookies.

If you don’t use cookies, you can takelocalStorage + AuthorizationIn this way.

//HTTP header. The authorization header needs to be carried every time the permission interface is requested
const headers = {
  Authorization: `Bearer ${localStorage.get('token')}`
}

A library called localforce is recommendedIndexedDBWebSQLas well asIndexedDBDo key value pair storage.

Stateless login

sessionIt is necessary to keep the corresponding information of user and token in the databaseState

Imagine how you can log in without maintaining user status in the database.

The first method:The front end transmits the user directly_ ID to the server

The disadvantages are particularly obvious, which can easily be tampered by users into task users_ ID, permission setting is virtual. But the idea is right, and move on.

improvement:For user_ ID is encrypted symmetrically

Slightly stronger than the above, if the last method is empty windows, this method is the windows pasted with paper.

improvement:For user_ ID does not need to be encrypted, only need to be signed to ensure that it is not tampered with

This is the idea of JWT, user_ ID, encryption algorithm and signature are stored in the client together. Each time the interface is requested, the server judges whether the signature is consistent.

Json Web Token

  • jwt.io

JWT byHeaderPayloadas well asSignaturefrom.It’s made by splicing.

Header

The header consists of asymmetric encryption algorithms and types, as follows

const header = {
  //Encryption algorithm
  alg: 'HS256',
  type: 'jwt'
}

Payload

The payload consists of registered claim and the data to be communicated. These data fields are also calledClaim

Registered ClaimWhat’s more important is that"exp" ClaimRepresents the expiration time, which is set when the user logs in.

const payload = {
  //Represents the JWT creation time
  iat: 1532135735,

  //Represents the JWT expiration time
  exp: 1532136735,

  //User ID for communication
  user_id: 10086
}

Signature

Sign byHeaderPayloadas well assecretOrPrivateKeyCalculated.

aboutsecretOrPrivateKeyIf the encryption algorithm adoptsHMAC, is a string, if theRSAperhapsECDSA, is privatekey.

//The signature is performed by hmacsha256 algorithm, and secret cannot be leaked
const sign = HMACSHA256(base64.encode(header) + '.' + base64.encode(payload), secret)

//JWT is composed of three parts
const jwt = base64.encode(header) + '.' + base64.encode(payload) + '.' + sign

From the generation of JWT rules, the client can parse the payload, so do not carry sensitive data, such as user password, in the payload

check

According to the generation rules, the first two parts of JWT are Base64 encoding of header and payload.

When the server receives the token from the client, it parses the first two parts to get the header and payload, and uses the algorithm in the header to sign with the secret or private key to judge whether the signature is consistent with that in JWT.

How to judge token expiration?

application

It can be seen from the above that JWT does not encrypt the data, but signs the data to ensure that it will not be tampered with. In addition to login can be used, in the mailbox verification and graphic verification code can also be used.

Graphic verification code

When logging in, if the number of incorrect password input is too many, the graphic verification code will appear.

The principle of graphic verification code is to give a graph to the client, and save the string matching with the image on the server side. Previously, it was mostly implemented by session.

The string matched by the captcha can be used as secret for stateless verification.

const jwt = require('jsonwebtoken')

//Suppose that the captcha is character captcha and the character is ACDE, and it will be invalid for 10 minutes
const token = jwt.sign({ userId: 10085 }, secrect + 'ACDE', { expiresIn: 60 * 10 })

Mailbox verification

Now the website will check the mailbox after the registration is successful. The specific method is to send a link to the mailbox, and the user can click the link to verify the success.

//Bind the mailbox and user ID together
const code = jwt.sign({ email, userId }, secret, { expiresIn: 60 * 30 })

//Check the verification code here
const link = `https://example.com/code=${code}`

Stateless vs. stateful

As for stateless and stateful, there are also comparisons in other technical directions, such as react’s stateless component and stateful component. Side effects in functional programming can be understood as states. HTTP is also a stateless protocol, which needs to be carried by headers and cookies.

In user authentication, statefulness refers to whether or not to rely on external data storage, such as mysql, redis, etc.

Consider the following questions about login, how to use session and JWT implementation

How to make the token invalid when the user logs off

Because JWT is stateless and does not save the user’s device information, it can not be used to complete the above problems. You can use the database to save some state.

  • Session: just put user_ Clear the token corresponding to ID
  • JWT: use redis to maintain a blacklist. When a user logs off, the blacklist (signature) is added. The expiration time is consistent with that of JWT.

How to allow users to log in only on one device, such as wechat

  • Session: use SQL database to add token field to the user database table and quote it. Reset the token field every time you log in. When you need permission interface every time, search for user according to token_ ID
  • JWT: if SQL database is used, the token field is added to the user database table (there is no need to add an index). The token field is reset every time you log in, and the user is obtained according to JWT when the permission interface is required_ ID, according to user_ ID looks up the user table to get the token to determine whether the token is consistent. In addition, you can also use the counter method, as follows.

For this requirement, session is a little simpler, after all, JWT also needs to rely on the database.

How to allow users to log in only on the last five devices, such as many players

  • Session: use SQL database to create token database table with ID, token and user_ There are three fields of ID, and the relationship between user and token table is 1: M. Add a record line at each login. Get user according to token_ ID, and then according to user_ ID gets how many devices the user has logged in. If there are more than 5 devices, the row with the smallest ID will be deleted.
  • JWT: use the counter, use the SQL database, add the field count in the user table, the default value is 0, the count field will increase by 1 each time you log in, and the JWT payload created by each login will carry the data current_ Count is the count value of the user. Each time the permission interface is requested, the count and current are obtained according to JWT_ Count, according to user_ ID looks up the user table to get count, judge and current_ Is the count difference less than 5

For this requirement, JWT is a little simpler, and using session requires maintaining one more token table.

How to allow users to log in only on the last five devices, and make a user kick off all devices except the existing devices, such as many players

  • Session: on the basis of the previous question, delete all token records except the device.
  • JWT: on the basis of the previous question, assign count + 5 and assign the device a new count.

How to display the login device list of the user / how to kick out a specific user

  • Session: add a new column device to the token table
  • JWT: the server side needs to keep the device list information. It is the same as the session, so it is not meaningful to use JWT

summary

From the above problems, if you do not need to control the number of login devices and device information, stateless JWT is a good choice. Once the device information is involved, it is necessary to add additional state support to JWT, which increases the complexity of authentication. At this time, session is a good choice.

JWT is not omnipotent. Whether to adopt JWT or not depends on business requirements.