ximinghao 3 сар өмнө
parent
commit
2d90600f4c

+ 77 - 29
src/main/java/com/skyversation/xjcy/oauth/AuthService.java

@@ -8,6 +8,7 @@ import com.skyversation.xjcy.dms.DMSService;
 import com.skyversation.xjcy.service.WeChatService;
 import com.skyversation.xjcy.util.HttpUtil;
 import com.skyversation.xjcy.util.MessageManage;
+import com.skyversation.xjcy.util.ObfuscationUtils;
 import lombok.Getter;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
@@ -31,42 +32,76 @@ public class AuthService {
 
     // ============================ 常量定义 ============================
 
-    /** OAuth客户端ID */
+    /**
+     * OAuth客户端ID
+     */
     private static final String CLIENT_ID = "2";
-    /** 成功状态码 */
+    /**
+     * 成功状态码
+     */
     private static final Integer SUCCESS_CODE_INT = 200;
-    /** 密码错误消息 */
+    /**
+     * 密码错误消息
+     */
     private static final String MESSAGE_PASSWORD_ERROR = "密码错误";
-    /** 用户不存在消息 */
+    /**
+     * 用户不存在消息
+     */
     private static final String MESSAGE_USER_NOT_EXIST = "用户不存在";
 
-    /** 用户登录接口路径 */
+    /**
+     * 用户登录接口路径
+     */
     private static final String API_USER_LOGIN = "/api/user/login";
-    /** 用户注册接口路径 */
+    /**
+     * 用户注册接口路径
+     */
     private static final String USER_REGISTER = "/user/register";
-    /** Token验证接口路径 */
+    /**
+     * Token验证接口路径
+     */
     private static final String USER_VALIDATE_TOKEN = "/user/validateToken";
 
-    /** 微信账号用户名前缀 */
+    /**
+     * 微信账号用户名前缀
+     */
     private static final String WX_NAME_PREFIX = "#wx";
-    /** 微信账号密码前缀 */
+    /**
+     * 微信账号密码前缀
+     */
     private static final String WX_PASSWORD_PREFIX = "Wx@";
-    /** 微信账号加密盐值 */
+    /**
+     * 微信账号加密盐值
+     */
     private static final String WX_SALT = "chatWe";
-    /** 手机账号用户名前缀 */
+    /**
+     * 手机账号用户名前缀
+     */
     private static final String PHONE_NAME_PREFIX = "#phone";
-    /** 手机账号密码前缀 */
+    /**
+     * 手机账号密码前缀
+     */
     private static final String PHONE_PASSWORD_PREFIX = "Phone@";
-    /** 手机账号加密盐值 */
+    /**
+     * 手机账号加密盐值
+     */
     private static final String PHONE_SALT = "enohp";
 
-    /** 响应字段:状态码 */
+    /**
+     * 响应字段:状态码
+     */
     private static final String RESPONSE_FIELD_CODE = "code";
-    /** 响应字段:消息 */
+    /**
+     * 响应字段:消息
+     */
     private static final String RESPONSE_FIELD_MESSAGE = "message";
-    /** 响应字段:内容数据 */
+    /**
+     * 响应字段:内容数据
+     */
     private static final String RESPONSE_FIELD_CONTENT = "content";
-    /** 响应字段:用户ID */
+    /**
+     * 响应字段:用户ID
+     */
     private static final String RESPONSE_FIELD_ID = "id";
     /**
      * 响应字段:用户名
@@ -96,26 +131,38 @@ public class AuthService {
 
     // ============================ 实例变量 ============================
 
-    /** 微信认证服务 */
+    /**
+     * 微信认证服务
+     */
     private final WeChatService weChatService;
 
     private final PhoneService phoneService;
-    /** 服务账户用户名 */
+    /**
+     * 服务账户用户名
+     */
     @Value("${app.oauth.login-name}")
     private String loginName;
 
-    /** 服务账户密码 */
+    /**
+     * 服务账户密码
+     */
     @Value("${app.oauth.password}")
     private String password;
 
-    /** 服务账户信息 */
+    /**
+     * 服务账户信息
+     */
     private Account account;
 
-    /** OAuth服务路径 */
+    /**
+     * OAuth服务路径
+     */
     @Value("${app.oauth.path}")
     private String oauthPath = null;
 
-    /** Token缓存,使用volatile确保多线程可见性 */
+    /**
+     * Token缓存,使用volatile确保多线程可见性
+     */
     private volatile String cacheToken;
 
     // ============================ 构造方法 ============================
@@ -211,8 +258,8 @@ public class AuthService {
      * @param code phoneService提供的验证码
      * @return 完整的response.body
      */
-    public String logOrRegPhoneAccount(String phone,String code) {
-        PhoneService.Result result = phoneService.login(phone,code);
+    public String logOrRegPhoneAccount(String phone, String code) {
+        PhoneService.Result result = phoneService.login(phone, code);
         if (result.isSuccess()) {
             return logOrReg(generateAccount(result.getPhone(), PHONE_NAME_PREFIX, PHONE_PASSWORD_PREFIX, PHONE_SALT));
         } else {
@@ -274,10 +321,10 @@ public class AuthService {
         if (usercode == null || usercode.isEmpty()) {
             return false;
         }
-        if (!isUserDmsDataExist(usercode)){
+        if (!isUserDmsDataExist(usercode)) {
             User user = new User();
             user.setCUsercode(usercode);
-            boolean insertSuccess = dMSService.insertToDms(user.toJSON(),getTokenOfServiceAccount(), DMSColumn.USER);
+            boolean insertSuccess = dMSService.insertToDms(user.toJSON(), getTokenOfServiceAccount(), DMSColumn.USER);
             if (!insertSuccess) {
                 return false;
             }
@@ -314,7 +361,7 @@ public class AuthService {
     /**
      * 检查用户账户DMS数据存在性
      */
-    private boolean isUserDmsDataExist(String userCode){
+    private boolean isUserDmsDataExist(String userCode) {
         List<JSONObject> js = dMSService.getUserJSONByCode(userCode);
         return !js.isEmpty();
     }
@@ -356,7 +403,8 @@ public class AuthService {
      * 生成账户信息
      */
     private static Account generateAccount(String uniCode, String namePrefix, String passwordPrefix, String salt) {
-        String oauthAccount = namePrefix + uniCode;
+        String uniCodeBase64 = ObfuscationUtils.advancedObfuscate(uniCode + salt);
+        String oauthAccount = namePrefix + uniCodeBase64 + uniCode.substring(uniCode.length() - 4);
         String oauthPassword = passwordPrefix + encrypt(uniCode + salt);
         return new Account(oauthAccount, oauthPassword);
     }

+ 165 - 0
src/main/java/com/skyversation/xjcy/util/ObfuscationUtils.java

@@ -0,0 +1,165 @@
+package com.skyversation.xjcy.util;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * 字符串脱敏转码工具类
+ * 提供基本的欺骗性转码功能,确保无碰撞
+ */
+public class ObfuscationUtils {
+    
+    // 字符映射表 - 使用简单的替换密码原理
+    private static final Map<Character, Character> CHAR_MAPPING = new HashMap<>();
+    private static final Map<Character, Character> REVERSE_MAPPING = new HashMap<>();
+    
+    static {
+        // 构建字符映射表 (可扩展更多字符)
+        String original = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+        String mapped =   "QWE1RTY2UIO3PAS4DFG5HJK6LZX7CVB8NM9qwe0rtyuio@pas#dfg$hjk%lzx*cvb+nm";
+        
+        for (int i = 0; i < original.length(); i++) {
+            CHAR_MAPPING.put(original.charAt(i), mapped.charAt(i));
+            REVERSE_MAPPING.put(mapped.charAt(i), original.charAt(i));
+        }
+        
+        // 添加一些特殊字符映射
+        CHAR_MAPPING.put('@', '!');
+        CHAR_MAPPING.put('#', '&');
+        CHAR_MAPPING.put('$', '*');
+        CHAR_MAPPING.put('%', '(');
+        CHAR_MAPPING.put('*', ')');
+        CHAR_MAPPING.put('+', '-');
+        CHAR_MAPPING.put('!', '@');
+        CHAR_MAPPING.put('&', '#');
+        CHAR_MAPPING.put('(', '$');
+        CHAR_MAPPING.put(')', '%');
+        CHAR_MAPPING.put('-', '+');
+        
+        // 更新反向映射
+        for (Map.Entry<Character, Character> entry : CHAR_MAPPING.entrySet()) {
+            REVERSE_MAPPING.put(entry.getValue(), entry.getKey());
+        }
+    }
+    
+    /**
+     * 基础字符替换脱敏
+     */
+    public static String basicObfuscate(String input) {
+        if (input == null) return null;
+        
+        StringBuilder result = new StringBuilder();
+        for (char c : input.toCharArray()) {
+            if (CHAR_MAPPING.containsKey(c)) {
+                result.append(CHAR_MAPPING.get(c));
+            } else {
+                result.append(c); // 保持未知字符不变
+            }
+        }
+        return result.toString();
+    }
+    
+    /**
+     * 基础字符替换还原
+     */
+    public static String basicDeobfuscate(String obfuscated) {
+        if (obfuscated == null) return null;
+        
+        StringBuilder result = new StringBuilder();
+        for (char c : obfuscated.toCharArray()) {
+            if (REVERSE_MAPPING.containsKey(c)) {
+                result.append(REVERSE_MAPPING.get(c));
+            } else {
+                result.append(c); // 保持未知字符不变
+            }
+        }
+        return result.toString();
+    }
+    
+    /**
+     * Base64 + 字符替换双重脱敏
+     */
+    public static String advancedObfuscate(String input) {
+        if (input == null) return null;
+        
+        // 第一步:Base64编码
+        String base64Encoded = Base64.getEncoder().encodeToString(
+            input.getBytes(StandardCharsets.UTF_8));
+        
+        // 第二步:字符替换
+        return basicObfuscate(base64Encoded);
+    }
+    
+    /**
+     * 还原Base64 + 字符替换双重脱敏
+     */
+    public static String advancedDeobfuscate(String obfuscated) {
+        if (obfuscated == null) return null;
+        
+        // 第一步:字符替换还原
+        String deobfuscated = basicDeobfuscate(obfuscated);
+        
+        // 第二步:Base64解码
+        byte[] decodedBytes = Base64.getDecoder().decode(deobfuscated);
+        return new String(decodedBytes, StandardCharsets.UTF_8);
+    }
+    
+    /**
+     * 生成随机偏移的脱敏(增加随机性)
+     */
+    public static String randomOffsetObfuscate(String input) {
+        if (input == null) return null;
+        
+        StringBuilder result = new StringBuilder();
+        ThreadLocalRandom random = ThreadLocalRandom.current();
+        
+        for (char c : input.toCharArray()) {
+            if (CHAR_MAPPING.containsKey(c)) {
+                char mapped = CHAR_MAPPING.get(c);
+                // 添加随机偏移(0-9)增加随机性
+                if (Character.isLetterOrDigit(mapped)) {
+                    int offset = random.nextInt(10);
+                    result.append(mapped).append(offset);
+                } else {
+                    result.append(mapped);
+                }
+            } else {
+                result.append(c);
+            }
+        }
+        return result.toString();
+    }
+    
+    /**
+     * 还原随机偏移脱敏
+     */
+    public static String randomOffsetDeobfuscate(String obfuscated) {
+        if (obfuscated == null) return null;
+        
+        StringBuilder result = new StringBuilder();
+        int i = 0;
+        while (i < obfuscated.length()) {
+            char c = obfuscated.charAt(i);
+            
+            if (REVERSE_MAPPING.containsKey(c)) {
+                // 检查下一个字符是否是数字(随机偏移)
+                if (i + 1 < obfuscated.length() && 
+                    Character.isDigit(obfuscated.charAt(i + 1))) {
+                    // 跳过数字字符
+                    i += 2;
+                } else {
+                    i++;
+                }
+                result.append(REVERSE_MAPPING.get(c));
+            } else {
+                result.append(c);
+                i++;
+            }
+        }
+        return result.toString();
+    }
+
+}