Browse Source

泛微OA待办集成

wanghaiwu 1 week ago
parent
commit
5db46f6c58

+ 153 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/FanWeiSSOAuthtication.java

@@ -0,0 +1,153 @@
+package nckd.jimin.jyyy.bd.common.oauth;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.dc.api.model.Account;
+import kd.bos.entity.AppInfo;
+import kd.bos.entity.AppMetadataCache;
+import kd.bos.entity.param.AppParam;
+import kd.bos.exception.ErrorCode;
+import kd.bos.exception.KDException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.login.thirdauth.app.AppAuthResult;
+import kd.bos.login.thirdauth.app.ThirdAppAuthtication;
+import kd.bos.login.thirdauth.app.UserType;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.sdk.util.KHttpClientUtils;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.parameter.SystemParamServiceHelper;
+import kd.bos.workflow.exception.WFErrorCode;
+import kd.bos.workflow.exception.WFMessageServiceException;
+import nckd.jimin.jyyy.bd.plugin.msg.ecology.HttpUtils;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 泛微OA:E10单点登录拦截,验证token用户
+ * @author wanghaiwu_kd
+ * @date 2025/04/16
+ */
+public class FanWeiSSOAuthtication extends ThirdAppAuthtication {
+    private static Log logger = LogFactory.getLog(FanWeiSSOAuthtication.class);
+    /**
+     * 判断该接口请求是否需要通过此插件认证
+     */
+    @Override
+    public boolean isNeedHandle(HttpServletRequest request, Account account) {
+        //加密的数据信息
+        String token = request.getParameter("eteams_token");
+        if(StringUtils.isNotBlank(token)){
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     *用户身份解析
+     */
+    @Override
+    public AppAuthResult appAuthtication(HttpServletRequest request, Account account) {
+        AppAuthResult result = new AppAuthResult();
+        result.setSucceed(false);
+        try{
+            //获取请求连接中的token
+            String token = request.getParameter("eteams_token");
+            if(StringUtils.isBlank(token)){
+                logger.info("FanWeiSSOAuthtication:eteams_token is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:eteams_token is null");
+                return result;
+            }
+
+            String selectField = "nckd_entryentity.nckd_key, nckd_entryentity.nckd_value";
+
+            QFilter qFilter = new QFilter("number", QCP.equals, "fanwei");
+            DynamicObject commonParam = BusinessDataServiceHelper.loadSingle("nckd_commonparams", selectField, qFilter.toArray());
+            if (ObjectUtils.isEmpty(commonParam)) {
+                logger.info("FanWeiSSOAuthtication:nckd_commonparams is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数");
+                return result;
+            }
+
+            DynamicObjectCollection entryentity = commonParam.getDynamicObjectCollection("nckd_entryentity");
+            Map<String, String> mapentity = entryentity.stream().collect(Collectors.toMap(k -> k.getString("nckd_key"), v -> v.getString("nckd_value")));
+
+            if(mapentity == null ){
+                logger.info("FanWeiSSOAuthtication:nckd_entryentity is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数");
+                return result;
+            }
+
+            String userUrl = mapentity.get("getuserinfo");
+            if(StringUtils.isEmpty(userUrl)){
+                logger.info("FanWeiSSOAuthtication:getuserinfo is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数");
+                return result;
+            }
+
+            String ssouser_dev = mapentity.get("ssouser_dev");
+            String user = "";
+
+//            String apiResult = "";
+//
+//            Map<String, String> header = new HashMap<>();
+//            header.put("Content-Type", "application/json; charset=UTF-8");
+//
+//            //获取token
+//            try {
+//                userUrl = userUrl + "?eteams_token=" + token;
+//                logger.info("获取泛微用户url:" + userUrl);
+//
+//                apiResult = KHttpClientUtils.postjson(userUrl, header, null);
+//            } catch (IOException e) {
+//                logger.info(e.getMessage());
+//
+//                logger.info("FanWeiSSOAuthtication:getuserinfo fail");
+//
+//                result.setErrorMessage("FanWeiSSOAuthtication:获取用户异常" + e.getMessage());
+//                return result;
+//            }
+//
+//            if(kd.bos.util.StringUtils.isEmpty(apiResult)){
+//                logger.info("FanWeiSSOAuthtication:getuserinfo fail");
+//
+//                result.setErrorMessage("FanWeiSSOAuthtication:获取用户异常");
+//                return result;
+//            }
+//
+//            JSONObject userInfo = JSONObject.parseObject(apiResult);
+//            if(userInfo.get("mobile") == null){
+//                logger.info("FanWeiSSOAuthtication:getuserinfo fail");
+//
+//                result.setErrorMessage("FanWeiSSOAuthtication:获取用户异常");
+//                return result;
+//            }
+
+            if(StringUtils.isNotEmpty(ssouser_dev)){
+                user = ssouser_dev;
+
+            }
+            result.setUserFlag(user);
+            result.setUserType(UserType.USER_NAME);
+            result.setSucceed(true);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return result;
+    }
+}

+ 108 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/RSAUtils.java

@@ -0,0 +1,108 @@
+package nckd.jimin.jyyy.bd.common.oauth;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+public class RSAUtils {
+
+    private static Provider provider;
+
+    static {
+        provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
+        Security.addProvider(provider);
+    }
+
+    /**
+     * 产生key pair,提供provider和random
+     * @return
+     * @throws NoSuchAlgorithmException
+     */
+    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
+        // 产生用于安全加密的随机数
+        SecureRandom random = new SecureRandom();
+
+        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
+        Integer length = 2048;//加密算法位数
+        generator.initialize(length, random);
+        return generator.generateKeyPair();
+    }
+
+    /**
+     * 返回一个keyBytes生成的PublicKey对象
+     * @param keyBytes
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PublicKey publicKey = keyFactory.generatePublic(keySpec);
+        return publicKey;
+    }
+
+    public static byte[] encryptByKey(Key keys, byte[] byteArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        // Cipher: 提供加密和解密功能的实例
+        // transformation: "algorithm/mode/padding"
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
+        // PrivateKey privateKey = keyPair.getPrivate();
+        // 初始化
+        cipher.init(Cipher.ENCRYPT_MODE, keys);
+        // doFinal(): 加密或者解密数据
+        byte[] plainText = cipher.doFinal(byteArray);
+        return plainText;
+    }
+
+    /**
+     * 返回一个keyBytes生成的privateKey对象
+     * @param keyBytes
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+        return privateKey;
+    }
+
+    /**
+     * 用相应的key解密对应加密的问题
+     *
+     * @param keys
+     * @param byteArray
+     * @return
+     */
+    public static byte[] decryptByKey(Key keys, byte[] byteArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        // Cipher: 提供加密和解密功能的实例
+        // transformation: "algorithm/mode/padding"
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
+
+        // 初始化
+        cipher.init(Cipher.DECRYPT_MODE, keys);
+        // doFinal(): 加密或者解密数据
+        byte[] plainText = cipher.doFinal(byteArray);
+        return plainText;
+    }
+
+    /**
+     * 产生public key
+     *
+     * @return public key字符串
+     */
+    public static String generateBase64Key(byte[] keys) {
+        // encodeBase64(): Encodes binary data using the base64
+        // algorithm but does not chunk the output.
+        // getEncoded():返回key的原始编码形式
+        return new String(Base64.encodeBase64(keys));
+    }
+}

+ 47 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/SHAUtils.java

@@ -0,0 +1,47 @@
+package nckd.jimin.jyyy.bd.common.oauth;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class SHAUtils {
+
+
+    public static String getSHA256Hex(String input) {
+        try {
+            // 创建一个 MessageDigest 实例,并指定算法为 SHA-256
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+
+            // 将输入字符串转换为字节数组
+            byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
+
+            // 将字节数组转换为十六进制字符串
+            StringBuilder hexString = new StringBuilder();
+            for (byte b : hash) {
+                String hex = Integer.toHexString(0xff & b);
+                if (hex.length() == 1) hexString.append('0');
+                hexString.append(hex);
+            }
+
+            return hexString.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 检查时间戳是否一致,默认允许5分钟误差
+     * @param timeStamp
+     * @return
+     */
+    public static boolean checkDateTime(String timeStamp){
+        long now = System.currentTimeMillis();
+        if(StringUtils.isEmpty(timeStamp) || (StringUtils.isNotEmpty(timeStamp) && StringUtils.isNumeric(timeStamp) && Math.abs(now - Long.parseLong(timeStamp)) / 1000 > 5 * 60)){
+            return false;
+        }
+        return true;
+    }
+
+}

+ 10 - 4
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/FanweiCommonUtil.java

@@ -62,6 +62,7 @@ public final class FanweiCommonUtil {
     private static String param_getcode = "";
     private static String param_gettoken = "";
     private static String param_sendflow = "";
+    private static String param_receiver_dev = "";
 
     /**
      * 获取公共参数中的泛微相关参数配置
@@ -92,6 +93,7 @@ public final class FanweiCommonUtil {
 
             param_gettoken = mapentity.get("gettoken");
             param_sendflow = mapentity.get("sendflow");
+            param_receiver_dev = mapentity.get("receiver_dev");
         }
     }
 
@@ -719,7 +721,9 @@ public final class FanweiCommonUtil {
         bodyData.put("receiver", personNo);
 
         //测试人员
-        bodyData.put("receiver", "18296674436");
+        if(StringUtils.isNotEmpty(param_receiver_dev)) {
+            bodyData.put("receiver", param_receiver_dev);
+        }
 
         //接收时间
         bodyData.put("receivedatetime", createTime);
@@ -886,8 +890,10 @@ public final class FanweiCommonUtil {
         //接收人
         bodyData.put("receiver", personNo);
 
-        //测试人员
-        bodyData.put("receiver", "18296674436");
+        if(StringUtils.isNotEmpty(param_receiver_dev)) {
+            //测试人员
+            bodyData.put("receiver", param_receiver_dev);
+        }
 
         //接收时间
         bodyData.put("receivedatetime", createTime);
@@ -908,7 +914,7 @@ public final class FanweiCommonUtil {
      * 获取泛微OA的accesstoken
      * @return
      */
-    private static String getFanWeiToken() {
+    public static String getFanWeiToken() {
         String token = "";
 
         String result = "";

+ 10 - 8
code/nckd-cosmic-debug/src/main/java/nckd/cosmic/debug/DebugApplication.java

@@ -22,19 +22,21 @@ public class DebugApplication {
     	
         CosmicLauncher cosmic = new CosmicLauncher(false);
 
-        cosmic.setClusterNumber("jmkx-uat");
-        cosmic.setTenantNumber("jmkx-uat");
+        cosmic.setClusterNumber("jmkd-dev");
+        cosmic.setTenantNumber("jmkd-dev");
 
-        cosmic.setConfigUrl("172.16.51.125:2181?user=zookeeper&password=d@f*g:SGVsbG8==855QCU/CYX432khLmGVPXD67TE4faNQfn2Ku1r1fVGpwa2RwYXNzd29yZA==");
-        cosmic.setMcServerUrl("http://172.16.51.125:8090/");
+        cosmic.setConfigUrl("172.16.51.127:2181?user=zookeeper&password=d@f*g:SGVsbG8==ks1LiwKd/S7nGdJNoDTBJDXUCSlnkc/6ELhd8lK10IEYa2RwYXNzd29yZA==");
+        cosmic.setMcServerUrl("http://172.16.51.127:8090/");
 
-        cosmic.setFsServerUrl("172.16.51.125", 8100);
-        cosmic.setImageServerUrl("172.16.51.125", 8100);
+        cosmic.setFsServerUrl("172.16.51.127", 8100);
+        cosmic.setImageServerUrl("172.16.51.127", 8100);
         //自定义本地苍穹调试服务的端口
         cosmic.setCosmicWebPort(8080);
 //        cosmic.setDubboConfig(false, true, true);
+
+        cosmic.setStartWithQing(true);
+
+
         cosmic.start();
-        
-        
     }
 }