Jelajahi Sumber

1.修复用户生日字段 引起的夏令时问题
2.修复苹果登录不上问题

slambb 1 tahun lalu
induk
melakukan
485a38f28f

+ 1 - 1
src/main/java/com/YuyeTech/HeartRate/game/controller/LoginController.java

@@ -350,7 +350,7 @@ public class LoginController {
             saveUserInfo.setUserId(request.getParameterValues("userId")[0]);
             saveUserInfo.setUsername(userInfo.getNickName());
             saveUserInfo.setGender(userInfo.getGender());
-            saveUserInfo.setBirthday(new Date());
+            saveUserInfo.setBirthday(new java.sql.Date(DateUtil.date().getTime()));
             saveUserInfo.setSignature("");
             saveUserInfo.setAvatarUrl(userInfo.getAvatarUrl());
             saveUserInfo.setHeight(0.0);

+ 4 - 4
src/main/java/com/YuyeTech/HeartRate/game/userinfo/controller/UserInfoController.java

@@ -198,7 +198,7 @@ public class UserInfoController {
                 userInfo.setUserId(form.getUserId());
                 userInfo.setUsername("");
                 userInfo.setGender("其他");
-                userInfo.setBirthday(DateUtil.date());
+                userInfo.setBirthday(new java.sql.Date(DateUtil.date().getTime()));
                 userInfo.setSignature("");
                 userInfo.setAvatarUrl(uploadUrl);
                 userInfo.setHeight(0.0);
@@ -275,7 +275,7 @@ public class UserInfoController {
             userInfo.setUsername(username);
             userInfo.setUserId(userId);
             userInfo.setGender(gender);
-            userInfo.setBirthday(DateUtil.date());
+            userInfo.setBirthday(new java.sql.Date(DateUtil.date().getTime()));
             userInfo.setAvatarUrl(uploadUrl);
             userInfo.setHeight(0.0);
             userInfo.setWeight(0.0);
@@ -331,7 +331,7 @@ public class UserInfoController {
                 userInfo.setUserId(userId);
                 userInfo.setUsername(username);
                 userInfo.setGender(gender);
-                userInfo.setBirthday(DateUtil.date());
+                userInfo.setBirthday(new java.sql.Date(DateUtil.date().getTime()));
                 userInfo.setSignature("");
                 userInfo.setHeight(0.0);
                 userInfo.setWeight(0.0);
@@ -390,7 +390,7 @@ public class UserInfoController {
                 userInfo.setUserId(form.getUserId());
                 userInfo.setUsername(form.getUsername());
                 userInfo.setGender(form.getGender());
-                userInfo.setBirthday(DateUtil.date());
+                userInfo.setBirthday(new java.sql.Date(DateUtil.date().getTime()));
                 userInfo.setSignature(form.getSignature());
                 userInfo.setHeight(0.0);
                 userInfo.setWeight(0.0);

+ 1 - 1
src/main/java/com/YuyeTech/HeartRate/game/userinfo/projo/UserInfo.java

@@ -26,7 +26,7 @@ public class UserInfo {
      */
     private String cityCode;
 
-    private Date birthday;
+    private java.sql.Date birthday;
 
     private String signature;
 

+ 60 - 63
src/main/java/com/YuyeTech/HeartRate/utils/AppleUtil.java

@@ -17,6 +17,7 @@ import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 
 import java.io.*;
+import java.nio.charset.StandardCharsets;
 import java.security.Key;
 import java.security.KeyFactory;
 import java.security.PublicKey;
@@ -67,95 +68,91 @@ public class AppleUtil {
     public void set_APPLE_BUNDLE_IDENTIFIER(String BUNDLE_IDENTIFIER) {
         AppleUtil.APPLE_BUNDLE_IDENTIFIER = BUNDLE_IDENTIFIER;
     }
+
     /**
-     * 获取苹果的公钥
-     * @return
-     * @throws Exception
+     * 解码identityToken
+     * 对前端传来的JWT字符串identityToken的第二部分进行解码
+     * 主要获取其中的aud和sub,aud大概对应ios前端的包名,sub大概对应当前用户的授权的openID
+     * @param identityToken
+     * @return  {"aud":"com.xkj.****","sub":"000***.8da764d3f9e34d2183e8da08a1057***.0***","c_hash":"UsKAuEoI-****","email_verified":"true","auth_time":1574673481,"iss":"https://appleid.apple.com","exp":1574674081,"iat":1574673481,"email":"****@qq.com"}
      */
-    private static JSONArray getAuthKeys() throws Exception {
-//        String url = "https://appleid.apple.com/auth/keys";
-        RestTemplate restTemplate = new RestTemplate();
-        JSONObject json = restTemplate.getForObject(APPLE_KEYS_URL,JSONObject.class);
-        JSONArray arr = json.getJSONArray("keys");
-        return arr;
+    public static JSONObject parserIdentityToken(String identityToken) {
+        String[] arr = identityToken.split("\\.");
+
+        String firstDate = new String(Base64.decodeBase64(arr[0]), StandardCharsets.UTF_8);
+        String decode = new String(Base64.decodeBase64(arr[1]), StandardCharsets.UTF_8);
+        JSONObject claimObj = JSON.parseObject(decode);
+        // 将第一部分获取到的kid放入消息体中,方便后续匹配对应的公钥使用
+        claimObj.put("kid", JSONObject.parseObject(firstDate).get("kid"));
+        return claimObj;
     }
 
-    public static Boolean verify(String jwt) throws  Exception{
-        JSONArray arr = getAuthKeys();
-        if(arr == null){
-            return false;
-        }
-        //先取苹果第一个key进行校验
-        JSONObject authKey = arr.getJSONObject(0);
-        if(verifyExc(jwt, authKey)){
-            return true;
-        }else{
-            //再取第二个key校验
-            authKey = arr.getJSONObject(1);
-            return verifyExc(jwt, authKey);
-        }
+    /**
+     * 根据kid获取对应的苹果公钥
+     * @param kid
+     * @return
+     */
+    public static PublicKey getPublicKey(String kid) {
+        try {
+            RestTemplate restTemplate = new RestTemplate();
+            JSONObject data = restTemplate.getForObject(APPLE_KEYS_URL, JSONObject.class);
+            assert data != null;
+            JSONArray jsonArray = data.getJSONArray("keys");
+            for (Object obj : jsonArray) {
+                Map json = ((Map) obj);
+                // 获取kid对应的公钥
+                if (json.get("kid").equals(kid)) {
+                    Jwk jwa = Jwk.fromValues(json);
+                    return jwa.getPublicKey();
+                }
+            }
+        } catch (Exception e) {
 
+        }
+        return null;
     }
 
     /**
      * 对前端传来的identityToken进行验证
-     * @param jwt 对应前端传来的 identityToken
-     * @param authKey 苹果的公钥 authKey
+     *
+     * @param identityToken
+     * @param jsonObject
      * @return
      * @throws Exception
      */
-    public static Boolean verifyExc(String jwt, JSONObject authKey) throws Exception {
-
-        Jwk jwa = Jwk.fromValues(authKey);
-        PublicKey publicKey = jwa.getPublicKey();
+    public static Boolean verifyExc(String identityToken, JSONObject jsonObject) throws Exception {
+        String kid = (String) jsonObject.get("kid");
+        PublicKey publicKey = getPublicKey(kid);
 
-        String aud = "";
-        String sub = "";
-        if (jwt.split("\\.").length > 1) {
-            String claim = new String(Base64.decodeBase64(jwt.split("\\.")[1]));
-            aud = JSONObject.parseObject(claim).get("aud").toString();
-            sub = JSONObject.parseObject(claim).get("sub").toString();
-        }
         JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
         jwtParser.requireIssuer("https://appleid.apple.com");
-        jwtParser.requireAudience(aud);
-        jwtParser.requireSubject(sub);
-
+        jwtParser.requireAudience((String) jsonObject.get("aud"));
+        jwtParser.requireSubject((String) jsonObject.get("sub"));
         try {
-            Jws<Claims> claim = jwtParser.parseClaimsJws(jwt);
+            Jws<Claims> claim = jwtParser.parseClaimsJws(identityToken);
             if (claim != null && claim.getBody().containsKey("auth_time")) {
-                System.out.println(claim);
                 return true;
             }
             return false;
         } catch (ExpiredJwtException e) {
-//            log.error("apple identityToken expired", e);
             return false;
         } catch (Exception e) {
-//            log.error("apple identityToken illegal", e);
             return false;
         }
-
     }
 
+    public static Boolean verify(String identityToken) throws  Exception{
 
-
-    /**
-     * 对前端传来的JWT字符串identityToken的第二部分进行解码
-     * 主要获取其中的aud和sub,aud大概对应ios前端的包名,sub大概对应当前用户的授权的openID
-     * @param identityToken
-     * @return  {"aud":"com.xkj.****","sub":"000***.8da764d3f9e34d2183e8da08a1057***.0***","c_hash":"UsKAuEoI-****","email_verified":"true","auth_time":1574673481,"iss":"https://appleid.apple.com","exp":1574674081,"iat":1574673481,"email":"****@qq.com"}
-     */
-    public static JSONObject parserIdentityToken(String identityToken){
-        String[] arr = identityToken.split("\\.");
-        Base64 base64 = new Base64();
-        String decode = new String (base64.decodeBase64(arr[1]));
-        String substring = decode.substring(0, decode.indexOf("}")+1);
-        JSONObject jsonObject = JSON.parseObject(substring);
-        return  jsonObject;
+        JSONObject playloadObj = parserIdentityToken(identityToken);
+        Boolean success;
+        try {
+            success = verifyExc(identityToken, playloadObj);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return success;
     }
 
-
     /**
      * 获取p8文件中的内容
      *
@@ -163,7 +160,8 @@ public class AppleUtil {
      */
     private static Key getPrivateKey() {
         try {
-            ClassPathResource resource = new ClassPathResource("config/AuthKey_8G9994KW4L.p8");
+            //ClassPathResource resource = new ClassPathResource("config/AuthKey_8G9994KW4L.p8");
+            ClassPathResource resource = new ClassPathResource("config/AuthKey_"+AppleUtil.APPLE_KID+".p8");
             InputStream inputStream = resource.getInputStream();
             Reader reader = new InputStreamReader(inputStream, "utf-8");
             BufferedReader br = new BufferedReader(reader);
@@ -181,7 +179,7 @@ public class AppleUtil {
             EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(org.apache.commons.codec.binary.Base64.decodeBase64(sb.toString().replaceAll("\\n", "")));
             return factory.generatePrivate(keySpec);
         } catch (FileNotFoundException e) {
-            log.error("not find p8 file !=>{}", e.getMessage());
+            System.out.println("not find p8 file !=>"+e.getMessage());
             return null;
         } catch (Exception e) {
             e.printStackTrace();
@@ -269,11 +267,10 @@ public class AppleUtil {
                 }
             }
         } catch (Exception e) {
-            log.error("revoke token error");
+            System.out.println("revoke token error:" + e.getMessage());
             return false;
         }
         return true;
     }
 
-
 }