소스 검색

:rabbit: jwt代替redis

nnkwrik 6 년 전
부모
커밋
64fe118161
32개의 변경된 파일1233개의 추가작업 그리고 226개의 파일을 삭제
  1. 3 1
      .gitignore
  2. 25 0
      auth-service/.gitignore
  3. 106 0
      auth-service/pom.xml
  4. 14 0
      auth-service/src/main/java/io/github/nnkwrik/authservice/AuthServiceApplication.java
  5. 44 0
      auth-service/src/main/java/io/github/nnkwrik/authservice/config/WxMaConfiguration.java
  6. 1 1
      auth-service/src/main/java/io/github/nnkwrik/authservice/config/WxMaProperties.java
  7. 79 0
      auth-service/src/main/java/io/github/nnkwrik/authservice/controller/AuthController.java
  8. 157 0
      auth-service/src/main/java/io/github/nnkwrik/authservice/util/RSAKeysUtil.java
  9. 33 0
      auth-service/src/main/java/io/github/nnkwrik/authservice/util/RSAPubKeyProvider.java
  10. 33 0
      auth-service/src/main/java/io/github/nnkwrik/authservice/util/RSAPvtKeyProvider.java
  11. 47 0
      auth-service/src/main/java/io/github/nnkwrik/authservice/util/TokenFactory.java
  12. 13 0
      auth-service/src/main/resources/application.yml
  13. 16 0
      auth-service/src/test/java/io/github/nnkwrik/authservice/AuthServiceApplicationTests.java
  14. 40 0
      common/pom.xml
  15. 16 0
      common/src/main/java/io/github/nnkwrik/common/dto/AuthDTO.java
  16. 17 0
      common/src/main/java/io/github/nnkwrik/common/dto/JWTUser.java
  17. 140 0
      common/src/main/java/io/github/nnkwrik/common/dto/Response.java
  18. 2 0
      dev/ngrok/start.sh
  19. 96 24
      mini-app/app.js
  20. 41 36
      mini-app/pages/index/index.js
  21. 3 2
      mini-app/pages/index/index.wxml
  22. 32 0
      user-service/pom.xml
  23. 2 0
      user-service/src/main/java/io/github/nnkwrik/userservice/UserServiceApplication.java
  24. 22 0
      user-service/src/main/java/io/github/nnkwrik/userservice/client/AuthClient.java
  25. 0 122
      user-service/src/main/java/io/github/nnkwrik/userservice/config/WxMaConfiguration.java
  26. 53 24
      user-service/src/main/java/io/github/nnkwrik/userservice/controller/UserController.java
  27. 18 0
      user-service/src/main/java/io/github/nnkwrik/userservice/dao/UserMapper.java
  28. 5 2
      user-service/src/main/java/io/github/nnkwrik/userservice/model/User.java
  29. 3 2
      user-service/src/main/java/io/github/nnkwrik/userservice/service/UserService.java
  30. 24 0
      user-service/src/main/java/io/github/nnkwrik/userservice/service/impl/UserServiceImpl.java
  31. 140 0
      user-service/src/main/java/io/github/nnkwrik/userservice/util/Response.java
  32. 8 12
      user-service/src/main/resources/application.yml

+ 3 - 1
.gitignore

