فهرست منبع

:key: 完善JWT工具

nnkwrik 6 سال پیش
والد
کامیت
5267b45d4c

+ 4 - 4
auth-service/pom.xml

@@ -26,10 +26,10 @@
     </properties>
 
     <dependencies>
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
-        </dependency>
+        <!--<dependency>-->
+            <!--<groupId>org.springframework.cloud</groupId>-->
+            <!--<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
+        <!--</dependency>-->
 
         <dependency>
             <groupId>org.springframework.boot</groupId>

+ 4 - 2
auth-service/src/main/java/io/github/nnkwrik/authservice/AuthServiceApplication.java

@@ -2,10 +2,12 @@ package io.github.nnkwrik.authservice;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.ComponentScan;
+
 
 @SpringBootApplication
-@EnableDiscoveryClient
+//@EnableDiscoveryClient
+@ComponentScan(basePackages = "io.github.nnkwrik")
 public class AuthServiceApplication {
 
     public static void main(String[] args) {

+ 26 - 12
auth-service/src/main/java/io/github/nnkwrik/authservice/controller/AuthController.java

@@ -5,28 +5,31 @@ import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import io.github.nnkwrik.authservice.config.WxMaConfiguration;
+import io.github.nnkwrik.authservice.token.TokenCreator;
 import io.github.nnkwrik.common.dto.AuthDTO;
-import io.github.nnkwrik.authservice.util.TokenFactory;
 import io.github.nnkwrik.common.dto.JWTUser;
 import io.github.nnkwrik.common.dto.Response;
+import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
 
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
 import java.util.Map;
 
 /**
  * @author nnkwrik
  * @date 18/11/12 15:32
  */
+@Slf4j
 @RestController
 public class AuthController {
-    private final Logger log = LoggerFactory.getLogger(this.getClass());
 
+    @Autowired
+    public TokenCreator creator;
 
     @GetMapping("/test")
     public String test() {
@@ -68,12 +71,23 @@ public class AuthController {
             return Response.fail(message);
         }
 
-        JWTUser jwtUser = new JWTUser();
-        jwtUser.setOpenId(openId);
-        jwtUser.setNickName(jsonMap.get("nickName"));
-        jwtUser.setAvatarUrl(jsonMap.get("avatarUrl"));
+        JWTUser jwtUser = new JWTUser(openId,jsonMap.get("nickName"),jsonMap.get("avatarUrl"));
 
-        String token = TokenFactory.createTokenFromUser(jwtUser);
+        String token =  creator.create(jwtUser);
         return Response.ok(token);
     }
+
+//    @PostMapping("/generateJwt")
+//    public String generateJwt (@RequestBody JWTUser jwtUser){
+//        String token = TokenCreator.create(jwtUser);
+//        System.out.println(token);
+//        return token;
+//    }
+//
+//    @PostMapping("/solveJwt")
+//    public JWTUser generateJwt (@RequestBody String token){
+//        JWTUser user = TokenSolver.solve(token);
+//        System.out.println(user);
+//        return user;
+//    }
 }

+ 86 - 0
auth-service/src/main/java/io/github/nnkwrik/authservice/token/RSAKeysGenerator.java

@@ -0,0 +1,86 @@
+package io.github.nnkwrik.authservice.token;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.security.*;
+import java.util.Base64;
+
+/**
+ * 生成rsa的公钥和私钥
+ * 需要把生成的公钥(.pub)拷贝到需要使用jwt的所有模块的resources目录下
+ * @author nnkwrik
+ * @date 18/11/12 11:35
+ */
+@Slf4j
+public class RSAKeysGenerator {
+
+    public static final String defaultGenerateLocation = "auth-service/src/main/resources";
+
+    public static final String defaultGenerateFilePrefix = "RSA";
+
+    public static void generateRSAKeys() {
+        generateRSAKeys(defaultGenerateLocation, defaultGenerateFilePrefix);
+    }
+
+    public static void generateRSAKeys(String location, String filePrefix) {
+        KeyPairGenerator kpg = null;
+        try {
+            kpg = KeyPairGenerator.getInstance("RSA");
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        kpg.initialize(2048);
+        KeyPair kp = kpg.generateKeyPair();
+        PrivateKey pvt = kp.getPrivate();
+        PublicKey pub = kp.getPublic();
+
+
+        Base64.Encoder encoder = Base64.getEncoder();
+        String outFile = location + "/" + filePrefix;
+
+        Writer out = null;
+        try {
+            if (outFile != null) out = new FileWriter(outFile + ".key");
+            else out = new OutputStreamWriter(System.out);
+
+            System.err.println("Private key format: " +
+                    kp.getPrivate().getFormat());
+            out.write("-----BEGIN RSA PRIVATE KEY-----\n");
+            out.write(encoder.encodeToString(pvt.getEncoded()));
+            out.write("\n-----END RSA PRIVATE KEY-----\n");
+
+            if (outFile != null) {
+                out.close();
+                out = new FileWriter(outFile + ".pub");
+            }
+
+            System.err.println("Public key format: " +
+                    kp.getPublic().getFormat());
+            out.write("-----BEGIN RSA PUBLIC KEY-----\n");
+            out.write(encoder.encodeToString(pub.getEncoded()));
+            out.write("\n-----END RSA PUBLIC KEY-----\n");
+        } catch (IOException e) {
+            log.info("密钥生成失败");
+            e.printStackTrace();
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                    log.info("文件流关闭失败");
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+
+
+    public static void main(String[] args) {
+        generateRSAKeys();
+    }
+}

+ 61 - 0
auth-service/src/main/java/io/github/nnkwrik/authservice/token/TokenCreator.java

@@ -0,0 +1,61 @@
+package io.github.nnkwrik.authservice.token;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.interfaces.RSAKeyProvider;
+import io.github.nnkwrik.common.dto.JWTUser;
+import io.github.nnkwrik.common.token.RSAKeysReader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+
+
+/**
+ * @author nnkwrik
+ * @date 18/11/12 14:18
+ */
+@Component
+public class TokenCreator {
+
+    @Value("${jwt.pvt-key-file-name}")
+    private String pvtFile;
+
+    private RSAKeyProvider keyProvider = new RSAKeyProvider() {
+        @Override
+        public RSAPublicKey getPublicKeyById(String s) {
+            return null;
+        }
+
+        @Override
+        public RSAPrivateKey getPrivateKey() {
+            return RSAKeysReader.readRsaPvt(pvtFile);
+        }
+
+        @Override
+        public String getPrivateKeyId() {
+            return null;
+        }
+    };
+
+    public String create(JWTUser jwtUser) {
+        Algorithm algorithm = Algorithm.RSA256(keyProvider);
+        //一天后过期
+        Date expire = Date.from(Instant.now().plus(1, ChronoUnit.DAYS));
+
+        String token = JWT.create()
+                .withClaim("openId", jwtUser.getOpenId())
+                .withClaim("nickName", jwtUser.getNickName())
+                .withClaim("avatarUrl", jwtUser.getAvatarUrl())
+                .withExpiresAt(expire)
+                .sign(algorithm);
+
+        return "Bearer " + token;
+    }
+
+}

+ 0 - 157
auth-service/src/main/java/io/github/nnkwrik/authservice/util/RSAKeysUtil.java

@@ -1,157 +0,0 @@
-package io.github.nnkwrik.authservice.util;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.*;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.Base64;
-
-/**
- * @author nnkwrik
- * @date 18/11/12 11:35
- */
-public class RSAKeysUtil {
-
-    private static final Logger log = LoggerFactory.getLogger(RSAKeysUtil.class);
-
-    public static final String defaultLocation = "auth-service/src/main/resources";
-
-    public static final String defaultFilePrefix = "RSA";
-
-    public static void generateRSAKeys() {
-        generateRSAKeys(defaultLocation, defaultFilePrefix);
-    }
-
-    public static void generateRSAKeys(String location, String filePrefix) {
-        KeyPairGenerator kpg = null;
-        try {
-            kpg = KeyPairGenerator.getInstance("RSA");
-        } catch (NoSuchAlgorithmException e) {
-            e.printStackTrace();
-        }
-        kpg.initialize(2048);
-        KeyPair kp = kpg.generateKeyPair();
-        PrivateKey pvt = kp.getPrivate();
-        PublicKey pub = kp.getPublic();
-
-
-        Base64.Encoder encoder = Base64.getEncoder();
-        String outFile = location + "/" + filePrefix;
-
-        Writer out = null;
-        try {
-            if (outFile != null) out = new FileWriter(outFile + ".key");
-            else out = new OutputStreamWriter(System.out);
-
-            System.err.println("Private key format: " +
-                    kp.getPrivate().getFormat());
-            out.write("-----BEGIN RSA PRIVATE KEY-----\n");
-            out.write(encoder.encodeToString(pvt.getEncoded()));
-            out.write("\n-----END RSA PRIVATE KEY-----\n");
-
-            if (outFile != null) {
-                out.close();
-                out = new FileWriter(outFile + ".pub");
-            }
-
-            System.err.println("Public key format: " +
-                    kp.getPublic().getFormat());
-            out.write("-----BEGIN RSA PUBLIC KEY-----\n");
-            out.write(encoder.encodeToString(pub.getEncoded()));
-            out.write("\n-----END RSA PUBLIC KEY-----\n");
-        } catch (IOException e) {
-            log.info("密钥生成失败");
-            e.printStackTrace();
-        } finally {
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    log.info("文件流关闭失败");
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-
-    public static RSAPrivateKey readRsaPvt() {
-        return readRsaPvt(defaultLocation, defaultFilePrefix);
-    }
-
-    public static RSAPrivateKey readRsaPvt(String location, String filePrefix) {
-        Path path = Paths.get(location + "/" + filePrefix + ".key");
-        String data = "";
-        try {
-            data = new String(Files.readAllBytes(path));
-        } catch (IOException e) {
-            log.info("文件读取失败");
-            e.printStackTrace();
-        }
-        data = data.replace("-----BEGIN RSA PRIVATE KEY-----\n", "")
-                .replace("\n-----END RSA PRIVATE KEY-----\n", "");
-
-
-        byte[] bytes = Base64.getDecoder().decode(data);
-
-        PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
-        KeyFactory kf = null;
-        PrivateKey pvt = null;
-        try {
-            kf = KeyFactory.getInstance("RSA");
-            pvt = kf.generatePrivate(ks);
-        } catch (Exception e) {
-            log.info("私钥读取失败");
-            e.printStackTrace();
-        }
-
-        return (RSAPrivateKey) pvt;
-    }
-
-    public static RSAPublicKey readRsaPub() {
-        return readRsaPub(defaultLocation, defaultFilePrefix);
-    }
-
-    public static RSAPublicKey readRsaPub(String location, String filePrefix) {
-        Path path = Paths.get(location + "/" + filePrefix + ".pub");
-        String data = "";
-        try {
-            data = new String(Files.readAllBytes(path));
-        } catch (IOException e) {
-            log.info("文件读取失败");
-            e.printStackTrace();
-        }
-        data = data.replace("-----BEGIN RSA PUBLIC KEY-----\n", "")
-                .replace("\n-----END RSA PUBLIC KEY-----\n", "");
-
-
-        byte[] bytes = Base64.getDecoder().decode(data);
-
-        X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
-        KeyFactory kf = null;
-        PublicKey pub = null;
-        try {
-            kf = KeyFactory.getInstance("RSA");
-            pub = kf.generatePublic(ks);
-        } catch (Exception e) {
-            log.info("公钥读取失败");
-            e.printStackTrace();
-        }
-
-        return (RSAPublicKey) pub;
-    }
-
-    public static void main(String[] args) {
-        generateRSAKeys();
-    }
-}

+ 0 - 33
auth-service/src/main/java/io/github/nnkwrik/authservice/util/RSAPubKeyProvider.java

@@ -1,33 +0,0 @@
-package io.github.nnkwrik.authservice.util;
-
-import com.auth0.jwt.interfaces.RSAKeyProvider;
-
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-
-/**
- * @author nnkwrik
- * @date 18/11/12 15:02
- */
-public class RSAPubKeyProvider implements RSAKeyProvider {
-    private final RSAPublicKey publicKey;
-
-    public RSAPubKeyProvider() {
-        publicKey = RSAKeysUtil.readRsaPub();
-    }
-
-    @Override
-    public RSAPublicKey getPublicKeyById(String s) {
-        return publicKey;
-    }
-
-    @Override
-    public RSAPrivateKey getPrivateKey() {
-        return null;
-    }
-
-    @Override
-    public String getPrivateKeyId() {
-        return null;
-    }
-}

+ 0 - 33
auth-service/src/main/java/io/github/nnkwrik/authservice/util/RSAPvtKeyProvider.java

@@ -1,33 +0,0 @@
-package io.github.nnkwrik.authservice.util;
-
-import com.auth0.jwt.interfaces.RSAKeyProvider;
-
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-
-/**
- * @author nnkwrik
- * @date 18/11/12 15:02
- */
-public class RSAPvtKeyProvider implements RSAKeyProvider {
-    private final RSAPrivateKey privateKey;
-
-    public RSAPvtKeyProvider() {
-        privateKey = RSAKeysUtil.readRsaPvt();
-    }
-
-    @Override
-    public RSAPublicKey getPublicKeyById(String s) {
-        return null;
-    }
-
-    @Override
-    public RSAPrivateKey getPrivateKey() {
-        return privateKey;
-    }
-
-    @Override
-    public String getPrivateKeyId() {
-        return null;
-    }
-}

+ 0 - 47
auth-service/src/main/java/io/github/nnkwrik/authservice/util/TokenFactory.java

@@ -1,47 +0,0 @@
-package io.github.nnkwrik.authservice.util;
-
-import com.auth0.jwt.JWT;
-import com.auth0.jwt.algorithms.Algorithm;
-import com.auth0.jwt.interfaces.DecodedJWT;
-import io.github.nnkwrik.common.dto.JWTUser;
-
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Date;
-
-
-/**
- * @author nnkwrik
- * @date 18/11/12 14:18
- */
-public class TokenFactory {
-
-    public static String createTokenFromUser(JWTUser jwtUser) {
-        Algorithm algorithm = Algorithm.RSA256(new RSAPvtKeyProvider());
-        //一天后过期
-        Date expire = Date.from(Instant.now().plus(1, ChronoUnit.DAYS));
-
-        String token = JWT.create()
-                .withClaim("openId", jwtUser.getOpenId())
-                .withClaim("nickName", jwtUser.getNickName())
-                .withClaim("avatarUrl", jwtUser.getAvatarUrl())
-                .withExpiresAt(expire)
-                .sign(algorithm);
-
-        return "Bearer " + token;
-    }
-
-    public static JWTUser createUserFromToken(String token) {
-        Algorithm algorithm = Algorithm.RSA256(new RSAPubKeyProvider());
-        //会自动验证过期时间
-        DecodedJWT decodedJWT = JWT.require(algorithm).build().verify(token);
-        JWTUser jwtUser = new JWTUser();
-
-        jwtUser.setOpenId(decodedJWT.getClaim("openId").asString());
-        jwtUser.setNickName(decodedJWT.getClaim("nickName").asString());
-        jwtUser.setAvatarUrl(decodedJWT.getClaim("avatarUrl").asString());
-
-        return jwtUser;
-    }
-
-}

+ 6 - 1
auth-service/src/main/resources/application.yml

@@ -10,4 +10,9 @@ spring:
     include: secret
 
 server:
-  port: 8803
+  port: 8803
+
+
+jwt:
+  pvt-key-file-name: RSA.key
+  pub-key-file-name: RSA.pub

+ 39 - 0
auth-service/src/test/java/io/github/nnkwrik/authservice/jwt/GenerateToken.java

@@ -0,0 +1,39 @@
+package io.github.nnkwrik.authservice.jwt;
+
+import io.github.nnkwrik.authservice.token.TokenCreator;
+import io.github.nnkwrik.common.dto.JWTUser;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/19 9:47
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class GenerateToken {
+
+    @Autowired
+    private TokenCreator creator;
+
+    /**
+     * 生产环境下可以用这个生成Token进行测试
+     */
+    @Test
+    public void generateToken(){
+        String openId = "1212";
+        String nickName = "nickname";
+        String avatarUrl = "https://avatars2.githubusercontent.com/u/29662114?s=460&v=4";
+
+        JWTUser jwtUser = new JWTUser(openId,nickName,avatarUrl);
+        String token = creator.create(jwtUser);
+
+        System.out.println("==================== 生成的Token =========================\n");
+        System.out.println(token);
+        System.out.println("\n=========================================================");
+
+    }
+}

+ 57 - 0
auth-service/src/test/java/io/github/nnkwrik/authservice/jwt/TestToken.java

@@ -0,0 +1,57 @@
+package io.github.nnkwrik.authservice.jwt;
+
+import io.github.nnkwrik.authservice.token.TokenCreator;
+import io.github.nnkwrik.common.dto.JWTUser;
+import io.github.nnkwrik.common.token.TokenSolver;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/18 22:20
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class TestToken {
+
+    @Value("${jwt.pub-key-file-name}")
+    private String pubFile;
+
+    @Value("${jwt.pvt-key-file-name}")
+    private String pvtFile;
+
+    @Autowired
+    private TokenCreator creator;
+
+    @Autowired
+    private TokenSolver solver;
+
+
+    @Test
+    public void testToken(){
+        //测试注入密钥文件名
+        System.out.println(pubFile);
+        System.out.println(pvtFile);
+
+        JWTUser jwtUser = new JWTUser();
+        jwtUser.setOpenId("1212");
+        jwtUser.setNickName("nickName");
+
+
+        //找到resource目录下的私钥文件后生成Token
+        String token = creator.create(jwtUser);
+        System.out.println(token);
+
+        token = token.replace("Bearer ", "");
+
+        //找到resource目录下的公钥文件后还原用户信息
+        JWTUser user = solver.solve(token);
+        System.out.println(user);
+
+    }
+
+}

+ 19 - 0
common/pom.xml

@@ -11,6 +11,13 @@
     <name>common</name>
     <description>Demo project for Spring Boot</description>
 
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.1.0.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -19,12 +26,24 @@
     </properties>
 
     <dependencies>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <version>1.16.20</version>
             <scope>provided</scope>
         </dependency>
+
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.4.1</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 4 - 0
common/src/main/java/io/github/nnkwrik/common/dto/JWTUser.java

@@ -1,12 +1,16 @@
 package io.github.nnkwrik.common.dto;
 
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 /**
  * @author nnkwrik
  * @date 18/11/12 14:12
  */
 @Data
+@NoArgsConstructor
+@AllArgsConstructor
 public class JWTUser {
 
     private String openId;

+ 83 - 0
common/src/main/java/io/github/nnkwrik/common/token/RSAKeysReader.java

@@ -0,0 +1,83 @@
+package io.github.nnkwrik.common.token;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.io.ClassPathResource;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/18 21:38
+ */
+@Slf4j
+public class RSAKeysReader {
+
+
+    public static RSAPrivateKey readRsaPvt(String fileName) {
+        String data = getData(fileName);
+        data = data.replace("-----BEGIN RSA PRIVATE KEY-----\n", "")
+                .replace("\n-----END RSA PRIVATE KEY-----\n", "");
+
+
+        byte[] bytes = Base64.getDecoder().decode(data);
+
+        PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
+        KeyFactory kf = null;
+        PrivateKey pvt = null;
+        try {
+            kf = KeyFactory.getInstance("RSA");
+            pvt = kf.generatePrivate(ks);
+        } catch (Exception e) {
+            log.info("私钥读取失败");
+            e.printStackTrace();
+        }
+
+        return (RSAPrivateKey) pvt;
+    }
+
+
+    public static RSAPublicKey readRsaPub(String fileName) {
+        String data = getData(fileName);
+        data = data.replace("-----BEGIN RSA PUBLIC KEY-----\n", "")
+                .replace("\n-----END RSA PUBLIC KEY-----\n", "");
+
+
+        byte[] bytes = Base64.getDecoder().decode(data);
+
+        X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
+        KeyFactory kf = null;
+        PublicKey pub = null;
+        try {
+            kf = KeyFactory.getInstance("RSA");
+            pub = kf.generatePublic(ks);
+        } catch (Exception e) {
+            log.info("公钥读取失败");
+            e.printStackTrace();
+        }
+
+        return (RSAPublicKey) pub;
+    }
+
+    private static String getData(String fileName){
+        String data = "";
+        try {
+            File file = new ClassPathResource(fileName).getFile();
+            log.info("从[{}]试图读取秘钥文件",file.getPath());
+            data = new String(Files.readAllBytes(file.toPath()));
+        } catch (IOException e) {
+            log.info("文件读取失败");
+            e.printStackTrace();
+        }
+        return data;
+    }
+}

+ 54 - 0
common/src/main/java/io/github/nnkwrik/common/token/TokenSolver.java

@@ -0,0 +1,54 @@
+package io.github.nnkwrik.common.token;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.auth0.jwt.interfaces.RSAKeyProvider;
+import io.github.nnkwrik.common.dto.JWTUser;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/18 21:27
+ */
+@Component
+public class TokenSolver {
+
+    @Value("${jwt.pub-key-file-name}")
+    private String pubFile;
+
+    private RSAKeyProvider keyProvider = new RSAKeyProvider() {
+        @Override
+        public RSAPublicKey getPublicKeyById(String s) {
+            return RSAKeysReader.readRsaPub(pubFile);
+        }
+
+        @Override
+        public RSAPrivateKey getPrivateKey() {
+            return null;
+        }
+
+        @Override
+        public String getPrivateKeyId() {
+            return null;
+        }
+    };
+
+    public JWTUser solve(String token) {
+        token = token.replace("Bearer ", "");
+        Algorithm algorithm = Algorithm.RSA256(keyProvider);
+        //会自动验证过期时间
+        DecodedJWT decodedJWT = JWT.require(algorithm).build().verify(token);
+        JWTUser jwtUser = new JWTUser();
+
+        jwtUser.setOpenId(decodedJWT.getClaim("openId").asString());
+        jwtUser.setNickName(decodedJWT.getClaim("nickName").asString());
+        jwtUser.setAvatarUrl(decodedJWT.getClaim("avatarUrl").asString());
+
+        return jwtUser;
+    }
+}