SpringBook integrates Jwt to generate token tokens (session can be replaced when front and back ends are separated)

Overview of token tokens generated by Jwt

1. Stateful landing and stateless landing

  1. Stateful service, that is, the server needs to record the client information of each session to identify the identity of the client and process requests according to the identity of the user, such as session in tomcat
  2. Stateless, especially for providing restful wind interface to microservices
    1. The server does not save any client requester information
    2. Each client request must have self-describing information that identifies the client.

2. Composition of token generated by JWT

  1. The payload includes: the expiration time of attributes stored by the issuer of the token, etc.
  2. The signature is to verify that the token is valid.

I. Preparations

1. dependence

		<!--jwt Dependence-->
		<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>

		<!--Set up jwt Tool class for parsing current time when parameters-->
		<dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
     	</dependency>

2. The attributes of the payload in token generated by JWT encapsulate it as an entity class

/**
 * Load object
 */
public class UserInfo {

    private Long id;

    private String username;

    public UserInfo() {
    }

    public UserInfo(Long id, String username) {
        this.id = id;
        this.username = username;
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

II. Tools

1.JwtConstans

  • jwt's configuration modification property has the same value as the property name of the payload entity class
public abstract class JwtConstans {
    public static final String JWT_KEY_ID = "id";
    public static final String JWT_KEY_USER_NAME = "username";
}

2.RsaUtils

  • Tool classes for generating public and private keys
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RsaUtils {
    /**
     * Reading public keys from files
     *
     * @param filename Public key save path, relative to classpath
     * @return Public key object
     * @throws Exception
     */
    public static PublicKey getPublicKey(String filename) throws Exception {
        byte[] bytes = readFile(filename);
        return getPublicKey(bytes);
    }

    /**
     * Read keys from files
     *
     * @param filename Private key save path, relative to classpath
     * @return Private key object
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String filename) throws Exception {
        byte[] bytes = readFile(filename);
        return getPrivateKey(bytes);
    }

    /**
     * Get public key
     *
     * @param bytes Byte form of public key
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(byte[] bytes) throws Exception {
        X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePublic(spec);
    }

    /**
     * Get key
     *
     * @param bytes Byte form of private key
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(byte[] bytes) throws Exception {
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePrivate(spec);
    }

    /**
     * Survive rsa public and private keys according to ciphertext and write to the specified file
     *
     * @param publicKeyFilename  Public key file path
     * @param privateKeyFilename Private key file path
     * @param secret             Generate the ciphertext of the key
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(secret.getBytes());
        keyPairGenerator.initialize(1024, secureRandom);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        // Get the public key and write it out
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        writeFile(publicKeyFilename, publicKeyBytes);
        // Get the private key and write it out
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        writeFile(privateKeyFilename, privateKeyBytes);
    }

    private static byte[] readFile(String fileName) throws Exception {
        return Files.readAllBytes(new File(fileName).toPath());
    }

    private static void writeFile(String destPath, byte[] bytes) throws IOException {
        File dest = new File(destPath);
        if (!dest.exists()) {
            dest.createNewFile();
        }
        Files.write(dest.toPath(), bytes);
    }
}

3.JwtUtils

  • Generating and parsing token generated by jwt
import com.yzx.shop.auth.entity.UserInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;

import java.security.PrivateKey;
import java.security.PublicKey;

public class JwtUtils {
    /**
     * Private key encryption token
     *
     * @param userInfo      Data in Load
     * @param privateKey    Private key
     * @param expireMinutes Expiration time, unit second
     * @return
     * @throws Exception
     */
    public static String generateToken(UserInfo userInfo, PrivateKey privateKey, int expireMinutes) throws Exception {
        return Jwts.builder()
                .claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
                .claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();
    }

    /**
     * Private key encryption token
     *
     * @param userInfo      Data in Load
     * @param privateKey    Private key byte array
     * @param expireMinutes Expiration time, unit second
     * @return
     * @throws Exception
     */
    public static String generateToken(UserInfo userInfo, byte[] privateKey, int expireMinutes) throws Exception {
        return Jwts.builder()
                .claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
                .claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256, RsaUtils.getPrivateKey(privateKey))
                .compact();
    }

    /**
     * Public key parsing token
     *
     * @param token     token in user request
     * @param publicKey Public key
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

    /**
     * Public key parsing token
     *
     * @param token     token in user request
     * @param publicKey Public key byte array
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, byte[] publicKey) throws Exception {
        return Jwts.parser().setSigningKey(RsaUtils.getPublicKey(publicKey))
                .parseClaimsJws(token);
    }

    /**
     * Get user information in token
     *
     * @param token     Token in user request
     * @param publicKey Public key
     * @return User information
     * @throws Exception
     */
    public static UserInfo getInfoFromToken(String token, PublicKey publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                ObjectUtils.toLong(body.get(JwtConstans.JWT_KEY_ID)),
                ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
        );
    }