@@ -12,4 +12,6 @@
 
 # other
 dev/mysql/data/*
-user-service/src/main/resources/application-secret.yml
+auth-service/src/main/resources/application-secret.yml
+**/*.key
+**/*.pub

+ 25 - 0
auth-service/.gitignore

@@ -0,0 +1,25 @@
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/

+ 106 - 0
auth-service/pom.xml

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>io.github.nnkwrik</groupId>
+    <artifactId>auth-service</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>auth-service</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>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+        <spring-cloud.version>Greenwich.M1</spring-cloud.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-miniapp</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.github.nnkwrik</groupId>
+            <artifactId>common</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+
+
+
+    </dependencies>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-dependencies</artifactId>
+                <version>${spring-cloud.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>spring-milestones</id>
+            <name>Spring Milestones</name>
+            <url>https://repo.spring.io/milestone</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+
+</project>

+ 14 - 0
auth-service/src/main/java/io/github/nnkwrik/authservice/AuthServiceApplication.java

@@ -0,0 +1,14 @@
+package io.github.nnkwrik.authservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+@SpringBootApplication
+@EnableDiscoveryClient
+public class AuthServiceApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(AuthServiceApplication.class, args);
+    }
+}

+ 44 - 0
auth-service/src/main/java/io/github/nnkwrik/authservice/config/WxMaConfiguration.java

@@ -0,0 +1,44 @@
+package io.github.nnkwrik.authservice.config;
+
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
+import cn.binarywang.wx.miniapp.config.WxMaInMemoryConfig;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author <a href="https://github.com/binarywang">Binary Wang</a>
+ */
+@Configuration
+@EnableConfigurationProperties(WxMaProperties.class)
+public class WxMaConfiguration {
+
+    private WxMaProperties properties;
+    private static WxMaService maServices;
+
+
+    @Autowired
+    public WxMaConfiguration(WxMaProperties properties) {
+        this.properties = properties;
+    }
+
+
+    public static WxMaService getMaServices() {
+        return maServices;
+    }
+
+    @Bean
+    public Object services() {
+        WxMaInMemoryConfig config = new WxMaInMemoryConfig();
+        BeanUtils.copyProperties(properties,config);
+        maServices = new WxMaServiceImpl();
+        maServices.setWxMaConfig(config);
+
+        return Boolean.TRUE;
+    }
+
+
+}

+ 1 - 1
user-service/src/main/java/io/github/nnkwrik/userservice/config/WxMaProperties.java → auth-service/src/main/java/io/github/nnkwrik/authservice/config/WxMaProperties.java

@@ -1,4 +1,4 @@
-package io.github.nnkwrik.userservice.config;
+package io.github.nnkwrik.authservice.config;
 
 import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;

+ 79 - 0
auth-service/src/main/java/io/github/nnkwrik/authservice/controller/AuthController.java

@@ -0,0 +1,79 @@
+package io.github.nnkwrik.authservice.controller;
+
+import cn.binarywang.wx.miniapp.api.WxMaUserService;
+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.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 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 java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/12 15:32
+ */
+@RestController
+public class AuthController {
+    private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+
+    @GetMapping("/test")
+    public String test() {
+        return "test is success";
+    }
+
+    @PostMapping("/login")
+    public Response login(@RequestBody AuthDTO authDTO) {
+        log.info("用户登录 : {}", authDTO);
+        WxMaUserService wxUserService = WxMaConfiguration.getMaServices().getUserService();
+
+        //验证用户登录凭证
+        WxMaJscode2SessionResult sessionInfo = null;
+        try {
+            sessionInfo = wxUserService.getSessionInfo(authDTO.getJsCode());
+        } catch (WxErrorException e) {
+            return Response.fail("凭证失效,登录失败");
+        }
+
+        //验证用户给出的userInfo是否正确
+        String sessionKey = sessionInfo.getSessionKey();
+        String openId = sessionInfo.getOpenid();
+        if (!wxUserService.checkUserInfo(sessionKey, authDTO.getRawData(), authDTO.getSignature())) {
+            String message = "userInfo 和 session 中的不一致";
+            log.info(message);
+            return Response.fail(message);
+        }
+
+        //构造JWT token
+        ObjectMapper mapper = new ObjectMapper();
+        Map<String, String> jsonMap = null;
+        try {
+            jsonMap = mapper.readValue(authDTO.getRawData(), new TypeReference<Map<String, String>>() {
+            });
+        } catch (IOException e) {
+            String message = "Json转Map失败";
+            log.info(message);
+            e.printStackTrace();
+            return Response.fail(message);
+        }
+
+        JWTUser jwtUser = new JWTUser();
+        jwtUser.setOpenId(openId);
+        jwtUser.setNickName(jsonMap.get("nickName"));
+        jwtUser.setAvatarUrl(jsonMap.get("avatarUrl"));
+
+        String token = TokenFactory.createTokenFromUser(jwtUser);
+        return Response.ok(token);
+    }
+}

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

@@ -0,0 +1,157 @@
+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();
+    }
+}

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

@@ -0,0 +1,33 @@
+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;
+    }
+}

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

@@ -0,0 +1,33 @@
+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;
+    }
+}

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

@@ -0,0 +1,47 @@
+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;
+    }
+
+}

+ 13 - 0
auth-service/src/main/resources/application.yml

@@ -0,0 +1,13 @@
+eureka:
+  client:
+    service-url:
+      defaultZone: http://localhost:8801/eureka/
+
+spring:
+  application:
+    name: auth-service
+  profiles:
+    include: secret
+
+server:
+  port: 8803

