Json Web Token
The essence of JWT is a string. It saves user information into a Json string, and then encodes it to get a JWT token. The JWT token has signature information. After receiving, it can verify whether it has been tampered with. Therefore, it can be used to safely transmit information as a Json object between all parties
At present, JWT token is more recommended for user authentication in both single and distributed applications
Process of user authentication using token
1. The client requests login with user name and password
2. The server receives the request and verifies the user name and password
3. After successful verification, the server will issue a token and return the token to the client
4. After receiving the token, the client can store it, for example, in a cookie
5. Each time the client requests resources from the server, it needs to carry the token issued by the server, which can be carried in the cookie or header
6. The server receives the request, and then verifies the token carried in the client request. If the verification is successful, it returns the request data to the client
JWT certification process
1. The front end sends its user name and password to the back-end interface through a Web form. This process is generally a POST request. The recommended method is SSL encrypted transmission (HTTPS), so as to avoid sensitive information being sniffed
2. After checking the user name and password successfully, the back-end takes the data containing user information as the Payload of JWT, performs Base64 coding and splicing with JWT Header respectively, and then signs to form a JWT Token. The formed JWT Token is a string like lll.zzz.xxx
3. The back end returns the JWT Token string to the front end as the result of successful login. The front end can save the returned results in the browser and delete the saved JWT Token when logging out
4. The front end puts the JWT Token into the Authorization attribute in the HTTP request header every time the request is made (solve the XSS and XSRF problems)
5. The back end checks the JWT Token passed from the front end to verify its validity, such as checking whether the signature is correct, whether it has expired, whether the receiver of the token is itself, etc
6. After the verification is passed, the back end parses the user information contained in the JWT Token, performs other logical operations (generally obtains permissions according to the user information), and returns the results
Advantages of JWT certification
Compared with the traditional session authentication method, the advantages of JWT are:
Concise: JWT Token has small amount of data and fast transmission speed
Because JWT tokens are stored on the client in JSON encrypted form, JWT is cross language and is supported in any web form in principle
There is no need to save session information on the server, that is, it does not depend on cookie s and sessions, so it has no disadvantages of traditional session authentication, and is especially suitable for distributed microservices
Single sign on friendly: if you use Session for identity authentication, it is difficult to achieve single sign on because cookies cannot cross domains. However, if the token is used for authentication, the token can be saved in the memory of any location of the client, not necessarily a cookie, so it does not rely on cookies, so there will be no such problems
Suitable for mobile applications: if you use Session for identity authentication, you need to save a piece of information on the server, and this method will depend on cookies (you need to save SessionId with cookies), so it is not suitable for mobile applications
At present, JWT token is more recommended for user authentication in both single and distributed applications
JWT structure
Header, payload, and signature
During transmission, the three parts of JWT will be Base64 encoded and connected with. To form the final transmitted string
1.Header
The JWT header is a JSON object that describes JWT metadata. The alg attribute indicates the algorithm used for signature. The default is HMAC SHA256; The typ attribute indicates the type of token. JWT tokens are uniformly written as JWT.
2.Payload
The payload part is the main content part of JWT. It is also a JSON object that contains the data to be passed. JWT specifies seven default fields to choose from
iss: publisher exp: Expiration time sub: theme aud: user nbf: Not available before iat: Release time jti: JWT ID Used to identify the JWT
In addition to the above default fields, we can also customize private fields. Generally, we will put the data containing user information into the payload
By default, JWT is unencrypted, because only base64 algorithm is adopted. After getting the JWT string, it can be converted back to the original JSON data, and anyone can interpret its content. Therefore, do not build a private information field. For example, the user's password must not be saved in JWT to prevent information disclosure. JWT is only suitable for transmitting some non sensitive information in the network
3.Signature
The signature hash part is to sign the above two parts of data. The header and payload data encoded by base64 need to be used to generate hash through the specified algorithm to ensure that the data will not be tampered with. First, you need to specify a secret. The password is only stored in the server and cannot be disclosed to the user. Then, use the signature algorithm specified in the header (HMAC SHA256 by default)
Role of each part of JWT
After the server receives the JWT token sent by the client:
The header and payload can directly decode the original text using base64, obtain the hash signature algorithm from the header, and obtain valid data from the payload
signature cannot decode the original text because it uses an irreversible encryption algorithm. Its function is to verify whether the token has been tampered with. After obtaining the encryption algorithm in the header, the server encrypts the header and payload with the algorithm and the secretKey, and compares whether the encrypted data is consistent with the data sent by the client. Note that the secretKey can only be saved on the server and has different meanings for different encryption algorithms. Generally, for MD5 digest encryption algorithms, the secretKey actually represents the salt value
JWT dependency
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency>
JWT tool class
package com.example.demo.util; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * @date 2019/4/25 11:46 * @atuther wangbo */ public class JwtUtil { //Key (for signature) public static final String SECRET = "sdjhakdhajdklsl;o653632"; //Expiration time: seconds public static final int EXPIRE = 5; /** * Generate Token * @param userId * @param userName * @return * @throws Exception */ public static String createToken(String userId, String userName) throws Exception { Calendar nowTime = Calendar.getInstance(); nowTime.add(Calendar.SECOND, EXPIRE); Date expireDate = nowTime.getTime(); Map<String, Object> map = new HashMap<>(); map.put("alg", "HS256"); map.put("typ", "JWT"); String token = JWT.create() .withHeader(map)//head .withClaim("userId", userId) .withClaim("userName", userName) .withSubject("test")// .withIssuedAt(new Date())//Signature time .withExpiresAt(expireDate)//Expiration time .sign(Algorithm.HMAC256(SECRET));//autograph return token; } /** * Verify Token * @param token * @return * @throws Exception */ public static Map<String, Claim> verifyToken(String token)throws Exception{ // When creating a parsing object, the algorithm and secret used should be consistent with that when creating a token JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build(); DecodedJWT jwt = null; try { //If an exception occurs when parsing a token, it indicates that the previous and subsequent tokens are inconsistent, the verification fails, or the token expires jwt = verifier.verify(token); }catch (Exception e){ throw new RuntimeException("The certificate has expired. Please log in again"); } return jwt.getClaims(); } /** * Parse Token * @param token * @return */ public static Map<String, Claim> parseToken(String token){ DecodedJWT decodedJWT = JWT.decode(token); return decodedJWT.getClaims(); } }