Description of user login services

1. Traditional user authentication

Internet services cannot be separated from user authentication. The general process is as follows:

  1. The user sends the user name and password to the server.
  2. After the server authenticates, relevant data (user role, login time, etc.) is saved in the current session.
  3. The server returns the session_ID to the user, and the session information is stored in the cookie of the user.
  4. Each subsequent request by the user extracts the session_ID from the cookie and passes it to the server.
  5. The server receives the Session_ID and compares it to the previous data to authenticate the user.

The biggest problem with this model is that it has no distributed architecture to scale horizontally!

2. Solutions

2.1 the session radio

2.2 Store transparent tokens into cookies and store user information into Redis.

There is also a flexible solution (using token technology)

Using self-contained tokens, data is saved on the client and not on the server. JWT is an example of this solution

3. JWT token mechanism

3.1 Type of access token

3.2 Composition of JWT

A typical JWT looks like this:

The object is a long string that passes through three “.” Is split into three substrings.

Each substring contains a block of functionality. There are three parts:JWT head, payload, signature.

JWT head

The JWT header is a JSON object that describes the JWT metadata, typically as shown below

{
  "alg": "HS256",
  "typ": "JWT"
}
Copy the code

The alG attribute indicates the algorithm used by the signature, which is HS256 by default. The TYP attribute represents the type of the token, and JWT tokens are represented as JWT. Finally, the Base64URL algorithm is used to convert the above JSON object into a string for saving.

The payload

The payload section is the subject content section of JWT, which is also a JSON object that contains the data that needs to be passed. By default, JWT specifies seven fields to select from.

Iss: publisher exp: expiration time sub: subject AUD: user NBF: Unavailable before iAT: release time jTI: JWT ID Identifies the JWTCopy the code

In addition to the above default fields, we can also customize our own private fields. The following example

{
  "sub": "1234567890",
  "name": "Helen",
  "admin": true
}
Copy the code

Please note that JWT is not encrypted by default and anyone can interpret its contents, so do not build a private field to hold confidential information in case it gets leaked. JSON objects are also converted to strings for saving using the Base64URL algorithm.

Signature hash

Signature hash is the data signature of the above two parts, and the hash is generated by the formulated algorithm to ensure that the data will not be tampered with. First, you need to specify a password (secret). The password is stored only on the server and cannot be disclosed to users. Then, using the signature algorithm specified in the header (HS256 by default), the signature is generated according to the following formula.

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(claims), secret)
Copy the code

After calculating the signature hash, the JWT header, payload, and signature hash three parts form a string, each part using “. Split, and you form a JWT object.

2.4. JWT principle

The principle of JWT is that after authentication by the server, a JSON object is generated and returned to the user, as shown below

{
  "sub": "1234567890",
  "name": "Helen",
  "admin": true
}
Copy the code

Later, when the client communicates with the server, the client sends back the JSON object in the request. The server relies on this JSON object to identify the user. To prevent users from tampering with the data, the server adds a signature when the object is generated. The server does not hold any session data, which means the server becomes session-free, making it easier to scale.

2.5 Usage of JWT

When the client receives the JWT from the server, it saves it in a Cookie or localStoreage.

Since then, the client has taken Jwt with each request. If it is stored in a cookie, it can be sent automatically, but it does not resolve cross-domain issues, so it is generally placed in the Header Authorization field of the HTTP request. When across domains, JWT can also be placed in the data body of the POST request.

2.6 JWT issues and trends

  • JWT can be used not only for authentication but also for information exchange. Making good use of JWT can help reduce the number of server requests to the database.
  • The generated token can contain basic information, such as ID, user nickname, and profile picture, to avoid checking the database again
  • The storage device is stored on the client and does not occupy memory resources on the server
  • JWT does not encrypt by default, but can encrypt. Once the original token is generated, it can be encrypted again.
  • When JWT is not encrypted, some private data cannot be transmitted through JWT.
  • The biggest drawback of JWT is that the server does not save session state, so it is impossible to cancel or change the privileges of a token during use. That is, once the JWT is issued, it will remain in effect for the duration of its validity.
  • JWT itself contains authentication information, and the token is base64 encoded, so it can be decoded. Therefore, objects before token encryption should not contain sensitive information. Once the information is leaked, anyone can get all the privileges of the token. In order to reduce theft, the validity period of JWT should not be set too long. For some important operations, users should authenticate every time they use them.
  • To reduce theft and theft, JWT does not recommend using the HTTP protocol to transmit code, but using the encrypted HTTPS protocol for transmission.

JWT springboot integration

1. Import dependencies

<! -- JWT--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> </dependency>Copy the code

2. Create a JWT utility class

Public class JwtUtils {public static final long EXPIRE = 1000 * 60 * 60 * 24; public class JwtUtils {public static final long EXPIRE = 1000 * 60 * 60 * 24; / / token expiration time public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; Public static String getJwtToken(String id, String id) String nickname){String JwtToken = jwts.builder (); "HS256").setSubject("edu-online") // You can modify.setissuedat (new Date()) // Set the start time of the time.setexpiration (new) Date(system.currentTimemillis () + EXPIRE)) Can add many times * * * * * * * * * * * * * * *. The claim (" id ", id). The claim (" nickname ", nickname). SignWith (SignatureAlgorithm HS256, APP_SECRET) .compact(); return JwtToken; * @param jwtToken * @return */ public static Boolean checkToken(String jwtToken) { if(StringUtils.isEmpty(jwtToken)) return false; try { Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * Check whether the token exists and is valid * @param request * @return */ public static Boolean checkToken(HttpServletRequest request) {try { String jwtToken = request.getHeader("token"); if(StringUtils.isEmpty(jwtToken)) return false; Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken); } catch (Exception e) { e.printStackTrace(); return false; } return true; } public static String getMemberIdByJwtToken(HttpServletRequest) request) { String jwtToken = request.getHeader("token"); if(StringUtils.isEmpty(jwtToken)) return ""; Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken); Claims claims = claimsJws.getBody(); return (String)claims.get("id"); }}Copy the code

Now we’re ready to use it! Super convenient. This article draws lessons from the teacher’s notes of Shangsilicon Valley Valley Institute, thank you very much!