+ 16 - 0
auth-service/src/test/java/io/github/nnkwrik/authservice/AuthServiceApplicationTests.java

@@ -0,0 +1,16 @@
+package io.github.nnkwrik.authservice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class AuthServiceApplicationTests {
+
+    @Test
+    public void contextLoads() {
+    }
+
+}

+ 40 - 0
common/pom.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>io.github.nnkwrik</groupId>
+    <artifactId>common</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>common</name>
+    <description>Demo project for Spring Boot</description>
+
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.16.20</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>

+ 16 - 0
common/src/main/java/io/github/nnkwrik/common/dto/AuthDTO.java

@@ -0,0 +1,16 @@
+package io.github.nnkwrik.common.dto;
+
+import lombok.Data;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/12 15:49
+ */
+@Data
+public class AuthDTO {
+    private String jsCode;
+    private String signature;
+    private String rawData;
+//    private String encryptedData;
+//    private String iv;
+}

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

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

+ 140 - 0
common/src/main/java/io/github/nnkwrik/common/dto/Response.java

@@ -0,0 +1,140 @@
+package io.github.nnkwrik.common.dto;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/11 16:42
+ */
+public class Response<T> {
+    /**
+     * 服务器响应数据
+     */
+    private T payload;
+
+    /**
+     * 请求是否成功
+     */
+    private boolean success;
+
+    /**
+     * 错误信息
+     */
+    private String msg;
+
+    /**
+     * 状态码
+     */
+    private int code = -1;
+
+    /**
+     * 服务器响应时间
+     */
+    private long timestamp;
+
+    public Response() {
+        this.timestamp = System.currentTimeMillis() / 1000;
+    }
+
+    public Response(boolean success) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+    }
+
+    public Response(boolean success, T payload) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+        this.payload = payload;
+    }
+
+    public Response(boolean success, T payload, int code) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+        this.payload = payload;
+        this.code = code;
+    }
+
+    public Response(boolean success, String msg) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+        this.msg = msg;
+    }
+
+    public Response(boolean success, String msg, int code) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+        this.msg = msg;
+        this.code = code;
+    }
+
+    public T getPayload() {
+        return payload;
+    }
+
+    public void setPayload(T payload) {
+        this.payload = payload;
+    }
+
+    public boolean isSuccess() {
+        return success;
+    }
+
+    public void setSuccess(boolean success) {
+        this.success = success;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public static Response ok() {
+        return new Response(true);
+    }
+
+    public static <T> Response ok(T payload) {
+        return new Response(true, payload);
+    }
+
+    public static <T> Response ok(int code) {
+        return new Response(true, null, code);
+    }
+
+    public static <T> Response ok(T payload, int code) {
+        return new Response(true, payload, code);
+    }
+
+    public static Response fail() {
+        return new Response(false);
+    }
+
+    public static Response fail(String msg) {
+        return new Response(false, msg);
+    }
+
+    public static Response fail(int code) {
+        return new Response(false, null, code);
+    }
+
+    public static Response fail(int code, String msg) {
+        return new Response(false, msg, code);
+    }
+
+}

+ 2 - 0
dev/ngrok/start.sh

@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+./ngrok http 8802

+ 96 - 24
mini-app/app.js

