Browse Source

提交竹云单点认证业务代码

Heyuan 8 months ago
parent
commit
cd1e849d54

+ 7 - 0
properties/Api/propertie.properties

@@ -0,0 +1,7 @@
+Appkey=1838882415880818690
+AppSecret=BFOmgnJrmdl6lEcQEIEt3fXtbfavRB82
+serverName=https://api-test.gemdale.com
+#获取用户总数接口地址
+getEmpCountPath=/openApi/organization-center/emp/getEmpCount
+#获取用户信息接口地址
+getEmpPath=/openApi/organization-center/emp/getEmp

+ 78 - 0
src/com/kingdee/eas/custom/task/AbstractSyncZYEmpFacadeControllerBean.java

@@ -0,0 +1,78 @@
+package com.kingdee.eas.custom.task;
+
+import javax.ejb.*;
+import java.rmi.RemoteException;
+import com.kingdee.bos.*;
+import com.kingdee.bos.util.BOSObjectType;
+import com.kingdee.bos.metadata.IMetaDataPK;
+import com.kingdee.bos.metadata.rule.RuleExecutor;
+import com.kingdee.bos.metadata.MetaDataPK;
+//import com.kingdee.bos.metadata.entity.EntityViewInfo;
+import com.kingdee.bos.framework.ejb.AbstractEntityControllerBean;
+import com.kingdee.bos.framework.ejb.AbstractBizControllerBean;
+//import com.kingdee.bos.dao.IObjectPK;
+import com.kingdee.bos.dao.IObjectValue;
+import com.kingdee.bos.dao.IObjectCollection;
+import com.kingdee.bos.service.ServiceContext;
+import com.kingdee.bos.service.IServiceContext;
+import com.kingdee.eas.framework.Result;
+import com.kingdee.eas.framework.LineResult;
+import com.kingdee.eas.framework.exception.EASMultiException;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+
+import java.lang.String;
+
+
+
+public abstract class AbstractSyncZYEmpFacadeControllerBean extends AbstractBizControllerBean implements SyncZYEmpFacadeController
+{
+    protected AbstractSyncZYEmpFacadeControllerBean()
+    {
+    }
+
+    protected BOSObjectType getBOSType()
+    {
+        return new BOSObjectType("76DBFEF7");
+    }
+
+    public void SyncAllEmp(Context ctx) throws BOSException
+    {
+        try {
+            ServiceContext svcCtx = createServiceContext(new MetaDataPK("4f7f7893-a76c-4353-8240-c61f51b8cd78"), new Object[]{ctx});
+            invokeServiceBefore(svcCtx);
+              if(!svcCtx.invokeBreak()) {
+            _SyncAllEmp(ctx);
+            }
+            invokeServiceAfter(svcCtx);
+        } catch (BOSException ex) {
+            throw ex;
+        } finally {
+            super.cleanUpServiceState();
+        }
+    }
+    protected void _SyncAllEmp(Context ctx) throws BOSException
+    {    	
+        return;
+    }
+
+    public void SyncEmpByUpdateTime(Context ctx, String updateBeginTime, String updateEndTime) throws BOSException
+    {
+        try {
+            ServiceContext svcCtx = createServiceContext(new MetaDataPK("92db3db3-6ebe-4876-9ba1-2088ac70a94a"), new Object[]{ctx, updateBeginTime, updateEndTime});
+            invokeServiceBefore(svcCtx);
+              if(!svcCtx.invokeBreak()) {
+            _SyncEmpByUpdateTime(ctx, updateBeginTime, updateEndTime);
+            }
+            invokeServiceAfter(svcCtx);
+        } catch (BOSException ex) {
+            throw ex;
+        } finally {
+            super.cleanUpServiceState();
+        }
+    }
+    protected void _SyncEmpByUpdateTime(Context ctx, String updateBeginTime, String updateEndTime) throws BOSException
+    {    	
+        return;
+    }
+
+}

+ 19 - 0
src/com/kingdee/eas/custom/task/ISyncZYEmpFacade.java

@@ -0,0 +1,19 @@
+package com.kingdee.eas.custom.task;
+
+import com.kingdee.bos.BOSException;
+//import com.kingdee.bos.metadata.*;
+import com.kingdee.bos.framework.*;
+import com.kingdee.bos.util.*;
+import com.kingdee.bos.Context;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.util.*;
+import java.lang.String;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.framework.*;
+
+public interface ISyncZYEmpFacade extends IBizCtrl
+{
+    public void SyncAllEmp() throws BOSException;
+    public void SyncEmpByUpdateTime(String updateBeginTime, String updateEndTime) throws BOSException;
+}

+ 62 - 0
src/com/kingdee/eas/custom/task/SyncZYEmpFacade.java

@@ -0,0 +1,62 @@
+package com.kingdee.eas.custom.task;
+
+import com.kingdee.bos.framework.ejb.EJBRemoteException;
+import com.kingdee.bos.util.BOSObjectType;
+import java.rmi.RemoteException;
+import com.kingdee.bos.framework.AbstractBizCtrl;
+import com.kingdee.bos.orm.template.ORMObject;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.util.*;
+import com.kingdee.eas.custom.task.*;
+import java.lang.String;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.framework.*;
+
+public class SyncZYEmpFacade extends AbstractBizCtrl implements ISyncZYEmpFacade
+{
+    public SyncZYEmpFacade()
+    {
+        super();
+        registerInterface(ISyncZYEmpFacade.class, this);
+    }
+    public SyncZYEmpFacade(Context ctx)
+    {
+        super(ctx);
+        registerInterface(ISyncZYEmpFacade.class, this);
+    }
+    public BOSObjectType getType()
+    {
+        return new BOSObjectType("76DBFEF7");
+    }
+    private SyncZYEmpFacadeController getController() throws BOSException
+    {
+        return (SyncZYEmpFacadeController)getBizController();
+    }
+    /**
+     *同步所有用户-User defined method
+     */
+    public void SyncAllEmp() throws BOSException
+    {
+        try {
+            getController().SyncAllEmp(getContext());
+        }
+        catch(RemoteException err) {
+            throw new EJBRemoteException(err);
+        }
+    }
+    /**
+     *根据更新时间同步用户-User defined method
+     *@param updateBeginTime 更新开始时间(yyyy-MM-dd HH:mm:ss)
+     *@param updateEndTime 更新结束时间(yyyy-MM-dd HH:mm:ss)
+     */
+    public void SyncEmpByUpdateTime(String updateBeginTime, String updateEndTime) throws BOSException
+    {
+        try {
+            getController().SyncEmpByUpdateTime(getContext(), updateBeginTime, updateEndTime);
+        }
+        catch(RemoteException err) {
+            throw new EJBRemoteException(err);
+        }
+    }
+}

+ 22 - 0
src/com/kingdee/eas/custom/task/SyncZYEmpFacadeController.java

@@ -0,0 +1,22 @@
+package com.kingdee.eas.custom.task;
+
+import com.kingdee.bos.BOSException;
+//import com.kingdee.bos.metadata.*;
+import com.kingdee.bos.framework.*;
+import com.kingdee.bos.util.*;
+import com.kingdee.bos.Context;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.util.*;
+import java.lang.String;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.framework.*;
+
+import java.rmi.RemoteException;
+import com.kingdee.bos.framework.ejb.BizController;
+
+public interface SyncZYEmpFacadeController extends BizController
+{
+    public void SyncAllEmp(Context ctx) throws BOSException, RemoteException;
+    public void SyncEmpByUpdateTime(Context ctx, String updateBeginTime, String updateEndTime) throws BOSException, RemoteException;
+}