    /**
     * Get user information in token
     *
     * @param token     Token in user request
     * @param publicKey Public key
     * @return User information
     * @throws Exception
     */
    public static UserInfo getInfoFromToken(String token, byte[] publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                ObjectUtils.toLong(body.get(JwtConstans.JWT_KEY_ID)),
                ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
        );
    }
}

Note: The above three tool classes can be used directly.

Three. Test

1. Generating public and private keys

@SpringBootTest
@RunWith(SpringRunner.class)
public class JwtTest { 
	//Path to generate public key
	private static final String pubKeyPath = "C:\\tmp\\rsa\\rsa.pub"; 
	//Path to Generate Private Key
	private static final String priKeyPath = "C:\\tmp\\rsa\\rsa.pri"; 

	@Test 
	public void testRsa() throws Exception { 
		//Generating public and private keys
		//The more complex the salt is, the better.
		RsaUtils.generateKey(pubKeyPath, priKeyPath, "234"); 
	}
}

2. Test to get the public and private keys just generated

@SpringBootTest
@RunWith(SpringRunner.class)
public class JwtTest { 
	//Path to generate public key
	private static final String pubKeyPath = "C:\\tmp\\rsa\\rsa.pub"; 
	//Path to Generate Private Key
	private static final String priKeyPath = "C:\\tmp\\rsa\\rsa.pri"; 
	//Generated public key
	private PublicKey publicKey; 
	//Generated private key
	private PrivateKey privateKey; 

	@Test
	public void testGetRsa() throws Exception { 
		//Get public and private keys
		this.publicKey = RsaUtils.getPublicKey(pubKeyPath); 
		this.privateKey = RsaUtils.getPrivateKey(priKeyPath); 
	}
}

3. Test generation token

@SpringBootTest
@RunWith(SpringRunner.class)
public class JwtTest { 
	//Path to generate public key
	private static final String pubKeyPath = "C:\\tmp\\rsa\\rsa.pub"; 
	//Path to Generate Private Key
	private static final String priKeyPath = "C:\\tmp\\rsa\\rsa.pri"; 
	//Generated public key
	private PublicKey publicKey; 
	//Generated private key
	private PrivateKey privateKey; 

	@Before 
	public void testGetRsa() throws Exception { 
		//Get public and private keys
		this.publicKey = RsaUtils.getPublicKey(pubKeyPath); 
		this.privateKey = RsaUtils.getPrivateKey(priKeyPath); 
	}

	@Test 
	public void testGenerateToken() throws Exception { 
		// Generate token 
		String token = JwtUtils.generateToken(new UserInfo(20L, "jack"), privateKey, 5); 
		System.out.println("token = " + token); 
	}
}

4. Test parsing token

@SpringBootTest
@RunWith(SpringRunner.class)
public class JwtTest { 
	//Path to generate public key
	private static final String pubKeyPath = "C:\\tmp\\rsa\\rsa.pub"; 
	//Path to generate private key
	private static final String priKeyPath = "C:\\tmp\\rsa\\rsa.pri"; 
	//Generated public key
	private PublicKey publicKey; 
	//Generated private key
	private PrivateKey privateKey; 

	@Before 
	public void testGetRsa() throws Exception { 
		//Get public and private keys
		this.publicKey = RsaUtils.getPublicKey(pubKeyPath); 
		this.privateKey = RsaUtils.getPrivateKey(priKeyPath); 
	}

	@Test 
	public void testParseToken() throws Exception {
		//The token was just tested to generate token prints
		String token = "eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MjAsInVzZXJuYW1lIjoiamFjayIsImV4cCI6MTUzMzI4MjQ3N3 0.EPo35Vyg1IwZAtXvAx2TCWuOPnRwPclRNAM4ody5CHk8RF55wdfKKJxjeGh4H3zgruRed9mEOQzWy7 9iF1nGAnvbkraGlD6iM-9zDW8M1G9if4MX579Mv1x57lFewzEo-zKnPdFJgGlAPtNWDPv4iKvbKOk1- U7NUtRmMsF1Wcg"; 
		// analysis
		token UserInfo user = JwtUtils.getInfoFromToken(token, publicKey); 
		System.out.println("id: " + user.getId()); 
		System.out.println("userName: " + user.getUsername());
	 } 
}

Keywords: Java Session Tomcat

Added by mrodrigues on Fri, 04 Oct 2019 17:04:39 +0300