@@ -1,35 +1,97 @@
 //app.js
 App({
-  onLaunch: function () {
+  onLaunch: function() {
     // 展示本地存储能力
     var logs = wx.getStorageSync('logs') || []
     logs.unshift(Date.now())
     wx.setStorageSync('logs', logs)
 
-    // 登录
-    wx.login({
+    wx.getUserInfo({
       success: res => {
-        // 发送 res.code 到后台换取 openId, sessionKey, unionId
+        // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
+        // 没授权的状态下调用getUserInfo会弹框
+
+        this.globalData.userInfo = res.userInfo
+        this.globalData.rawData = res.rawData
+        this.globalData.signature = res.signature
+        console.log("获取用户信息" + res.rawData)
+
+        // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
+        // 所以此处加入 callback 以防止这种情况
+        if (this.userInfoReadyCallback) {
+          console.log("app.userInfoReadyCallback" + res.iv)
+          this.userInfoReadyCallback(res)
+        }
+      }
+    })
+    // 检查sessionKey
+    wx.checkSession({
+      fail() {
+        // session_key 已经失效,需要重新执行登录流程
+        wx.login({
+          success: res => {
+            var userInfo = wx.getStorageSync("userInfo")
+            if (userInfo == null && wx.setStorageSync("token") == null){
+              //注册
+              console.log("注册")
+              wx.setStorage("userInfo", this.globalData.userInfo)
+            } else if (userInfo != this.globalData.userInfo) {
+              //更新 userInfo 和 token
+              console.log("更新 userInfo 和 token")
+              wx.setStorage("userInfo", this.globalData.userInfo)
+            } else  {
+              //更新token
+              console.log("更新token")
+            } 
+          }
+        })
       }
     })
+
     // 获取用户信息
-    wx.getSetting({
-      success: res => {
-        if (res.authSetting['scope.userInfo']) {
-          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
-          wx.getUserInfo({
-            success: res => {
-              // 可以将 res 发送给后台解码出 unionId
-              this.globalData.userInfo = res.userInfo
+    // wx.getSetting({
+    //   success: res => {
+    //     if (res.authSetting['scope.userInfo']) {
+    //       // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
+    //       // 没授权的状态下调用getUserInfo会弹框
+    //       wx.getUserInfo({
+    //         success: res => {
+    //           console.log("app.getUserInfo" + res.iv)
+    //           // 可以将 res 发送给后台解码出 unionId
+    //           this.globalData.userInfo = res.userInfo
+    //           this.globalData.rawData = res.rawData
+    //           this.globalData.signature = res.signature
+    //           this.globalData.encryptedData = res.encryptedData
+    //           this.globalData.iv = res.iv
 
-              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
-              // 所以此处加入 callback 以防止这种情况
-              if (this.userInfoReadyCallback) {
-                this.userInfoReadyCallback(res)
-              }
-            }
-          })
-        }
+    //           // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
+    //           // 所以此处加入 callback 以防止这种情况
+    //           if (this.userInfoReadyCallback) {
+    //             console.log("app.userInfoReadyCallback" + res.iv)
+    //             this.userInfoReadyCallback(res)
+    //           }
+    //         }
+    //       })
+    //     }
+    //   }
+    // })
+  },
+  register: function () {
+    //注册新用户
+    wx.request({
+      url: this.globalData.host + "/register",
+      data: {
+        jsCode: res.code,
+        rawData: this.globalData.rawData,
+        signature: this.globalData.signature
+      },
+      header: {
+        'content-type': 'application/json' // 默认值
+      },
+      dataType: "json",
+      method: "POST",
+      success(res) {
+        console.log(res.data)
       }
     })
   },
@@ -37,8 +99,18 @@ App({
     userInfo: null,
     rawData: '',
     signature: '',
-    encryptedData: '',
-    iv: '',
-    host: "http://e87c8984.ngrok.io"
+    host: "https://77ee0a14.ngrok.io"
   }
-})
+})
+
+/*
+已登录的情况
+app.getUserInfosCddGUbsg0MB3oB7tvlmfA==
+app.userInfoReadyCallbacksCddGUbsg0MB3oB7tvlmfA==
+page.userInfoReadyCallbacksCddGUbsg0MB3oB7tvlmfA==
+*/
+/*
+未登录
+先点,点击登录授权
+page.bindGetUserInfoBObXMSFjVRixIoyncg2kyA==
+*/

+ 41 - 36
mini-app/pages/index/index.js

@@ -6,7 +6,7 @@ Page({
     motto: 'Hello World',
     userInfo: {},
     hasUserInfo: false,
-    canIUse: wx.canIUse('button.open-type.getUserInfo')
+    canIUse: wx.canIUse('button.open-type.getUserInfo')//组件是否可用
   },
   //事件处理函数
   bindViewTap: function() {
@@ -14,35 +14,37 @@ Page({
       url: '../logs/logs'
     })
   },
-  // onLoad: function () {
-  //   if (app.globalData.userInfo) {
-  //     this.setData({
-  //       userInfo: app.globalData.userInfo,
-  //       hasUserInfo: true
-  //     })
-  //   } else if (this.data.canIUse){
-  //     // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
-  //     // 所以此处加入 callback 以防止这种情况
-  //     app.userInfoReadyCallback = res => {
-  //       this.setData({
-  //         userInfo: res.userInfo,
-  //         hasUserInfo: true
-  //       })
-  //     }
-  //   } else {
-  //     // 在没有 open-type=getUserInfo 版本的兼容处理
-  //     wx.getUserInfo({
-  //       success: res => {
-  //         app.globalData.userInfo = res.userInfo
-  //         this.setData({
-  //           userInfo: res.userInfo,
-  //           hasUserInfo: true
-  //         })
-  //       }
-  //     })
-  //   }
-  // },
+  onLoad: function () {
+    if (app.globalData.userInfo) {
+      this.setData({
+        userInfo: app.globalData.userInfo,
+        hasUserInfo: true
+      })
+    } else if (this.data.canIUse){
+      // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
+      // 所以此处加入 callback 以防止这种情况
+      app.userInfoReadyCallback = res => {
+        console.log("page.userInfoReadyCallback" + res.iv)
+        this.setData({
+          userInfo: res.userInfo,
+          hasUserInfo: true
+        })
+      }
+    } else {
+      // 在没有 open-type=getUserInfo 版本的兼容处理
+      wx.getUserInfo({
+        success: res => {
+          app.globalData.userInfo = res.userInfo
+          this.setData({
+            userInfo: res.userInfo,
+            hasUserInfo: true
+          })
+        }
+      })
+    }
+  },
   bindGetUserInfo: function(e) {
+    console.log("page.bindGetUserInfo" + e.detail.iv)
     console.log(e)
     app.globalData.userInfo = e.detail.userInfo
     this.setData({
@@ -54,11 +56,10 @@ Page({
     // 获取userInfo
     wx.getUserInfo({
         success: res => {
-          app.globalData.userInfo = res.userInfo,
-            app.globalData.rawData = res.rawData,
-            app.globalData.signature = res.signature,
-            app.globalData.encryptedData = res.encryptedData,
-            app.globalData.iv = res.iv
+            app.globalData.rawData = res.rawData
+            app.globalData.signature = res.signature
+          console.log(app.globalData.rawData)
+          console.log(app.globalData.signature)
         }
       }),
       wx.login({
@@ -67,8 +68,12 @@ Page({
 
             //发起网络请求
             wx.request({
-              url: app.globalData.host + "/wx/user/login/" + res.code,
-              data: app.globalData.userInfo,
+              url: app.globalData.host + "/register",
+              data: {
+                jsCode: res.code,
+                rawData: app.globalData.rawData,
+                signature: app.globalData.signature
+              },
               header: {
                 'content-type': 'application/json' // 默认值
               },

+ 3 - 2
mini-app/pages/index/index.wxml

@@ -1,8 +1,9 @@
 <!--index.wxml-->
 <view class="container">
   <view class="userinfo">
-    <!-- <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo"> 点击登录 </button> -->
-    <button wx:if="{{!hasUserInfo && canIUse}}" bindtap='login'> 点击登录 </button>
+  <!-- 点了之后就会调用wx.getUserInfo, 随后调用bindGetUserInfo -->
+    <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo"> 点击登录 </button>
+    <!-- <button wx:if="{{true}}" bindtap='login'> 点击登录 </button> -->
     <block wx:else>
       <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
       <text class="userinfo-nickname">{{userInfo.nickName}}</text>

+ 32 - 0
user-service/pom.xml

@@ -31,6 +31,11 @@
             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
@@ -54,6 +59,33 @@
             <scope>provided</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.github.nnkwrik</groupId>
+            <artifactId>common</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 
     <dependencyManagement>

+ 2 - 0
user-service/src/main/java/io/github/nnkwrik/userservice/UserServiceApplication.java

@@ -3,9 +3,11 @@ package io.github.nnkwrik.userservice;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
 
 @SpringBootApplication
 @EnableDiscoveryClient
+@EnableFeignClients
 public class UserServiceApplication {
 
     public static void main(String[] args) {

+ 22 - 0
user-service/src/main/java/io/github/nnkwrik/userservice/client/AuthClient.java

@@ -0,0 +1,22 @@
+package io.github.nnkwrik.userservice.client;
+
+import io.github.nnkwrik.common.dto.AuthDTO;
+import io.github.nnkwrik.userservice.util.Response;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/12 17:44
+ */
+@FeignClient(name = "auth-service")
+public interface AuthClient {
+
+    @GetMapping("/test")
+    String test();
+
+    @PostMapping("/login")
+    Response login(@RequestBody AuthDTO authDTO);
+}

+ 0 - 122
user-service/src/main/java/io/github/nnkwrik/userservice/config/WxMaConfiguration.java

@@ -1,122 +0,0 @@
-package io.github.nnkwrik.userservice.config;
-
-import java.io.File;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import cn.binarywang.wx.miniapp.api.WxMaService;
-import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
-import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
-import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
-import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
-import cn.binarywang.wx.miniapp.config.WxMaInMemoryConfig;
-import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
-import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
-import me.chanjar.weixin.common.error.WxErrorException;
-
-/**
- * @author <a href="https://github.com/binarywang">Binary Wang</a>
- */
-@Configuration
-@EnableConfigurationProperties(WxMaProperties.class)
-public class WxMaConfiguration {
-//    private final WxMaMessageHandler templateMsgHandler = (wxMessage, context, service, sessionManager) ->
-//            service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder()
-//                    .templateId("此处更换为自己的模板id")
-//                    .formId("自己替换可用的formid")
-//                    .data(Lists.newArrayList(
-//                            new WxMaTemplateData("keyword1", "339208499", "#173177")))
-//                    .toUser(wxMessage.getFromUser())
-//                    .build());
-//
-//    private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
-//        System.out.println("收到消息:" + wxMessage.toString());
-//        service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
-//                .toUser(wxMessage.getFromUser()).build());
-//    };
-//
-//    private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) ->
-//            service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
-//                    .toUser(wxMessage.getFromUser()).build());
-//
-//    private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
-//        try {
-//            WxMediaUploadResult uploadResult = service.getMediaService()
-//                    .uploadMedia("image", "png",
-//                            ClassLoader.getSystemResourceAsStream("tmp.png"));
-//            service.getMsgService().sendKefuMsg(
-//                    WxMaKefuMessage
-//                            .newImageBuilder()
-//                            .mediaId(uploadResult.getMediaId())
-//                            .toUser(wxMessage.getFromUser())
-//                            .build());
-//        } catch (WxErrorException e) {
-//            e.printStackTrace();
-//        }
-//    };
-//
-//    private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
-//        try {
-//            final File file = service.getQrcodeService().createQrcode("123", 430);
-//            WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
-//            service.getMsgService().sendKefuMsg(
-//                    WxMaKefuMessage
-//                            .newImageBuilder()
-//                            .mediaId(uploadResult.getMediaId())
-//                            .toUser(wxMessage.getFromUser())
-//                            .build());
-//        } catch (WxErrorException e) {
-//            e.printStackTrace();
-//        }
-//    };
-//    private static Map<String, WxMaMessageRouter> routers = Maps.newHashMap();
-//    public static Map<String, WxMaMessageRouter> getRouters() {
-//        return routers;
-//    }
-
-
-    private WxMaProperties properties;
-    private static WxMaService maServices;
-
-
-    @Autowired
-    public WxMaConfiguration(WxMaProperties properties) {
-        this.properties = properties;
-    }
-
-
-    public static WxMaService getMaServices() {
-        return maServices;
-    }
-
-    @Bean
-    public Object services() {
-        WxMaInMemoryConfig config = new WxMaInMemoryConfig();
-        BeanUtils.copyProperties(properties,config);
-        maServices = new WxMaServiceImpl();
-        maServices.setWxMaConfig(config);
-
-        return Boolean.TRUE;
-    }
-
-//    private WxMaMessageRouter newRouter(WxMaService service) {
-//        final WxMaMessageRouter router = new WxMaMessageRouter(service);
-//        router
-//                .rule().handler(logHandler).next()
-//                .rule().async(false).content("模板").handler(templateMsgHandler).end()
-//                .rule().async(false).content("文本").handler(textHandler).end()
-//                .rule().async(false).content("图片").handler(picHandler).end()
-//                .rule().async(false).content("二维码").handler(qrcodeHandler).end();
-//        return router;
-//    }
-
-}

+ 53 - 24
user-service/src/main/java/io/github/nnkwrik/userservice/controller/UserController.java

@@ -1,47 +1,76 @@
 package io.github.nnkwrik.userservice.controller;
 
-import cn.binarywang.wx.miniapp.api.WxMaService;
-import cn.binarywang.wx.miniapp.api.WxMaUserService;
-import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
-import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
-import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
-import io.github.nnkwrik.userservice.config.WxMaConfiguration;
-import io.github.nnkwrik.userservice.entity.User;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.github.nnkwrik.common.dto.AuthDTO;
+import io.github.nnkwrik.userservice.client.AuthClient;
+import io.github.nnkwrik.userservice.model.User;
 import io.github.nnkwrik.userservice.service.UserService;
-import me.chanjar.weixin.common.error.WxErrorException;
-import org.apache.commons.lang.StringUtils;
+import io.github.nnkwrik.userservice.util.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 
+import java.io.IOException;
+
 /**
  * @author nnkwrik
  * @date 18/11/10 21:51
  */
 @RestController
-@RequestMapping("/wx/user")
 public class UserController {
 
-//    @Autowired
-//    private UserService userService;
+    private final Logger log = LoggerFactory.getLogger(this.getClass());
 
+    @Autowired
+    private UserService userService;
 
-    @PostMapping("/login/{code}")
-    public String login(@PathVariable String code, @RequestBody User user) {
+    @Autowired
+    private AuthClient authClient;
 
-        WxMaUserService wxUserService = WxMaConfiguration.getMaServices().getUserService();
-        try {
-            WxMaJscode2SessionResult sessionInfo = wxUserService.getSessionInfo(code);
+    @GetMapping("/test")
+    public String test(){
+        return authClient.test();
+    }
+
+
+    @PostMapping("/register")
+    public Response register(@RequestBody AuthDTO authDTO) {
 
-            String openid = sessionInfo.getOpenid();
-            user.setOpenId(openid);
+        Response response = authClient.login(authDTO);
+        if (!response.isSuccess()) {
+            log.info("认证失败,原因 :{}", response.getMsg());
+            return response;
+        }
 
-            System.out.println(user);
-            return "ok";
-        } catch (WxErrorException e) {
+        //rawData转User
+        ObjectMapper mapper = new ObjectMapper();
+        User user = null;
+        try {
+            user = mapper.readValue(authDTO.getRawData(), User.class);
+        } catch (IOException e) {
+            log.info("rawData转User失败 : rawData = {}", authDTO.getRawData());
             e.printStackTrace();
-            return e.toString();
+            return Response.fail("rawData转User失败 ");
         }
+        userService.register(user);
+
+        log.info("新用户:用户名 = [{}],城市 = [{}]", user.getNickName(), user.getCity());
+        return response;
     }
 
+//    //TODO 如果这个步骤比较频繁的话,需要另外做成一个服务
+//    @PostMapping("/checkSession")
+//    public Response checkSession(@RequestBody UserDTO userDTO) {
+//        UserDTO cache = redisClient.get(userDTO.getSessionKey());
+//        if (cache.equals(userDTO)) return Response.ok();
+//        return Response.fail("无效的Session");
+//    }
+//
+//    @PostMapping("/updateUserInfo") //UserInfo 发生变化时sessionKey肯定会变
+//    public Response updateUserInfo(@RequestBody User user) {
+//
+//    }
+
+
 }

+ 18 - 0
user-service/src/main/java/io/github/nnkwrik/userservice/dao/UserMapper.java

@@ -0,0 +1,18 @@
+package io.github.nnkwrik.userservice.dao;
+
+import io.github.nnkwrik.userservice.model.User;
+import org.apache.ibatis.annotations.*;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/11 16:57
+ */
+@Mapper
+public interface UserMapper {
+
+    @Insert("insert into user (openId,nickName,avatarUrl,gender,language,city,province,country) " +
+            "values (#{openId},#{nickName},#{avatarUrl},#{gender}," +
+            "#{language},#{city},#{province},#{country})")
+//    @SelectKey(resultType = Integer.class, before = false, keyProperty = "id", statement = "SELECT LAST_INSERT_ID()")
+    void register(User user);
+}

+ 5 - 2
user-service/src/main/java/io/github/nnkwrik/userservice/entity/User.java → user-service/src/main/java/io/github/nnkwrik/userservice/model/User.java

@@ -1,6 +1,7 @@
-package io.github.nnkwrik.userservice.entity;
+package io.github.nnkwrik.userservice.model;
 
 import lombok.Data;
+import org.apache.ibatis.annotations.Param;
 
 import javax.validation.constraints.NotNull;
 
@@ -10,7 +11,7 @@ import javax.validation.constraints.NotNull;
  */
 @Data
 public class User {
-    private String id;
+    private Integer id;
     private String openId;
     @NotNull
     private String nickName;
@@ -22,4 +23,6 @@ public class User {
     private String city;
     private String province;
     private String country;
+    //address
+    //phone
 }

+ 3 - 2
user-service/src/main/java/io/github/nnkwrik/userservice/service/UserService.java

@@ -1,11 +1,12 @@
 package io.github.nnkwrik.userservice.service;
 
-import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
+import io.github.nnkwrik.userservice.model.User;
 
 /**
  * @author nnkwrik
  * @date 18/11/10 22:15
  */
 public interface UserService {
-    void register(WxMaUserInfo userInfo);
+
+    void register(User user);
 }

+ 24 - 0
user-service/src/main/java/io/github/nnkwrik/userservice/service/impl/UserServiceImpl.java

@@ -0,0 +1,24 @@
+package io.github.nnkwrik.userservice.service.impl;
+
+import io.github.nnkwrik.userservice.dao.UserMapper;
+import io.github.nnkwrik.userservice.model.User;
+import io.github.nnkwrik.userservice.service.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/11 16:55
+ */
+@Service
+public class UserServiceImpl implements UserService {
+
+    @Autowired
+    private UserMapper userMapper;
+
+
+    @Override
+    public void register(User user) {
+        userMapper.register(user);
+    }
+}

+ 140 - 0
user-service/src/main/java/io/github/nnkwrik/userservice/util/Response.java

@@ -0,0 +1,140 @@
+package io.github.nnkwrik.userservice.util;
+
+/**
+ * @author nnkwrik
+ * @date 18/11/11 16:42
+ */
+public class Response<T> {
+    /**
+     * 服务器响应数据
+     */
+    private T payload;
+
+    /**
+     * 请求是否成功
+     */
+    private boolean success;
+
+    /**
+     * 错误信息
+     */
+    private String msg;
+
+    /**
+     * 状态码
+     */
+    private int code = -1;
+
+    /**
+     * 服务器响应时间
+     */
+    private long timestamp;
+
+    public Response() {
+        this.timestamp = System.currentTimeMillis() / 1000;
+    }
+
+    public Response(boolean success) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+    }
+
+    public Response(boolean success, T payload) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+        this.payload = payload;
+    }
+
+    public Response(boolean success, T payload, int code) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+        this.payload = payload;
+        this.code = code;
+    }
+
+    public Response(boolean success, String msg) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+        this.msg = msg;
+    }
+
+    public Response(boolean success, String msg, int code) {
+        this.timestamp = System.currentTimeMillis() / 1000;
+        this.success = success;
+        this.msg = msg;
+        this.code = code;
+    }
+
+    public T getPayload() {
+        return payload;
+    }
+
+    public void setPayload(T payload) {
+        this.payload = payload;
+    }
+
+    public boolean isSuccess() {
+        return success;
+    }
+
+    public void setSuccess(boolean success) {
+        this.success = success;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public static Response ok() {
+        return new Response(true);
+    }
+
+    public static <T> Response ok(T payload) {
+        return new Response(true, payload);
+    }
+
+    public static <T> Response ok(int code) {
+        return new Response(true, null, code);
+    }
+
+    public static <T> Response ok(T payload, int code) {
+        return new Response(true, payload, code);
+    }
+
+    public static Response fail() {
+        return new Response(false);
+    }
+
+    public static Response fail(String msg) {
+        return new Response(false, msg);
+    }
+
+    public static Response fail(int code) {
+        return new Response(false, null, code);
+    }
+
+    public static Response fail(int code, String msg) {
+        return new Response(false, msg, code);
+    }
+
+}

+ 8 - 12
user-service/src/main/resources/application.yml

@@ -4,19 +4,15 @@ eureka:
       defaultZone: http://localhost:8801/eureka/
 #  instance:
 #    hostname: clientName
+
+
 spring:
   application:
-    name: User-service
-  profiles:
-    include: secret
-#出于安全原因application-secret.yml被纳入.gitignore中,
-#application-secret.yml包含以下信息。
-#wx:
-#  miniapp:
-#    appid: #微信小程序的appid
-#    secret: #微信小程序的Secret
-#    token: #微信小程序消息服务器配置的token
-#    aesKey: #微信小程序消息服务器配置的EncodingAESKey
-#    msgDataFormat: JSON
+    name: user-service
+  datasource:
+    url: jdbc:mysql://localhost:3306/user_service
+    username: root
+    password: 1234
+    driver-class-name: com.mysql.cj.jdbc.Driver
 server:
   port: 8802