+ 328 - 0
src/com/kingdee/eas/custom/task/SyncZYEmpFacadeControllerBean.java

@@ -0,0 +1,328 @@
+package com.kingdee.eas.custom.task;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.gemdale.gdgateway.util.MD5Utils;
+import com.kingdee.eas.base.permission.UserCollection;
+import com.kingdee.eas.base.permission.UserFactory;
+import com.kingdee.eas.base.permission.UserInfo;
+import com.kingdee.eas.basedata.person.PersonInfo;
+import com.kingdee.eas.custom.task.vo.EmpInfo;
+import com.kingdee.eas.util.app.DbUtil;
+import com.kingdee.util.DateTimeUtils;
+import com.kingdee.util.StringUtils;
+import okhttp3.*;
+import org.apache.log4j.Logger;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import com.kingdee.bos.*;
+
+import java.lang.String;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+public class SyncZYEmpFacadeControllerBean extends AbstractSyncZYEmpFacadeControllerBean {
+    private static String propertiesUrl = System.getProperty("EAS_HOME") + "/server/properties/Api/propertie.properties";
+    private List<EmpInfo> empInfoList = new ArrayList<>();
+    private static Logger logger = Logger.getLogger(SyncZYEmpFacadeControllerBean.class);
+    private int pageSize = 100;
+
+    /**
+     * 同步所有用户
+     *
+     * @param ctx
+     * @throws BOSException
+     */
+    @Override
+    protected void _SyncAllEmp(Context ctx) throws BOSException {
+        super._SyncAllEmp(ctx);
+        Properties properties = new Properties();
+        try {
+            properties.load(new FileInputStream(propertiesUrl));
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new BOSException(String.format("获取配置失败,请检查配置[%s]", propertiesUrl));
+        }
+        int empCount = getEmpCount(properties, null, null);
+        logger.error("获取用户总数: " + empCount);
+        getEmp(properties, null, null, empCount);
+        //更新用户信息
+        updateUserInfo(ctx);
+    }
+
+    /**
+     * 更新用户信息
+     *
+     * @param ctx
+     * @throws BOSException
+     */
+    private void updateUserInfo(Context ctx) throws BOSException {
+        try {
+            ObjectMapper objectMapper = new ObjectMapper();
+            UserCollection userCollection = UserFactory.getLocalInstance(ctx).getUserCollection("select id,person.*");
+            Map<String, String> idCardNoMap = new HashMap<>();
+            Map<String, String> passportNoMap = new HashMap<>();
+            Map<String, String> emailMap = new HashMap<>();
+            for (int i = 0; i < userCollection.size(); i++) {
+                UserInfo userInfo = userCollection.get(i);
+                String userId = userInfo.getId().toString();
+                PersonInfo personInfo = userInfo.getPerson();
+                //身份证号码
+                String idCardNO = personInfo.getIdCardNO();
+                if (!StringUtils.isEmpty(idCardNO)) {
+                    idCardNoMap.put(idCardNO, userId);
+                }
+                //护照号码
+                String passportNO = personInfo.getPassportNO();
+                if (!StringUtils.isEmpty(passportNO)) {
+                    passportNoMap.put(passportNO, userId);
+                }
+                //邮箱
+                String email = personInfo.getEmail();
+                if (!StringUtils.isEmpty(email)) {
+                    emailMap.put(email, userId);
+                }
+            }
+            List<Object[]> updateParams = new ArrayList<>();
+            for (int i = 0; i < empInfoList.size(); i++) {
+                //首先匹配身份证或护照号,再匹配邮箱
+                EmpInfo empInfo = empInfoList.get(i);
+                //账号
+                String username = empInfo.getUsername();
+                String email = empInfo.getEmail();
+                String cardType = empInfo.getCardType();
+                String cardNum = empInfo.getCardNum();
+                String userId = null;
+                if (!StringUtils.isEmpty(cardNum)) {
+                    if ("大陆地区身份证".equals(cardType)) {
+                        userId = idCardNoMap.get(cardNum);
+                    } else {
+                        userId = passportNoMap.get(cardNum);
+                    }
+                } else {
+                    userId = emailMap.get(email);
+                }
+                if (!StringUtils.isEmpty(userId)) {
+                    updateParams.add(new Object[]{username, userId});
+                }
+            }
+            logger.error("更新用户信息参数: " + objectMapper.writeValueAsString(updateParams));
+            String updateSql = "update t_pm_user set CFZYLoginName=? where fid=?";
+            DbUtil.executeBatch(ctx, updateSql, updateParams);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BOSException("更新用户信息报错: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 根据更新时间同步用户
+     *
+     * @param ctx
+     * @param updateBeginTime 更新开始时间(yyyy-MM-dd HH:mm:ss)
+     * @param updateEndTime   更新结束时间(yyyy-MM-dd HH:mm:ss)
+     * @throws BOSException
+     */
+    @Override
+    protected void _SyncEmpByUpdateTime(Context ctx, String updateBeginTime, String updateEndTime) throws BOSException {
+        super._SyncEmpByUpdateTime(ctx, updateBeginTime, updateEndTime);
+        Properties properties = new Properties();
+        try {
+            properties.load(new FileInputStream(propertiesUrl));
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new BOSException(String.format("获取配置失败,请检查配置[%s]", propertiesUrl));
+        }
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        if (StringUtils.isEmpty(updateBeginTime) && StringUtils.isEmpty(updateEndTime)) {
+            updateBeginTime = sdf.format(DateTimeUtils.addDay(new Date(), -7));
+        }
+        int empCount = getEmpCount(properties, updateBeginTime, updateEndTime);
+        logger.error("获取用户总数: " + empCount);
+        getEmp(properties, updateBeginTime, updateEndTime, empCount);
+        //更新用户信息
+        updateUserInfo(ctx);
+    }
+
+    /**
+     * 获取md5签名
+     *
+     * @param appSecret
+     * @param path
+     * @return
+     * @throws BOSException
+     */
+    private String getSignMd5String(String appSecret, String path) throws BOSException {
+        StringBuilder errorMsg = new StringBuilder();
+        if (StringUtils.isEmpty(appSecret)) {
+            errorMsg.append("appSecret不能为空!").append("\n");
+        }
+        if (StringUtils.isEmpty(path)) {
+            errorMsg.append("path不能为空!").append("\n");
+        }
+        if (errorMsg.length() > 0) {
+            throw new BOSException("生成md5签名报错: " + errorMsg);
+        }
+        String sign = MD5Utils.sign(appSecret, path);
+        logger.error("生成md5签名: " + sign);
+        return sign;
+    }
+
+    /**
+     * 查询用户总数
+     *
+     * @param properties
+     * @param updateBeginTime 更新开始时间
+     * @param updateEndTime   更新结束时间
+     * @return
+     * @throws BOSException
+     */
+    private int getEmpCount(Properties properties, String updateBeginTime, String updateEndTime) throws BOSException {
+        StringBuilder errorMsg = new StringBuilder();
+        OkHttpClient client = new OkHttpClient();
+        String appkey = properties.getProperty("Appkey");
+        String appSecret = properties.getProperty("AppSecret");
+        //"https://api-test.gemdale.com/openApi/organization-center/emp/getEmpCount"
+        String serverName = properties.getProperty("serverName");
+        //获取用户总数接口地址
+        String getEmpCountPath = properties.getProperty("getEmpCountPath");
+        if (StringUtils.isEmpty(appkey)) {
+            errorMsg.append("appkey 不能为空!").append("\n");
+        }
+        if (StringUtils.isEmpty(appSecret)) {
+            errorMsg.append("appSecret 不能为空!").append("\n");
+        }
+        if (StringUtils.isEmpty(serverName)) {
+            errorMsg.append("serverName 不能为空!").append("\n");
+        }
+        if (StringUtils.isEmpty(getEmpCountPath)) {
+            errorMsg.append("获取用户总数接口地址 不能为空!").append("\n");
+        }
+        if (errorMsg.length() > 0) {
+            throw new BOSException("生成md5签名报错: " + errorMsg);
+        }
+        JSONObject content = new JSONObject();
+        content.put("containslnvalid", false);//是否包含失效用户
+        if (!StringUtils.isEmpty(updateBeginTime)) {
+            content.put("updateBeginTime", updateBeginTime);
+        }
+        if (!StringUtils.isEmpty(updateEndTime)) {
+            content.put("updateEndTime", updateEndTime);
+        }
+        String contentStr = content.toJSONString();
+        logger.error("查询用户总数请求参数: " + contentStr);
+        RequestBody body = RequestBody.create(MediaType.parse("application/json"), contentStr);
+        try {
+            Request request = new Request.Builder()
+                    .url(serverName + getEmpCountPath)
+                    .post(body)
+                    .addHeader("x-ca-key", appkey)
+                    .addHeader("x-ca-signature", getSignMd5String(appSecret, getEmpCountPath))
+                    .addHeader("x-ca-signature-method", "MD5")
+                    .addHeader("content-type", "application/json")
+                    .build();
+            Response response = client.newCall(request).execute();
+            if (response.isSuccessful()) {
+                ObjectMapper objectMapper = new ObjectMapper();
+                Map result = objectMapper.readValue(response.body().string(), Map.class);
+                Boolean success = (Boolean) result.get("success");
+                if (success) {
+                    return (int) result.get("total");
+                } else {
+                    String msg = (String) result.get("msg");
+                    throw new BOSException(msg);
+                }
+            } else {
+                throw new BOSException("请求失败");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BOSException("查询用户总数报错: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询用户
+     *
+     * @param properties
+     * @param updateBeginTime 更新开始时间
+     * @param updateEndTime   更新结束时间
+     * @return
+     * @throws BOSException
+     */
+    private void getEmp(Properties properties, String updateBeginTime, String updateEndTime, int empCount) throws BOSException {
+        if (empCount > 0) {
+            ObjectMapper objectMapper = new ObjectMapper();
+            StringBuilder errorMsg = new StringBuilder();
+            OkHttpClient client = new OkHttpClient();
+            String appkey = properties.getProperty("Appkey");
+            String appSecret = properties.getProperty("AppSecret");
+            String serverName = properties.getProperty("serverName");
+            //获取用户总数接口地址
+            String getEmpPath = properties.getProperty("getEmpPath");
+            if (StringUtils.isEmpty(appkey)) {
+                errorMsg.append("appkey 不能为空!").append("\n");
+            }
+            if (StringUtils.isEmpty(appSecret)) {
+                errorMsg.append("appSecret 不能为空!").append("\n");
+            }
+            if (StringUtils.isEmpty(serverName)) {
+                errorMsg.append("serverName 不能为空!").append("\n");
+            }
+            if (StringUtils.isEmpty(getEmpPath)) {
+                errorMsg.append("获取用户接口地址 不能为空!").append("\n");
+            }
+            if (errorMsg.length() > 0) {
+                throw new BOSException("生成md5签名报错: " + errorMsg);
+            }
+            String signMd5String = getSignMd5String(appSecret, getEmpPath);
+            int pageCount = empCount % pageSize == 0 ? empCount / pageSize : empCount / pageSize + 1;
+            for (int i = 1; i <= pageCount; i++) {
+                JSONObject content = new JSONObject();
+                content.put("containslnvalid", false);//是否包含失效用户
+                content.put("pageSize", pageSize);
+                content.put("pageNum", i);
+                if (!StringUtils.isEmpty(updateBeginTime)) {
+                    content.put("updateBeginTime", updateBeginTime);
+                }
+                if (!StringUtils.isEmpty(updateEndTime)) {
+                    content.put("updateEndTime", updateEndTime);
+                }
+                RequestBody body = RequestBody.create(MediaType.parse("application/json"), content.toJSONString());
+                try {
+                    Request request = new Request.Builder()
+                            .url(serverName + getEmpPath)
+                            .post(body)
+                            .addHeader("x-ca-key", appkey)
+                            .addHeader("x-ca-signature", signMd5String)
+                            .addHeader("x-ca-signature-method", "MD5")
+                            .addHeader("content-type", "application/json")
+                            .build();
+                    Response response = client.newCall(request).execute();
+                    if (response.isSuccessful()) {
+                        String resultStr = response.body().string();
+                        Map result = objectMapper.readValue(resultStr, Map.class);
+                        Boolean success = (Boolean) result.get("success");
+                        logger.error("查询用户数据: " + resultStr);
+                        if (success) {
+                            String data = (String) result.get("data");
+                            EmpInfo empInfo = objectMapper.readValue(data, EmpInfo.class);
+                            empInfoList.add(empInfo);
+                        } else {
+                            String msg = (String) result.get("msg");
+                            throw new BOSException(msg);
+                        }
+                    } else {
+                        throw new BOSException("请求失败");
+                    }
+                    Thread.sleep(100);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw new BOSException("查询用户报错: " + e.getMessage());
+                }
+            }
+        }
+    }
+}

+ 30 - 0
src/com/kingdee/eas/custom/task/SyncZYEmpFacadeFactory.java

@@ -0,0 +1,30 @@
+package com.kingdee.eas.custom.task;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.BOSObjectFactory;
+import com.kingdee.bos.util.BOSObjectType;
+import com.kingdee.bos.Context;
+
+public class SyncZYEmpFacadeFactory
+{
+    private SyncZYEmpFacadeFactory()
+    {
+    }
+    public static com.kingdee.eas.custom.task.ISyncZYEmpFacade getRemoteInstance() throws BOSException
+    {
+        return (com.kingdee.eas.custom.task.ISyncZYEmpFacade)BOSObjectFactory.createRemoteBOSObject(new BOSObjectType("76DBFEF7") ,com.kingdee.eas.custom.task.ISyncZYEmpFacade.class);
+    }
+    
+    public static com.kingdee.eas.custom.task.ISyncZYEmpFacade getRemoteInstanceWithObjectContext(Context objectCtx) throws BOSException
+    {
+        return (com.kingdee.eas.custom.task.ISyncZYEmpFacade)BOSObjectFactory.createRemoteBOSObjectWithObjectContext(new BOSObjectType("76DBFEF7") ,com.kingdee.eas.custom.task.ISyncZYEmpFacade.class, objectCtx);
+    }
+    public static com.kingdee.eas.custom.task.ISyncZYEmpFacade getLocalInstance(Context ctx) throws BOSException
+    {
+        return (com.kingdee.eas.custom.task.ISyncZYEmpFacade)BOSObjectFactory.createBOSObject(ctx, new BOSObjectType("76DBFEF7"));
+    }
+    public static com.kingdee.eas.custom.task.ISyncZYEmpFacade getLocalInstance(String sessionID) throws BOSException
+    {
+        return (com.kingdee.eas.custom.task.ISyncZYEmpFacade)BOSObjectFactory.createBOSObject(sessionID, new BOSObjectType("76DBFEF7"));
+    }
+}

+ 372 - 0
src/com/kingdee/eas/custom/task/vo/EmpInfo.java

@@ -0,0 +1,372 @@
+package com.kingdee.eas.custom.task.vo;
+
+import java.util.List;
+
+/**
+ * 员工信息实体类。
+ */
+public class EmpInfo {
+    /**
+     * 员工的唯一标识符。
+     */
+    private String id;
+
+    /**
+     * 员工的用户名。
+     */
+    private String username;
+
+    /**
+     * 员工的职位。
+     */
+    private String job;
+
+    /**
+     * 职位ID。
+     */
+    private String jobId;
+
+    /**
+     * 职位级别。
+     */
+    private String jobLevel;
+
+    /**
+     * 性别。
+     */
+    private String sex;
+
+    /**
+     * 员工的全名。
+     */
+    private String fullname;
+
+    /**
+     * 员工的编号。
+     */
+    private String code;
+
+    /**
+     * 员工类型。
+     */
+    private String type;
+
+    /**
+     * 证件类型。
+     */
+    private String cardType;
+
+    /**
+     * 证件号码。
+     */
+    private String cardNum;
+
+    /**
+     * 员工的电子邮件地址。
+     */
+    private String email;
+
+    /**
+     * 员工的电话号码。
+     */
+    private String phone;
+
+    /**
+     * 组织机构ID。
+     */
+    private String organizationId;
+
+    /**
+     * 组织机构名称。
+     */
+    private String organizationName;
+
+    /**
+     * 组织机构IDs,用斜杠分隔。
+     */
+    private String organizationIds;
+
+    /**
+     * 组织机构名称,用斜杠分隔。
+     */
+    private String organizationNames;
+
+    /**
+     * 是否被禁用。
+     */
+    private String isDisabled;
+
+    /**
+     * 删除标志。
+     */
+    private Integer delFlag;
+
+    /**
+     * 职位。
+     */
+    private String position;
+
+    /**
+     * 职位ID。
+     */
+    private String positionId;
+
+    /**
+     * APS系统职位列表。
+     */
+    private List<String> apsPosition;
+
+    /**
+     * UPS系统职位列表。
+     */
+    private List<String> upsPosition;
+
+    /**
+     * LPS系统职位列表。
+     */
+    private List<String> lpsPosition;
+
+    /**
+     * 创建时间。
+     */
+    private String createTime;
+
+    /**
+     * 更新时间。
+     */
+    private String updateTime;
+
+    /**
+     * AD域GUID。
+     */
+    private String adGuid;
+
+    /**
+     * AD域DN(Distinguished Name)。
+     */
+    private String adDn;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getJob() {
+        return job;
+    }
+
+    public void setJob(String job) {
+        this.job = job;
+    }
+
+    public String getJobId() {
+        return jobId;
+    }
+
+    public void setJobId(String jobId) {
+        this.jobId = jobId;
+    }
+
+    public String getJobLevel() {
+        return jobLevel;
+    }
+
+    public void setJobLevel(String jobLevel) {
+        this.jobLevel = jobLevel;
+    }
+
+    public String getSex() {
+        return sex;
+    }
+
+    public void setSex(String sex) {
+        this.sex = sex;
+    }
+
+    public String getFullname() {
+        return fullname;
+    }
+
+    public void setFullname(String fullname) {
+        this.fullname = fullname;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getCardType() {
+        return cardType;
+    }
+
+    public void setCardType(String cardType) {
+        this.cardType = cardType;
+    }
+
+    public String getCardNum() {
+        return cardNum;
+    }
+
+    public void setCardNum(String cardNum) {
+        this.cardNum = cardNum;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getOrganizationId() {
+        return organizationId;
+    }
+
+    public void setOrganizationId(String organizationId) {
+        this.organizationId = organizationId;
+    }
+
+    public String getOrganizationName() {
+        return organizationName;
+    }
+
+    public void setOrganizationName(String organizationName) {
+        this.organizationName = organizationName;
+    }
+
+    public String getOrganizationIds() {
+        return organizationIds;
+    }
+
+    public void setOrganizationIds(String organizationIds) {
+        this.organizationIds = organizationIds;
+    }
+
+    public String getOrganizationNames() {
+        return organizationNames;
+    }
+
+    public void setOrganizationNames(String organizationNames) {
+        this.organizationNames = organizationNames;
+    }
+
+    public String getIsDisabled() {
+        return isDisabled;
+    }
+
+    public void setIsDisabled(String isDisabled) {
+        this.isDisabled = isDisabled;
+    }
+
+    public Integer getDelFlag() {
+        return delFlag;
+    }
+
+    public void setDelFlag(Integer delFlag) {
+        this.delFlag = delFlag;
+    }
+
+    public String getPosition() {
+        return position;
+    }
+
+    public void setPosition(String position) {
+        this.position = position;
+    }
+
+    public String getPositionId() {
+        return positionId;
+    }
+
+    public void setPositionId(String positionId) {
+        this.positionId = positionId;
+    }
+
+    public List<String> getApsPosition() {
+        return apsPosition;
+    }
+
+    public void setApsPosition(List<String> apsPosition) {
+        this.apsPosition = apsPosition;
+    }
+
+    public List<String> getUpsPosition() {
+        return upsPosition;
+    }
+
+    public void setUpsPosition(List<String> upsPosition) {
+        this.upsPosition = upsPosition;
+    }
+
+    public List<String> getLpsPosition() {
+        return lpsPosition;
+    }
+
+    public void setLpsPosition(List<String> lpsPosition) {
+        this.lpsPosition = lpsPosition;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getAdGuid() {
+        return adGuid;
+    }
+
+    public void setAdGuid(String adGuid) {
+        this.adGuid = adGuid;
+    }
+
+    public String getAdDn() {
+        return adDn;
+    }
+
+    public void setAdDn(String adDn) {
+        this.adDn = adDn;
+    }
+}

+ 331 - 0
src/com/qy/sso/bamboocloud/filter/authentication/ZYPortalAuthenticationFilter.java

@@ -0,0 +1,331 @@
+package com.qy.sso.bamboocloud.filter.authentication;
+
+import com.kingdee.bos.Context;
+import com.kingdee.bos.dao.IObjectPK;
+import com.kingdee.bos.dao.IObjectValue;
+import com.kingdee.bos.sso.client.util.FilterUtil;
+import com.kingdee.eas.base.common.DCInfo;
+import com.kingdee.eas.base.usermonitor.IUserMonitor;
+import com.kingdee.eas.base.usermonitor.UserMonitorFactory;
+import com.kingdee.eas.base.usermonitor.UserMonitorSessionInfo;
+import com.kingdee.eas.cp.eip.sso.util.LoginUtil;
+import com.kingdee.shr.guilogin.web.wechart.WeChartUtil;
+import com.kingdee.util.StringUtils;
+import org.jasig.cas.client.Protocol;
+import org.jasig.cas.client.authentication.*;
+import org.jasig.cas.client.configuration.ConfigurationKeys;
+import org.jasig.cas.client.util.AbstractCasFilter;
+import org.jasig.cas.client.util.CommonUtils;
+import org.jasig.cas.client.validation.Assertion;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Locale;
+
+/**
+ * @Description 竹云单点认证过滤器
+ * @Date 2024/9/23 15:45
+ * @Created by Heyuan
+ */
+public class ZYPortalAuthenticationFilter extends AbstractCasFilter {
+    private boolean getServerNameFromRequest;
+    private boolean getServerLoginUrlFromRequest;
+    private String serverLoginUrl;
+    private String casServerLoginUrl;
+    private String clientId;
+    private String responseType;
+
+
+    private boolean renew;
+    private boolean gateway;
+    private String method;
+    private GatewayResolver gatewayStorage;
+    private AuthenticationRedirectStrategy authenticationRedirectStrategy;
+    //private static final Map<String, Class<? extends UrlPatternMatcherStrategy>> PATTERN_MATCHER_TYPES = new HashMap();
+
+    public ZYPortalAuthenticationFilter() {
+        this(Protocol.ZY);
+    }
+
+
+    protected ZYPortalAuthenticationFilter(Protocol protocol) {
+        super(protocol);
+        this.renew = false;
+        this.gateway = false;
+        this.gatewayStorage = new DefaultGatewayResolverImpl();
+        this.authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();
+    }
+
+    /**
+     * 初始化过滤器
+     */
+    public void init() {
+        super.init();
+        String message = String.format("one of %s and %s must not be null.",
+                ConfigurationKeys.CAS_SERVER_LOGIN_URL.getName(),
+                ConfigurationKeys.CAS_SERVER_URL_PREFIX.getName());
+        //
+        CommonUtils.assertNotNull(this.casServerLoginUrl, message);
+    }
+
+
+    public final void doFilter(ServletRequest servletRequest,
+                               ServletResponse servletResponse,
+                               FilterChain filterChain) throws IOException, ServletException {
+        //1.判断使用是否有登录会话,校验登录人和会话登录人一致性
+        //2.没有登录会话,判断是否有参数code,有就调用获取token方法和获取用户信息,登录
+        //3.没有code,就返回竹云登录页面
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        if (this.isRequestUrlExcluded(request)) {
+            //请求路径不在匹配规则路径内,忽略
+            this.logger.debug("Request is ignored.");
+            filterChain.doFilter(request, response);
+        } else {
+            //是否重置会话
+            boolean sessionRenew = false;
+            String username = request.getParameter("kdacccode");
+            if (StringUtils.isEmpty(username)) {
+                username = request.getParameter("username");
+            }
+            if (StringUtils.isEmpty(username)) {
+                username = request.getParameter("usern");
+            }
+            this.logger.debug("username  \"{}\"", username);
+            if (username != null) {
+                HttpSession session = request.getSession(false);
+                //会话
+                Assertion assertion = session != null ? (Assertion) session.getAttribute("_const_cas_assertion_") : null;
+                if (assertion != null) {
+                    username = URLDecoder.decode(username, "UTF-8");
+                    //当前登录用户人
+                    String ctxUsername = assertion.getPrincipal().getName();
+                    if (ctxUsername != null && !ctxUsername.equalsIgnoreCase(username)) {
+                        //用户名不等于当前用户,会话失效
+                        session.setAttribute("_const_cas_assertion_", (Object) null);
+                        session.setAttribute("KD_PORTAL_IS_INIT_CONTEXT", (Object) null);
+                        session.invalidate();
+                        sessionRenew = true;
+                    }
+                    if (session.getAttribute("userMonitorSessionInfo") != null) {
+                        UserMonitorSessionInfo userMonitorSessionInfo =
+                                (UserMonitorSessionInfo) session
+                                        .getAttribute("userMonitorSessionInfo");
+                        try {
+                            IUserMonitor iUserMonitor = UserMonitorFactory.getRemoteInstance();
+                            IObjectValue info = iUserMonitor.getValue(
+                                    userMonitorSessionInfo.getId());
+                            if (info == null) {
+                                session.setAttribute("_const_cas_assertion_", (Object) null);
+                                session.setAttribute("KD_PORTAL_IS_INIT_CONTEXT", (Object) null);
+                                session.invalidate();
+                                sessionRenew = true;
+                            }
+                        } catch (Exception var16) {
+                            this.logger.error("checkUserBeTicked err!", var16);
+                        }
+                    }
+                }
+            }
+            this.setEncodeServiceUrl(true);
+            //构建登录地址
+            this.constructLoginUrl(servletRequest, sessionRenew);
+            //构建服务ip和端口地址
+            String constructServerName = this.constructServerName(servletRequest);
+            HttpSession session = request.getSession(false);
+            Assertion assertion = session != null ? (Assertion) session.getAttribute("_const_cas_assertion_") : null;
+            String serviceUrl;
+            String constructServiceUrl;
+            if (assertion != null) {
+                filterChain.doFilter(request, response);
+            } else {
+                //跳转竹云认证
+                serviceUrl = com.kingdee.bos.sso.client.util.CommonUtils.constructServiceUrl(request, response, null, this.getServerName(constructServerName), this.getProtocol().getServiceParameterName(), this.getProtocol().getArtifactParameterName(), true);
+                constructServiceUrl = this.retrieveTicketFromRequest(request);
+                boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
+                if (!CommonUtils.isNotBlank(constructServiceUrl) && !wasGatewayed) {
+                    this.logger.debug("no ticket and no assertion found");
+                    String modifiedServiceUrl;
+                    if (this.gateway) {
+                        this.logger.debug("setting gateway attribute in session");
+                        modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
+                    } else {
+                        modifiedServiceUrl = serviceUrl;
+                    }
+                    this.logger.debug("Constructed service url: {}", modifiedServiceUrl);
+                    //生成重定向地址
+                    String urlToRedirectTo = constructRedirectUrl(this.casServerLoginUrl, this.getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway, this.method);
+                    this.logger.debug("redirecting to \"{}\"", urlToRedirectTo);
+                    this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
+                } else {
+                    filterChain.doFilter(request, response);
+                }
+            }
+        }
+    }
+
+
+    public String constructRedirectUrl(String casServerLoginUrl, String serviceParameterName, String serviceUrl, boolean renew, boolean gateway, String method) {
+        return casServerLoginUrl + (casServerLoginUrl.contains("?") ? "&" : "?") + serviceParameterName + "=" + serviceUrl + (renew ? "&renew=true" : "") + (gateway ? "&gateway=true" : "") + (method != null ? "&method=" + method : "");
+    }
+
+
+    protected static Context initRPC(String dataCenter, String easSessionId) {
+        DCInfo dcInfo = WeChartUtil.getDCInfo(dataCenter);
+        Context ctx = new Context((IObjectPK) null, dcInfo.getSolutionName(), dcInfo.getNumber(), (Locale) null);
+        LoginUtil.initRpcConfig(ctx, easSessionId);
+        return ctx;
+    }
+
+    /**
+     * 获取服务地址 ip:port
+     *
+     * @param constructServerName
+     * @return
+     */
+    private String getServerName(String constructServerName) {
+        if (constructServerName != null) {
+            return constructServerName;
+        } else {
+            try {
+                Class clazz = this.getClass().getSuperclass();
+                Field field = clazz.getDeclaredField("serverName");
+                field.setAccessible(true);
+                return (String) field.get(this);
+            } catch (Exception var4) {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * 构建服务地址   ip:port
+     *
+     * @param request
+     * @return
+     */
+    private String constructServerName(ServletRequest request) {
+        //是否从请求中获取服务地址
+        if (this.getServerNameFromRequest) {
+            StringBuilder serverName = new StringBuilder();
+            serverName.append(request.getServerName());
+            serverName.append(":");
+            serverName.append(request.getServerPort());
+            this.setServerName(serverName.toString());
+            return serverName.toString();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 构建登录地址
+     *
+     * @param request
+     * @param sessionRenew 是否重置会话
+     */
+    private void constructLoginUrl(ServletRequest request, boolean sessionRenew) {
+        HttpServletRequest httpRequest = (HttpServletRequest) request;
+        //获取httpSession,为空时不创建
+        HttpSession session = httpRequest.getSession(false);
+        Assertion assertion = session != null ? (Assertion) session.getAttribute("_const_cas_assertion_") : null;
+
+        try {
+            URL contextURL = new URL(this.serverLoginUrl);
+            URL destURL = contextURL;
+            //
+            if (this.getServerLoginUrlFromRequest) {
+                destURL = new URL(request.getScheme(), request.getServerName(), request.getServerPort(), contextURL.getFile());
+            }
+
+            if (assertion != null) {
+                this.setCasServerLoginUrl(destURL.toString());
+            } else {
+                String renew = request.getParameter("renew");
+                if (sessionRenew) {
+                    renew = "true";
+                }
+                StringBuilder optionParam = new StringBuilder();
+                optionParam.append("?client_id=").append(this.clientId)
+                        .append("&response_type=").append(this.responseType)
+                        .append("&state=").append(System.currentTimeMillis());
+                this.setCasServerLoginUrl(destURL.toString() + optionParam);
+            }
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public final void setRenew(boolean renew) {
+        this.renew = renew;
+    }
+
+    public final void setGateway(boolean gateway) {
+        this.gateway = gateway;
+    }
+
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+    public final void setCasServerUrlPrefix(String casServerUrlPrefix) {
+        this.setCasServerLoginUrl(CommonUtils.addTrailingSlash(casServerUrlPrefix) + "login");
+    }
+
+    public final void setCasServerLoginUrl(String casServerLoginUrl) {
+        this.casServerLoginUrl = casServerLoginUrl;
+    }
+
+    public final void setGatewayStorage(GatewayResolver gatewayStorage) {
+        this.gatewayStorage = gatewayStorage;
+    }
+
+    private boolean isRequestUrlExcluded(HttpServletRequest request) throws MalformedURLException {
+        return FilterUtil.isUnFilter(request);
+    }
+
+    public final void setIgnoreUrlPatternMatcherStrategyClass(UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass) {
+    }
+
+    public final void setServerLoginUrl(String serverLoginUrl) {
+        this.serverLoginUrl = serverLoginUrl;
+        this.setCasServerLoginUrl(this.serverLoginUrl);
+    }
+
+    public final void setGetServerNameFromRequest(boolean getServerNameFromRequest) {
+        this.getServerNameFromRequest = getServerNameFromRequest;
+    }
+
+    public final void setGetServerLoginUrlFromRequest(boolean getServerLoginUrlFromRequest) {
+        this.getServerLoginUrlFromRequest = getServerLoginUrlFromRequest;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public void setResponseType(String responseType) {
+        this.responseType = responseType;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+//    static {
+//        PATTERN_MATCHER_TYPES.put("CONTAINS", ContainsPatternUrlPatternMatcherStrategy.class);
+//        PATTERN_MATCHER_TYPES.put("REGEX", RegexUrlPatternMatcherStrategy.class);
+//        PATTERN_MATCHER_TYPES.put("FULL_REGEX", EntireRegionRegexUrlPatternMatcherStrategy.class);
+//        PATTERN_MATCHER_TYPES.put("EXACT", ExactUrlPatternMatcherStrategy.class);
+//    }
+}

+ 264 - 0
src/com/qy/sso/bamboocloud/filter/validate/ZYTicketValidationFilter.java

@@ -0,0 +1,264 @@
+package com.qy.sso.bamboocloud.filter.validate;
+
+import com.kingdee.bos.sso.client.util.FilterUtil;
+import com.kingdee.shr.base.syssetting.exception.SHRWebException;
+import com.qy.sso.bamboocloud.validation.ZYPortalServiceTicketValidator;
+import org.jasig.cas.client.Protocol;
+import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
+import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl;
+import org.jasig.cas.client.validation.*;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * @Description 竹云用户信息校验过滤器
+ * @Date 2024/9/23 16:01
+ * @Created by Heyuan
+ */
+public class ZYTicketValidationFilter extends Cas20ProxyReceivingTicketValidationFilter {
+    //com.kingdee.shr.base.syssetting.web.filter.SHRTicketValidationFilter
+    private String getTokenPath;//获取授权接口,相对地址
+    private String getUserInfoPath;//获取用户信息接口,相对地址
+    private String clientSecret;
+    private String grantType;
+    private String clientId;
+    private String responseType;
+
+    private boolean getServerNameFromRequest;
+    private boolean getServerLoginUrlFromRequest;
+    private String casServerUrlPrefix;
+    private String acceptAnyProxy;
+    private String allowedProxyChains;
+    private String proxyCallbackUrl;
+    private boolean renew;
+    private String encoding;
+    private Map<String, String> additionalParameters = new HashMap();
+    private ProxyGrantingTicketStorage proxyGrantingTicketStorage = new ProxyGrantingTicketStorageImpl();
+
+
+    public ZYTicketValidationFilter() {
+        this(Protocol.ZY);
+        //this.defaultServiceTicketValidatorClass = Cas20ServiceTicketValidator.class;
+        this.defaultProxyTicketValidatorClass = Cas20ProxyTicketValidator.class;
+    }
+
+    protected ZYTicketValidationFilter(Protocol protocol) {
+        super(protocol);
+        this.proxyGrantingTicketStorage = new ProxyGrantingTicketStorageImpl();
+    }
+
+    /**
+     * 校验成功
+     *
+     * @param request
+     * @param response
+     * @param assertion
+     */
+    protected void onSuccessfulValidation(HttpServletRequest request,
+                                          HttpServletResponse response,
+                                          Assertion assertion) {
+        super.onSuccessfulValidation(request, response, assertion);
+        try {
+            //初始化会话数据
+            this.initializeSessionData(request, response);
+        } catch (SHRWebException var5) {
+            throw new RuntimeException(var5);
+        }
+    }
+
+    /**
+     * 初始化会话数据
+     *
+     * @param request
+     * @param response
+     * @throws SHRWebException
+     */
+    private void initializeSessionData(HttpServletRequest request,
+                                       HttpServletResponse response) throws SHRWebException {
+        HttpSession session = request.getSession();
+        try {
+            if (session != null) {
+                session.setAttribute("contextPath", request.getContextPath());
+                session.setAttribute("sessionCreateTime", session.getCreationTime());
+            } else {
+                //重定向到登出页面
+                response.sendRedirect("/shr/shr_loginout/logout.do");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            try {
+                if (session != null) {
+                    //会话失效
+                    session.invalidate();
+                }
+                //重定向到登出页面
+                response.sendRedirect("/shr/shr_loginout/logout.do");
+            } catch (IOException var6) {
+                var6.printStackTrace();
+            }
+        }
+    }
+
+
+    /**
+     * 获取身份校验器
+     *
+     * @return
+     */
+    protected TicketValidator getTicketValidator() {
+        //Cas20ServiceTicketValidator
+        ZYPortalServiceTicketValidator validator = new ZYPortalServiceTicketValidator();
+        validator.setClientId(this.clientId);
+        validator.setClientSecret(this.clientSecret);
+        validator.setGrantType(this.grantType);
+        validator.setResponseType(this.responseType);
+        validator.setGetTokenPath(this.getTokenPath);
+        validator.setGetUserInfoPath(this.getUserInfoPath);
+        return validator;
+    }
+
+    /**
+     *
+     * @param request
+     * @return
+     */
+    protected String retrieveTicketFromRequest(HttpServletRequest request) {
+        try {
+            if (FilterUtil.isUnFilter(request)) {
+                return null;
+            }
+            this.constructLoginUrl(request);
+            this.constructServerName(request);
+            this.setTicketValidator(this.getTicketValidator());
+        } catch (MalformedURLException var3) {
+            var3.printStackTrace();
+        }
+        return super.retrieveTicketFromRequest(request);
+    }
+
+    /**
+     * 构建登录地址
+     *
+     * @param request
+     */
+    private void constructLoginUrl(ServletRequest request) {
+        if (this.getServerLoginUrlFromRequest) {
+            try {
+                URL contextURL = new URL(this.casServerUrlPrefix);
+                URL destURL = new URL(contextURL.getProtocol(), request.getServerName(), request.getServerPort(), contextURL.getFile());
+                this.casServerUrlPrefix = destURL.toString();
+            } catch (MalformedURLException var4) {
+                var4.printStackTrace();
+            }
+        }
+
+    }
+
+    /**
+     * 构建服务地址   ip:port
+     *
+     * @param request
+     * @return
+     */
+    private void constructServerName(ServletRequest request) {
+        if (this.getServerNameFromRequest) {
+            StringBuilder serverName = new StringBuilder();
+            serverName.append(request.getServerName());
+            serverName.append(":");
+            serverName.append(request.getServerPort());
+            this.setServerName(serverName.toString());
+        }
+    }
+
+
+    public void setGetTokenPath(String getTokenPath) {
+        this.getTokenPath = getTokenPath;
+    }
+
+    public void setGetUserInfo(String getUserInfoPath) {
+        this.getUserInfoPath = getUserInfoPath;
+    }
+
+    public void setClientSecret(String clientSecret) {
+        this.clientSecret = clientSecret;
+    }
+
+    public void setGrantType(String grantType) {
+        this.grantType = grantType;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public void setResponseType(String responseType) {
+        this.responseType = responseType;
+    }
+
+    public String getGetTokenPath() {
+        return getTokenPath;
+    }
+
+    public String getGetUserInfoPath() {
+        return getUserInfoPath;
+    }
+
+    public void setGetUserInfoPath(String getUserInfoPath) {
+        this.getUserInfoPath = getUserInfoPath;
+    }
+
+    public String getClientSecret() {
+        return clientSecret;
+    }
+
+    public String getGrantType() {
+        return grantType;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public String getResponseType() {
+        return responseType;
+    }
+
+    public final void setGetServerNameFromRequest(boolean getServerNameFromRequest) {
+        this.getServerNameFromRequest = getServerNameFromRequest;
+    }
+
+    public final void setGetServerLoginUrlFromRequest(boolean getServerLoginUrlFromRequest) {
+        this.getServerLoginUrlFromRequest = getServerLoginUrlFromRequest;
+    }
+
+    public final void setCasServerUrlPrefix(String casServerUrlPrefix) {
+        this.casServerUrlPrefix = casServerUrlPrefix;
+    }
+
+    public final void setAcceptAnyProxy(String acceptAnyProxy) {
+        this.acceptAnyProxy = acceptAnyProxy;
+    }
+
+    public final void setAllowedProxyChains(String allowedProxyChains) {
+        this.allowedProxyChains = allowedProxyChains;
+    }
+
+    public final void setProxyCallbackUrl(String proxyCallbackUrl) {
+        this.proxyCallbackUrl = proxyCallbackUrl;
+    }
+
+    public final void setRenew(boolean renew) {
+        this.renew = renew;
+    }
+
+    public final void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+}

+ 291 - 0
src/com/qy/sso/bamboocloud/validation/ZYPortalServiceTicketValidator.java

@@ -0,0 +1,291 @@
+package com.qy.sso.bamboocloud.validation;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.kingdee.bos.Context;
+import com.kingdee.eas.cp.eip.sso.util.CASLoginConfigPropUtil;
+import com.kingdee.eas.cp.eip.sso.util.CloudParamUtil;
+import com.kingdee.eas.util.app.DbUtil;
+import com.kingdee.jdbc.rowset.IRowSet;
+import com.kingdee.util.StringUtils;
+import okhttp3.*;
+import org.jasig.cas.client.authentication.AttributePrincipal;
+import org.jasig.cas.client.authentication.AttributePrincipalImpl;
+import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
+import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
+import org.jasig.cas.client.validation.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description 竹云系统单点身份校验器
+ * @Date 2024/9/23 19:28
+ * @Created by Heyuan
+ */
+public class ZYPortalServiceTicketValidator implements TicketValidator {
+    //org.jasig.cas.client.validation.Cas20ServiceTicketValidator
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+    //httpurl链接工厂
+    private HttpURLConnectionFactory urlConnectionFactory = new HttpsURLConnectionFactory();
+    //private final String casServerUrlPrefix;
+    private boolean renew;
+    private Map<String, String> customParameters;
+    private String encoding;
+    private String clientSecret;
+    private String grantType;
+    private String clientId;
+    private String responseType;
+    private String getTokenPath;//获取授权接口,相对地址
+    private String getUserInfoPath;//获取用户信息接口,相对地址
+
+
+    /**
+     * 校验
+     *
+     * @param code    身份标识
+     * @param service
+     * @return
+     * @throws TicketValidationException
+     */
+    public final Assertion validate(String code,
+                                    String service) throws TicketValidationException {
+        //String validationUrl = this.constructValidationUrl(code, service);
+        //this.logger.debug("Constructing validation url: {}", validationUrl);
+        try {
+            this.logger.debug("Retrieving response from server.");
+            Map<String, Object> token = getToken(code, null);
+            String loginName = getUserInfo(token);//员工编码
+            System.out.println("获取员工信息 登录账号: " + loginName);
+            if (StringUtils.isEmpty(loginName)) {
+                throw new TicketValidationException("获取用户信息的登录账号为空!");
+            }
+            String dataCenter = CASLoginConfigPropUtil.getDataCenter();
+            String locale = CASLoginConfigPropUtil.getLocale();
+            if (!StringUtils.isEmpty(dataCenter) && !StringUtils.isEmpty(locale)) {
+                Context ctx = CloudParamUtil.getContext(dataCenter, locale, "administrator");
+                String sql = "SELECT fnumber FROM T_PM_USER WHERE LOWER(CFZYLoginName)=?";
+                IRowSet rs = DbUtil.executeQuery(ctx, sql, new Object[]{loginName.toLowerCase()});
+                String userNumber = null;
+                if (rs.next()) {
+                    userNumber = rs.getString("fnumber");
+                }
+                if (StringUtils.isEmpty(userNumber)) {
+                    throw new TicketValidationException("loginName :" + loginName + "不是shr用户");
+                }
+                //创建登录用户
+                AttributePrincipal principal = new AttributePrincipalImpl(userNumber);
+                return new AssertionImpl(principal, new HashMap<>());
+            } else {
+                throw new TicketValidationException("数据中心 或 locale 为空!");
+            }
+        } catch (Exception var5) {
+            var5.printStackTrace();
+            throw new TicketValidationException(var5);
+        }
+    }
+
+    private Map<String, Object> getToken(String code, String state) throws TicketValidationException {
+        System.out.println("code: " + code);
+        System.out.println("state: " + state);
+        if (StringUtils.isEmpty(code)) {
+            //检查session
+            throw new TicketValidationException("code 不能为空!");
+        }
+        OkHttpClient client = new OkHttpClient();
+        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
+        Map<String, String> params = new HashMap<>();
+        params.put("client_id", this.clientId);
+        params.put("client_secret", this.clientSecret);
+        params.put("code", code);
+        params.put("grant_type", this.grantType);
+        RequestBody body = RequestBody.create(mediaType, constructRequestParameter(params));
+        Request request = new Request.Builder()
+                .url(this.getTokenPath)
+                .post(body)
+                .addHeader("content-type", "application/x-www-form-urlencoded")
+                .build();
+        Response sYResponse = null;
+        try {
+            sYResponse = client.newCall(request).execute();
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new TicketValidationException("获取Token请求执行失败!");
+        }
+        if (sYResponse.isSuccessful()) {
+            try {
+                String result = sYResponse.body().string();
+                System.out.println("getToken sYResponse : " + result);
+                ObjectMapper objectMapper = new ObjectMapper();
+                Map<String, Object> map = objectMapper.readValue(result, Map.class);
+                String errcode = (String) map.get("errcode");
+                if (StringUtils.isEmpty(errcode)) {
+                    //请求成功
+                    return map;
+                } else {
+                    String msg = (String) map.get("msg");//错误信息
+                    throw new TicketValidationException("获取Token失败: " + msg);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new TicketValidationException("获取Token失败: " + e.getMessage());
+            }
+        } else {
+            //失败
+            throw new TicketValidationException("获取Token请求失败");
+        }
+    }
+
+    private String getUserInfo(Map<String, Object> tokenResponse) throws TicketValidationException {
+        if (tokenResponse == null) {
+            throw new TicketValidationException("tokenResponse 不能为空!");
+        }
+        String access_token = (String) tokenResponse.get("access_token");
+//        int expires_in = tokenResponse.getInteger("expires_in");
+//        String refresh_token = tokenResponse.getString("refresh_token");
+//        String uid = tokenResponse.getString("uid");//登录用户
+        OkHttpClient client = new OkHttpClient();
+        Map<String, String> params = new HashMap<>();
+        params.put("client_id", this.clientId);
+        params.put("access_token", access_token);
+        Request request = new Request.Builder()
+                .url(this.getUserInfoPath + "?" + constructRequestParameter(params))
+                .get()
+                .addHeader("content-type", "application/json")
+                .build();
+        Response sYResponse = null;
+        try {
+            sYResponse = client.newCall(request).execute();
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new TicketValidationException("获取用户信息请求执行失败!");
+        }
+        if (sYResponse.isSuccessful()) {
+            try {
+                String result = sYResponse.body().string();
+                System.out.println("getUserInfo sYResponse : " + result);
+                ObjectMapper objectMapper = new ObjectMapper();
+                Map<String, Object> map = objectMapper.readValue(result, Map.class);
+                String errcode = (String) map.get("errcode");
+                if (StringUtils.isEmpty(errcode)) {
+                    //请求成功
+                    return (String) map.get("loginName");//登录账号
+                } else {
+                    String msg = (String) map.get("msg");//错误信息
+                    throw new TicketValidationException("获取用户信息失败: " + msg);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+                throw new TicketValidationException("获取用户信息失败: " + e.getMessage());
+            }
+        } else {
+            //失败
+            throw new TicketValidationException("获取用户信息请求失败 ");
+        }
+    }
+
+    /**
+     * 构建请求参数
+     *
+     * @param map
+     * @return
+     */
+    private String constructRequestParameter(Map<String, String> map) {
+        StringBuilder parameters = new StringBuilder();
+        if (map != null) {
+            for (String key : map.keySet()) {
+                String value = map.get(key);
+                parameters.append(key).append("=").append(value).append("&");
+            }
+            parameters.deleteCharAt(parameters.lastIndexOf("&"));
+        }
+        return parameters.toString();
+    }
+
+    protected String getUrlSuffix() {
+        return "serviceValidate";
+    }
+
+    public HttpURLConnectionFactory getUrlConnectionFactory() {
+        return urlConnectionFactory;
+    }
+
+    public void setUrlConnectionFactory(HttpURLConnectionFactory urlConnectionFactory) {
+        this.urlConnectionFactory = urlConnectionFactory;
+    }
+
+    public boolean isRenew() {
+        return renew;
+    }
+
+    public void setRenew(boolean renew) {
+        this.renew = renew;
+    }
+
+    public Map<String, String> getCustomParameters() {
+        return customParameters;
+    }
+
+    public void setCustomParameters(Map<String, String> customParameters) {
+        this.customParameters = customParameters;
+    }
+
+    public String getEncoding() {
+        return encoding;
+    }
+
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    public String getClientSecret() {
+        return clientSecret;
+    }
+
+    public void setClientSecret(String clientSecret) {
+        this.clientSecret = clientSecret;
+    }
+
+    public String getGrantType() {
+        return grantType;
+    }
+
+    public void setGrantType(String grantType) {
+        this.grantType = grantType;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getResponseType() {
+        return responseType;
+    }
+
+    public void setResponseType(String responseType) {
+        this.responseType = responseType;
+    }
+
+    public String getGetTokenPath() {
+        return getTokenPath;
+    }
+
+    public void setGetTokenPath(String getTokenPath) {
+        this.getTokenPath = getTokenPath;
+    }
+
+    public String getGetUserInfoPath() {
+        return getUserInfoPath;
+    }
+
+    public void setGetUserInfoPath(String getUserInfoPath) {
+        this.getUserInfoPath = getUserInfoPath;
+    }
+
+}

+ 34 - 0
src/org/jasig/cas/client/Protocol.java

@@ -0,0 +1,34 @@
+package org.jasig.cas.client;
+
+/**
+ * @Description 协议
+ * @Date 2024/9/24 1:04
+ * @Created by Heyuan
+ */
+public enum Protocol {
+    CAS1("ticket", "service"),
+    CAS2(CAS1),
+    CAS3(CAS2),
+    SAML11("SAMLart", "TARGET"),
+    ZY("code", "redirect_uri");//竹云
+
+    private final String artifactParameterName;//身份认证参数名
+    private final String serviceParameterName;//重定向地址参数名
+
+    private Protocol(String artifactParameterName, String serviceParameterName) {
+        this.artifactParameterName = artifactParameterName;
+        this.serviceParameterName = serviceParameterName;
+    }
+
+    private Protocol(Protocol protocol) {
+        this(protocol.getArtifactParameterName(), protocol.getServiceParameterName());
+    }
+
+    public String getArtifactParameterName() {
+        return this.artifactParameterName;
+    }
+
+    public String getServiceParameterName() {
+        return this.serviceParameterName;
+    }
+}