Parcourir la source

Merge branch 'feat-评测改造-chenbh' of http://192.168.0.144/dcuc-tjdsj/auth-service into mazq-jiekouyouhua-230523

 Conflicts:
	dcuc-auth-api/src/main/java/com/dragoninfo/dcuc/auth/token/facade/IAuthTokenFacade.java
	dcuc-auth-service/pom.xml
	dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/zerotrust/IAuthTokenBusiness.java
	dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/token/facade/AuthTokenFacade.java
mazq il y a 2 ans
Parent
commit
d9aa0a693c
22 fichiers modifiés avec 843 ajouts et 2 suppressions
  1. 40 0
      dcuc-auth-api/src/main/java/com/dragoninfo/dcuc/auth/element/facade/IEnvElementFacade.java
  2. 14 0
      dcuc-auth-api/src/main/java/com/dragoninfo/dcuc/auth/token/facade/IAuthTokenFacade.java
  3. 5 0
      dcuc-auth-model/pom.xml
  4. 22 0
      dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/audit/dto/warningrule/ExceptionIpRule.java
  5. 37 0
      dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/element/vo/ElementUserRelRespVo.java
  6. 27 0
      dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/element/vo/ElementUserSaveVo.java
  7. 33 0
      dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/element/vo/EnvElementRespVo.java
  8. 21 0
      dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/token/vo/TokenOnlineReqVo.java
  9. 21 0
      dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/token/vo/TokenOnlineRespVo.java
  10. 2 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/audit/listener/AuthenticationLogListener.java
  11. 111 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/audit/service/DetectLogService.java
  12. 29 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/impl/zerotrust/AuthTokenBusinessImpl.java
  13. 7 2
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/zerotrust/IAuthTokenBusiness.java
  14. 34 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/business/IEnvElementBusiness.java
  15. 149 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/business/impl/EnvElementBusiness.java
  16. 71 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/entity/ElementUserRel.java
  17. 27 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/facade/EnvElementFacade.java
  18. 23 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/repo/EnvElementUserRelRepository.java
  19. 47 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/service/IElementUserRelService.java
  20. 57 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/service/impl/EnvElemenUserRelServiceImpl.java
  21. 7 0
      dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/token/facade/AuthTokenFacade.java
  22. 59 0
      dcuc-auth-service/src/main/resources/config/mysql/V4_3_0031__UpdateEnvment.sql

+ 40 - 0
dcuc-auth-api/src/main/java/com/dragoninfo/dcuc/auth/element/facade/IEnvElementFacade.java

@@ -1,13 +1,19 @@
 package com.dragoninfo.dcuc.auth.element.facade;
 
+import com.dragoninfo.dcuc.auth.element.vo.ElementUserRelRespVo;
+import com.dragoninfo.dcuc.auth.element.vo.ElementUserSaveVo;
 import com.dragoninfo.dcuc.auth.element.vo.EnvElementSaveVo;
 import com.dragoninfo.dcuc.auth.element.vo.RespEnvElementVo;
+import com.dragoninfo.dcuc.auth.sub.vo.AuthUserVo;
+import com.dragoninfo.duceap.core.response.Result;
 import com.dragonsoft.duceap.base.entity.http.ResponseStatus;
 import com.dragonsoft.duceap.base.entity.search.SearchDTO;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.data.domain.Page;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 /**
  * @author mazq
  * @date 2022/8/25
@@ -54,4 +60,38 @@ public interface IEnvElementFacade {
      */
     @DeleteMapping("deleteById/{id}")
     ResponseStatus deleteById(@PathVariable("id") String id);
+
+    /**
+     * 关联用户分页查询
+     * @param searchDTO
+     * @return
+     */
+    @PostMapping("userRelPage")
+    Result<List<ElementUserRelRespVo>> userRelPage(@RequestBody SearchDTO searchDTO);
+
+    /**
+     * 保存用户关联关系
+     *
+     * @param relSaveVo
+     * @return
+     */
+    @PostMapping("userRelSave")
+    Result<Object> userRelSave(@RequestBody ElementUserSaveVo relSaveVo);
+
+    /**
+     * 删除用户关联关系
+     *
+     * @param id
+     * @return
+     */
+    @DeleteMapping("deleteUserRel/{id}")
+    Result<Object> deleteUserRel(@PathVariable("id") String id);
+
+    /**
+     * 非关联用户分页查询
+     * @param searchDTO
+     * @return
+     */
+    @PostMapping("notInUserRelPage")
+    Result<List<AuthUserVo>> notInUserRelPage(@RequestBody SearchDTO searchDTO);
 }

+ 14 - 0
dcuc-auth-api/src/main/java/com/dragoninfo/dcuc/auth/token/facade/IAuthTokenFacade.java

@@ -1,9 +1,14 @@
 package com.dragoninfo.dcuc.auth.token.facade;
 
+import com.dragoninfo.dcuc.auth.api.vo.zerotrust.ZeroTrustMessageRespVO;
+import com.dragoninfo.dcuc.auth.token.vo.TokenOnlineReqVo;
+import com.dragoninfo.dcuc.auth.token.vo.TokenOnlineRespVo;
 import com.dragoninfo.dcuc.auth.api.vo.zerotrust.ZeroTrustMessageRespVO;
 import com.dragoninfo.dcuc.auth.token.vo.TokenReceiveVO;
+import com.dragoninfo.duceap.core.response.Result;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 
 /**
  * @author mazq
@@ -20,4 +25,13 @@ public interface IAuthTokenFacade {
      */
     @PostMapping("tokenReceive")
     ZeroTrustMessageRespVO tokenReceive(TokenReceiveVO receiveVO);
+
+    /**
+     * 令牌在线查询
+     * @param reqVo
+     * @return
+     */
+    @PostMapping("tokenOnlineQuery")
+    Result<TokenOnlineRespVo> tokenOnlineQuery(@RequestBody TokenOnlineReqVo reqVo);
+
 }

+ 5 - 0
dcuc-auth-model/pom.xml

@@ -27,5 +27,10 @@
             <artifactId>lombok</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>com.dragoninfo</groupId>
+            <artifactId>dcuc-common</artifactId>
+            <version>2.1.0-tjdsj-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 </project>

+ 22 - 0
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/audit/dto/warningrule/ExceptionIpRule.java

@@ -0,0 +1,22 @@
+package com.dragoninfo.dcuc.auth.audit.dto.warningrule;
+
+/**
+ * @Author: qiuyu
+ * @Date: 2021/5/18 14:23
+ * @Description: 异常事件鉴权预警
+ */
+public class ExceptionIpRule {
+
+    /**
+     * 受限制的ip段,多个使用,隔开
+     */
+    private String limitIp;
+
+    public String getLimitIp() {
+        return limitIp;
+    }
+
+    public void setLimitIp(String limitIp) {
+        this.limitIp = limitIp;
+    }
+}

+ 37 - 0
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/element/vo/ElementUserRelRespVo.java

@@ -0,0 +1,37 @@
+package com.dragoninfo.dcuc.auth.element.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author mazq
+ * @date 2022/8/25
+ */
+@Data
+@ApiModel(value = "环境要素-用户关联关系Vo")
+public class ElementUserRelRespVo {
+
+    @ApiModelProperty(value = "关联关系id")
+    private String id;
+
+    @ApiModelProperty(value = "人员id")
+    private String userId;
+
+    @ApiModelProperty(value = "环境要素id")
+    private String elementId;
+
+    @ApiModelProperty(value = "人员姓名")
+    private String userName;
+
+    @ApiModelProperty(value = "身份证号")
+    private String idcard;
+
+    @ApiModelProperty(value = "机构名称")
+    private String orgName;
+
+    @ApiModelProperty(value = "警号")
+    private String policeNumber;
+
+
+}

+ 27 - 0
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/element/vo/ElementUserSaveVo.java

@@ -0,0 +1,27 @@
+package com.dragoninfo.dcuc.auth.element.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * @author mazq
+ * @date 2023/7/5
+ */
+@Data
+@ApiModel(value = "环境要素-用户关联关系保存Vo")
+public class ElementUserSaveVo {
+
+    @NotBlank
+    @ApiModelProperty(value = "环境要素id")
+    private String elementId;
+
+    @NotNull
+    @ApiModelProperty(value = "新增人员id集合")
+    private List<String> userIds;
+
+}

+ 33 - 0
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/element/vo/EnvElementRespVo.java

@@ -0,0 +1,33 @@
+package com.dragoninfo.dcuc.auth.element.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author mazq
+ * @date 2022/8/25
+ */
+@Data
+@ApiModel(value = "环境要素Vo")
+public class EnvElementRespVo {
+
+    @ApiModelProperty(value = "id")
+    private String id;
+
+    @ApiModelProperty(value = "环境要素类型 码表值")
+    private String envElementType;
+
+    @ApiModelProperty(value = "环境要素名称")
+    private String envElementName;
+
+    @ApiModelProperty(value = "环境要素值")
+    private String envElementValue;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date createTime;
+}

+ 21 - 0
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/token/vo/TokenOnlineReqVo.java

@@ -0,0 +1,21 @@
+package com.dragoninfo.dcuc.auth.token.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author mazq
+ * @date 2023/6/21
+ */
+@Data
+@ApiModel("令牌在线查询Vo")
+public class TokenOnlineReqVo {
+
+    @ApiModelProperty(value = "用户令牌id")
+    private String userTokenId;
+
+    @ApiModelProperty(value = "应用令牌id")
+    private String appTokenId;
+    
+}

+ 21 - 0
dcuc-auth-model/src/main/java/com/dragoninfo/dcuc/auth/token/vo/TokenOnlineRespVo.java

@@ -0,0 +1,21 @@
+package com.dragoninfo.dcuc.auth.token.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author mazq
+ * @date 2023/6/21
+ */
+@Data
+@ApiModel("令牌在线查询结果")
+public class TokenOnlineRespVo {
+
+    @ApiModelProperty(value = "用户令牌是否在线")
+    private String userTokenOnline;
+
+    @ApiModelProperty(value = "应用令牌是否在线")
+    private String appTokenOnline;
+
+}

+ 2 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/audit/listener/AuthenticationLogListener.java

@@ -65,6 +65,8 @@ public class AuthenticationLogListener {
 
             detectLogService.checkUltraVires(authenticationLogDto);
 
+            detectLogService.checkExceptionIp(authenticationLogDto);
+
             pushService.pushAuthenticationLog(authenticationLogDto);
         } catch (Exception e) {
             logger.error("receiveMessage error.", e);

+ 111 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/audit/service/DetectLogService.java

@@ -1,6 +1,7 @@
 package com.dragoninfo.dcuc.auth.audit.service;
 
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSON;
 import com.dragoninfo.dcuc.auth.async.BusiEventPublisher;
 import com.dragoninfo.dcuc.auth.audit.dto.AuthenticationLogDto;
@@ -8,6 +9,7 @@ import com.dragoninfo.dcuc.auth.audit.dto.LogErrContentDto;
 import com.dragoninfo.dcuc.auth.audit.dto.RiskPushLogDto;
 import com.dragoninfo.dcuc.auth.audit.dto.riskrule.NamelistFrequentRule;
 import com.dragoninfo.dcuc.auth.audit.dto.riskrule.UltraViresContinuedRule;
+import com.dragoninfo.dcuc.auth.audit.dto.warningrule.ExceptionIpRule;
 import com.dragoninfo.dcuc.auth.audit.dto.warningrule.ExceptionTimeRule;
 import com.dragoninfo.dcuc.auth.audit.entity.*;
 import com.dragoninfo.dcuc.auth.audit.enums.AuthenticationNecessaryParamEnum;
@@ -18,6 +20,7 @@ import com.dragoninfo.dcuc.auth.audit.service.log.QmAuditPushService;
 import com.dragonsoft.duceap.base.enums.BooleanEnum;
 import com.dragonsoft.duceap.commons.util.date.DateConst;
 import com.dragonsoft.duceap.commons.util.date.DateUtils;
+import com.dragonsoft.duceap.commons.util.ip.IpUtils;
 import com.google.common.base.Joiner;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -261,4 +264,112 @@ public class DetectLogService {
         riskLogDto.setLogIds(logIds);
         busiEventPublisher.sendRiskInfoEvent(Collections.singletonList(riskLogDto));
     }
+
+    /**
+     * 用户异常IP鉴权预警
+     *
+     * @param logDto
+     */
+    public void checkExceptionIp(AuthenticationLogDto logDto) {
+        WarningProgramme warningProgramme = warningProgrammeService.findOneByType(WarningProgrammeTypeEnum.YHYCIPJQYJ.getValue());
+        if (warningProgramme == null) {
+            return;
+        }
+        String ruleContent = warningProgramme.getRuleContent();
+        if (com.dragonsoft.duceap.commons.util.string.StringUtils.isBlank(ruleContent)) {
+            return;
+        }
+        ExceptionIpRule rule = JSON.parseObject(ruleContent, ExceptionIpRule.class);
+        String limitIpRule = rule.getLimitIp();
+        logger.info("==================异常ip风险检测, 检测ip段:{}==============", limitIpRule);
+        if (com.dragonsoft.duceap.commons.util.string.StringUtils.isBlank(limitIpRule)) {
+            return;
+        }
+
+        // 检测是否在异常ip
+        String terminalId = logDto.getTerminalId();
+
+        // 限制规则匹配
+        boolean match = limitIpMatch(limitIpRule, terminalId);
+        logger.info("==================异常ip风险检测, 鉴权ip:{}===,IP段:{},匹配结果:{}===========", terminalId, limitIpRule, match);
+        // 不符合IP才发送风险
+        if (!match) {
+            WarningLog warningLog = new WarningLog();
+            warningLog.setCreater(logDto.getUserName());
+            warningLog.setCreaterId(logDto.getUserIdcard());
+            warningLog.setCreateTime(new Date());
+            warningLog.setProgrammeType(WarningProgrammeTypeEnum.YHYCIPJQYJ.getValue());
+            warningLog.setWarningMsg(warningProgramme.getContentFormat()
+                    .replaceAll("#主体#", logDto.getUserName())
+                    .replaceAll("#ip#", terminalId));
+            warningLogService.save(warningLog);
+
+            warningProgrammeService.incNumber(warningProgramme.getId());
+        }
+    }
+
+    protected boolean limitIpMatch(String limitIpRule, String terminalId) {
+        if (!IpUtils.checkIP(terminalId)) {
+            return false;
+        }
+        String[] split = limitIpRule.split(StrUtil.COMMA);
+        for (String s : split) {
+            if (ipV4Match(s, terminalId)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected boolean ipV4Match(String limitIp, String requestIp) {
+        String[] limit = limitIp.split("\\.");
+        String[] request = requestIp.split("\\.");
+        for (int i = 0; i < limit.length; i++) {
+            String limitSector = limit[i];
+            String reqSector = request[i];
+            if ("*".equals(limitSector)) {
+                continue;
+            }
+            if (limitSector.contains(StrUtil.DASHED)) {
+                if (!sectorMatch(limitSector, reqSector)) {
+                    return false;
+                }
+            } else {
+                if (!singleCharMatch(limitSector, reqSector)) {
+                    return false;
+                }
+            }
+
+        }
+
+        return true;
+    }
+
+    private boolean sectorMatch(String limitSector, String reqSector) {
+        String[] split = limitSector.split(StrUtil.DASHED);
+        int start = Integer.parseInt(split[0]);
+        int end = Integer.parseInt(split[1]);
+        int integer = Integer.parseInt(reqSector);
+        return start <= integer && end >= integer;
+    }
+
+    /**
+     * 单字符匹配
+     *
+     * @param limitSector
+     * @param reqSector
+     * @return 不匹配返回false
+     */
+    private boolean singleCharMatch(String limitSector, String reqSector) {
+        if (limitSector.length() != reqSector.length()) {
+            return false;
+        }
+        for (int i1 = 0; i1 < limitSector.length(); i1++) {
+            char lc = limitSector.charAt(i1);
+            if (lc != '*' && lc != reqSector.charAt(i1)) {
+                return false;
+            }
+        }
+        return true;
+    }
 }

+ 29 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/impl/zerotrust/AuthTokenBusinessImpl.java

@@ -1,6 +1,7 @@
 package com.dragoninfo.dcuc.auth.business.impl.zerotrust;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.dragoninfo.dcuc.app.entity.ApplyInfo;
 import com.dragoninfo.dcuc.app.facade.IApplyInfoFacade;
 import com.dragoninfo.dcuc.auth.api.enums.zerotrust.ZeroTrustBusinessRespEnum;
@@ -20,6 +21,7 @@ import com.dragoninfo.dcuc.auth.sub.vo.ApplyInfoVo;
 import com.dragoninfo.dcuc.auth.sub.vo.AuthUserVo;
 import com.dragoninfo.dcuc.auth.token.enums.TokenActionEnum;
 import com.dragoninfo.dcuc.auth.token.vo.*;
+import com.dragoninfo.duceap.core.response.Result;
 import com.dragonsoft.auditlog.collection.qmtj.enums.TokenTypeEnum;
 import com.dragonsoft.duceap.commons.util.string.StringUtils;
 import com.dragonsoft.smtools.loader.SMFactory;
@@ -199,6 +201,32 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
         return ZeroTrustMessageRespVO.messageEnumMessage(ZeroTrustBusinessRespEnum.SUCCESS);
     }
 
+
+    @Override
+    public Result<TokenOnlineRespVo> tokenOnlineQuery(TokenOnlineReqVo reqVo) {
+        TokenOnlineRespVo respVo = new TokenOnlineRespVo();
+        String userTokenId = reqVo.getUserTokenId();
+        String appTokenId = reqVo.getAppTokenId();
+        if (StringUtils.isNotBlank(userTokenId)) {
+            UserTokenInfoRespVO userToken = cacheBusiness.getUserToken(userTokenId);
+            if (null != userToken) {
+                respVo.setUserTokenOnline(TokenActionEnum.ONLINE.getLabel());
+            } else {
+                respVo.setUserTokenOnline(TokenActionEnum.OFFLINE.getLabel());
+            }
+        }
+        if (StringUtils.isNotBlank(appTokenId)) {
+            AppTokenInfoRespVO appToken = cacheBusiness.getAppToken(appTokenId);
+            if (null != appToken) {
+                respVo.setAppTokenOnline(TokenActionEnum.ONLINE.getLabel());
+            } else {
+                respVo.setAppTokenOnline(TokenActionEnum.OFFLINE.getLabel());
+            }
+        }
+        return Result.success(respVo);
+    }
+
+
     /**
      * 生成令牌通知签名
      *
@@ -219,6 +247,7 @@ public class AuthTokenBusinessImpl implements IAuthTokenBusiness {
 
 
 
+
     private AuthUserVo getAuthUserVo(String pid) {
         // pid为人员身份证号
         // 查询权限中心用户信息, 填充id字段

+ 7 - 2
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/business/zerotrust/IAuthTokenBusiness.java

@@ -1,8 +1,6 @@
 package com.dragoninfo.dcuc.auth.business.zerotrust;
 
-import com.dragoninfo.dcuc.auth.api.vo.securitypolicy.req.AuthRiskOrderReqVo;
 import com.dragoninfo.dcuc.auth.api.vo.zerotrust.ZeroTrustMessageRespVO;
-import com.dragoninfo.dcuc.auth.api.vo.zerotrust.ZeroTrustSignReqVO;
 import com.dragoninfo.dcuc.auth.token.vo.AppTokenInfoRespVO;
 import com.dragoninfo.dcuc.auth.token.vo.TokenDetailRespVo;
 import com.dragoninfo.dcuc.auth.token.vo.TokenReceiveVO;
@@ -47,4 +45,11 @@ public interface IAuthTokenBusiness {
      * @return
      */
     ZeroTrustMessageRespVO tokenReceive(TokenReceiveVO receiveVO);
+
+    /**
+     * 令牌在线查询
+     * @param reqVo
+     * @return
+     */
+    Result<TokenOnlineRespVo> tokenOnlineQuery(TokenOnlineReqVo reqVo);
 }

+ 34 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/business/IEnvElementBusiness.java

@@ -1,11 +1,17 @@
 package com.dragoninfo.dcuc.auth.element.business;
 
+import com.dragoninfo.dcuc.auth.element.vo.ElementUserRelRespVo;
+import com.dragoninfo.dcuc.auth.element.vo.ElementUserSaveVo;
 import com.dragoninfo.dcuc.auth.element.vo.EnvElementSaveVo;
 import com.dragoninfo.dcuc.auth.element.vo.RespEnvElementVo;
+import com.dragoninfo.dcuc.auth.sub.vo.AuthUserVo;
+import com.dragoninfo.duceap.core.response.Result;
 import com.dragonsoft.duceap.base.entity.http.ResponseStatus;
 import com.dragonsoft.duceap.base.entity.search.SearchDTO;
 import org.springframework.data.domain.Page;
 
+import java.util.List;
+
 /**
  * @author mazq
  * @date 2022/8/25
@@ -21,4 +27,32 @@ public interface IEnvElementBusiness {
     ResponseStatus update(EnvElementSaveVo envElementVo);
 
     ResponseStatus deleteById(String id);
+
+    /**
+     * 关联用户分页查询
+     * @param searchDTO
+     * @return
+     */
+    Result<List<ElementUserRelRespVo>> userRelPage(SearchDTO searchDTO);
+
+    /**
+     * 保存用户关联关系
+     * @param relSaveVo
+     * @return
+     */
+    Result<Object> userRelSave(ElementUserSaveVo relSaveVo);
+
+    /**
+     * 删除用户关联关系
+     * @param id
+     * @return
+     */
+    Result<Object> deleteUserRel(String id);
+
+    /**
+     * 非关联用户查询
+     * @param searchDTO
+     * @return
+     */
+    Result<List<AuthUserVo>> notInUserRelPage(SearchDTO searchDTO);
 }

+ 149 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/business/impl/EnvElementBusiness.java

@@ -1,13 +1,27 @@
 package com.dragoninfo.dcuc.auth.element.business.impl;
 
 import com.dragoninfo.dcuc.auth.element.business.IEnvElementBusiness;
+import com.dragoninfo.dcuc.auth.element.entity.ElementUserRel;
 import com.dragoninfo.dcuc.auth.element.entity.EnvElement;
+import com.dragoninfo.dcuc.auth.element.service.IElementUserRelService;
 import com.dragoninfo.dcuc.auth.element.service.IEnvElementService;
+import com.dragoninfo.dcuc.auth.element.vo.ElementUserRelRespVo;
+import com.dragoninfo.dcuc.auth.element.vo.ElementUserSaveVo;
 import com.dragoninfo.dcuc.auth.element.vo.EnvElementSaveVo;
 import com.dragoninfo.dcuc.auth.element.vo.RespEnvElementVo;
+import com.dragoninfo.dcuc.auth.sub.entity.AuthUserInfo;
+import com.dragoninfo.dcuc.auth.sub.service.IAuthUserInfoService;
+import com.dragoninfo.dcuc.auth.sub.vo.AuthUserVo;
+import com.dragoninfo.dcuc.common.utils.DcucBeanUtil;
+import com.dragoninfo.duceap.core.enums.ResultEnum;
+import com.dragoninfo.duceap.core.response.Result;
 import com.dragonsoft.duceap.base.entity.http.ResponseStatus;
 import com.dragonsoft.duceap.base.entity.search.SearchDTO;
+import com.dragonsoft.duceap.base.enums.BooleanEnum;
+import com.dragonsoft.duceap.commons.util.collections.CollectionUtils;
 import com.dragonsoft.duceap.core.search.Searchable;
+import com.dragonsoft.duceap.core.search.enums.SearchOperator;
+import com.dragonsoft.duceap.core.search.filter.Condition;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
@@ -18,6 +32,7 @@ import org.springframework.stereotype.Service;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -30,6 +45,12 @@ public class EnvElementBusiness implements IEnvElementBusiness {
     @Autowired
     private IEnvElementService envElementService;
 
+    @Autowired
+    private IElementUserRelService elementUserRelService;
+
+    @Autowired
+    private IAuthUserInfoService userInfoService;
+
     @Override
     public RespEnvElementVo getById(String id) {
         EnvElement envElement = envElementService.getById(id);
@@ -82,4 +103,132 @@ public class EnvElementBusiness implements IEnvElementBusiness {
         envElementService.deleted(id);
         return ResponseStatus.success();
     }
+
+
+    @Override
+    public Result<List<ElementUserRelRespVo>> userRelPage(SearchDTO searchDTO) {
+        Searchable searchable = Searchable.toSearchable(searchDTO);
+        Condition elementIdCondition = searchable.getSearchFilter("elementId", SearchOperator.eq);
+        if (null == elementIdCondition) {
+            return Result.failMessage("请选择环境要素");
+        }
+
+        // 暂时没有用户查询条件
+        List<AuthUserInfo> userInfos = null;
+//        List<AuthUserInfo> userInfos = getSearchUsers(searchable);
+//        if (userInfos != null && userInfos.isEmpty()) {
+//            return Result.success(0L, Collections.emptyList());
+//        }
+        String elementId = elementIdCondition.getValue().toString();
+        Page<ElementUserRel> elementUserRels = getElementUserRels(searchable, elementId, userInfos);
+        if (elementUserRels.isEmpty()) {
+            return Result.success(0L, Collections.emptyList());
+        }
+        // 用户查询为空再次查询用户
+        if (null == userInfos) {
+            List<String> userIds = elementUserRels.getContent()
+                    .stream()
+                    .map(ElementUserRel::getUserId)
+                    .distinct()
+                    .collect(Collectors.toList());
+            userInfos = userInfoService.findByIds(userIds);
+            if (CollectionUtils.isEmpty(userInfos)) {
+                return Result.success(0L, Collections.emptyList());
+            }
+        }
+        return getPageVos(elementUserRels, userInfos);
+    }
+
+    @Override
+    public Result<Object> userRelSave(ElementUserSaveVo relSaveVo) {
+        List<String> userIds = relSaveVo.getUserIds();
+        if (CollectionUtils.isEmpty(userIds)) {
+            return Result.success();
+        }
+        String elementId = relSaveVo.getElementId();
+        List<ElementUserRel> collect = userIds.stream()
+                .map(e -> {
+                    ElementUserRel userRel = new ElementUserRel();
+                    userRel.setElementId(elementId);
+                    userRel.setUserId(e);
+                    userRel.setDeleted(BooleanEnum.FALSE.value);
+                    return userRel;
+                }).collect(Collectors.toList());
+        elementUserRelService.batchSave(collect);
+        return Result.success();
+    }
+
+    @Override
+    public Result<Object> deleteUserRel(String id) {
+        elementUserRelService.deleteById(id);
+        return Result.success();
+    }
+
+    @Override
+    public Result<List<AuthUserVo>> notInUserRelPage(SearchDTO searchDTO) {
+        Searchable searchable = Searchable.toSearchable(searchDTO);
+        Condition elementIdCondition = searchable.getSearchFilter("elementId", SearchOperator.eq);
+        if (null == elementIdCondition) {
+            return Result.failMessage("请选择环境要素");
+        }
+        searchable.removeSearchFilter("elementId", SearchOperator.eq);
+        String elementId = elementIdCondition.getValue().toString();
+        // 查询关联人员的id
+        List<String> userIds = elementUserRelService.getUserIdByElementId(elementId);
+        if (CollectionUtils.isNotEmpty(userIds)) {
+            searchable.addSearchFilter("id", SearchOperator.notIn, userIds);
+        }
+        Page<AuthUserInfo> page = userInfoService.page(searchable);
+        Page<AuthUserVo> copy = DcucBeanUtil.createCopyToObjectPage(page, AuthUserVo.class);
+        return new Result(ResultEnum.SUCCESS.getKey(), ResultEnum.SUCCESS.getValue(), copy.getTotalElements(),copy.getContent());
+    }
+
+    private Page<ElementUserRel> getElementUserRels(Searchable searchable, String elementId, List<AuthUserInfo> userInfos) {
+        Searchable relSearch = Searchable.newSearchable();
+        relSearch.addSort(Sort.Direction.DESC, "createTime");
+        relSearch.addSearchFilter("elementId", SearchOperator.eq, elementId);
+        relSearch.setPage(searchable.getPage());
+        if (userInfos != null) {
+            List<String> userIds = userInfos.stream()
+                    .map(AuthUserInfo::getId)
+                    .distinct()
+                    .collect(Collectors.toList());
+            relSearch.addSearchFilter("userId", SearchOperator.in, userIds);
+        }
+        return elementUserRelService.pageSearch(relSearch);
+    }
+
+    private Result<List<ElementUserRelRespVo>> getPageVos(Page<ElementUserRel> userRelPage, List<AuthUserInfo> userInfos) {
+        Map<String, AuthUserInfo> userInfoMap = userInfos
+                .stream()
+                .collect(Collectors.toMap(AuthUserInfo::getId, e -> e));
+        List<ElementUserRelRespVo> collect = userRelPage.stream()
+                .map(e -> {
+                    ElementUserRelRespVo vo = new ElementUserRelRespVo();
+                    BeanUtils.copyProperties(e, vo);
+                    String userId = e.getUserId();
+                    AuthUserInfo authUserInfo = userInfoMap.get(userId);
+                    if (null != authUserInfo) {
+                        vo.setIdcard(authUserInfo.getIdcard());
+                        vo.setUserName(authUserInfo.getName());
+                        vo.setOrgName(authUserInfo.getOrgName());
+                        vo.setPoliceNumber(authUserInfo.getPoliceNumber());
+                    }
+                    return vo;
+                }).collect(Collectors.toList());
+        return Result.success(userRelPage.getTotalElements(), collect);
+    }
+
+    /**
+     * 返回null表示不查询
+     * 返回空集合表示查询结果为空
+     *
+     * @param searchable
+     * @return
+     */
+    private List<AuthUserInfo> getSearchUsers(Searchable searchable) {
+        searchable.removeSearchFilter("elementId", SearchOperator.eq);
+        return null;
+    }
+
 }

+ 71 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/entity/ElementUserRel.java

@@ -0,0 +1,71 @@
+package com.dragoninfo.dcuc.auth.element.entity;
+
+import com.dragonsoft.duceap.base.annotations.audit.DeletedBy;
+import com.dragonsoft.duceap.base.annotations.audit.DeletedDate;
+import com.dragonsoft.duceap.core.persistent.audit.JpaAuditingEntityListener;
+import lombok.Data;
+import org.hibernate.annotations.GenericGenerator;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+
+import javax.persistence.*;
+import java.util.Date;
+
+/**
+ * @author mazq
+ * @date 2022/8/25
+ */
+@EntityListeners({JpaAuditingEntityListener.class})
+@Data
+@Entity
+@Table(name = "T_AUTH_ELEMENT_USER_REL")
+public class ElementUserRel{
+
+    /**
+     * ID
+     */
+    @Id
+    @GeneratedValue(generator="idGenerator")
+    @GenericGenerator(name="idGenerator", strategy="uuid")
+    @Column(name = "ID")
+    private String id;
+
+    /**
+     * 环境要素id
+     */
+    @Column(name = "ELEMENT_ID")
+    private String elementId;
+
+    /**
+     * 人员id
+     */
+    @Column(name = "USER_ID")
+    private String userId;
+
+    /** 创建人 */
+    @CreatedBy
+    @Column(name = "CREATE_USER")
+    private String createUser;
+
+    /** 创建时间 */
+    @CreatedDate
+    @Column(name = "CREATE_TIME")
+    private Date createTime;
+
+    /**
+     * 是否删除
+     */
+    @Column(name = "DELETED")
+    private String deleted = "0";
+
+    /** 删除人 */
+    @DeletedBy
+    @Column(name = "DELETE_USER")
+    private String deleteUser;
+
+    /** 删除时间 */
+    @DeletedDate
+    @Column(name = "DELETE_TIME")
+    private Date deleteTime;
+
+}

+ 27 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/facade/EnvElementFacade.java

@@ -1,8 +1,12 @@
 package com.dragoninfo.dcuc.auth.element.facade;
 
 import com.dragoninfo.dcuc.auth.element.business.IEnvElementBusiness;
+import com.dragoninfo.dcuc.auth.element.vo.ElementUserRelRespVo;
+import com.dragoninfo.dcuc.auth.element.vo.ElementUserSaveVo;
 import com.dragoninfo.dcuc.auth.element.vo.EnvElementSaveVo;
 import com.dragoninfo.dcuc.auth.element.vo.RespEnvElementVo;
+import com.dragoninfo.dcuc.auth.sub.vo.AuthUserVo;
+import com.dragoninfo.duceap.core.response.Result;
 import com.dragonsoft.duceap.base.entity.http.ResponseStatus;
 import com.dragonsoft.duceap.base.entity.search.SearchDTO;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -10,6 +14,8 @@ import org.springframework.data.domain.Page;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 /**
  * @author mazq
  * @date 2022/8/25
@@ -45,4 +51,25 @@ public class EnvElementFacade implements IEnvElementFacade {
     public ResponseStatus deleteById(String id) {
         return envElementBusiness.deleteById(id);
     }
+
+
+    @Override
+    public Result<List<ElementUserRelRespVo>> userRelPage(SearchDTO searchDTO) {
+        return envElementBusiness.userRelPage(searchDTO);
+    }
+
+    @Override
+    public Result<Object> userRelSave(ElementUserSaveVo relSaveVo) {
+        return envElementBusiness.userRelSave(relSaveVo);
+    }
+
+    @Override
+    public Result<Object> deleteUserRel(String id) {
+        return envElementBusiness.deleteUserRel(id);
+    }
+
+    @Override
+    public Result<List<AuthUserVo>> notInUserRelPage(SearchDTO searchDTO) {
+        return envElementBusiness.notInUserRelPage(searchDTO);
+    }
 }

+ 23 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/repo/EnvElementUserRelRepository.java

@@ -0,0 +1,23 @@
+package com.dragoninfo.dcuc.auth.element.repo;
+
+import com.dragoninfo.dcuc.auth.element.entity.ElementUserRel;
+import com.dragonsoft.duceap.core.persistent.repository.BaseRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * @author mazq
+ * @date 2022/8/25
+ */
+@Repository
+public interface EnvElementUserRelRepository extends BaseRepository<ElementUserRel,String> {
+
+    void deleteByElementId(String elementId);
+
+    @Query("from ElementUserRel  where elementId=:elementId ")
+    List<ElementUserRel> getUserIdByElementId(@Param("elementId") String elementId);
+
+}

+ 47 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/service/IElementUserRelService.java

@@ -0,0 +1,47 @@
+package com.dragoninfo.dcuc.auth.element.service;
+
+import com.dragoninfo.dcuc.auth.element.entity.ElementUserRel;
+import com.dragonsoft.duceap.core.search.Searchable;
+import org.springframework.data.domain.Page;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author mazq
+ * @date 2022/8/25
+ */
+public interface IElementUserRelService {
+
+    /**
+     * 批量添加环境要素-用户关联关系
+     * @param collections
+     */
+    void batchSave(Collection<ElementUserRel> collections);
+
+    /**
+     * 根据id删除
+     * @param id
+     */
+    void deleteById(String id);
+
+    /**
+     * 分页查询
+     * @param searchable
+     * @return
+     */
+    Page<ElementUserRel> pageSearch(Searchable searchable);
+
+    /**
+     * 根据环境要素id删除
+     * @param elementId
+     */
+    void deleteByElementId(String elementId);
+
+    /**
+     * 根据环境要素id查询关联的用户id
+     * @param elementId
+     * @return
+     */
+    List<String> getUserIdByElementId(String elementId);
+}

+ 57 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/element/service/impl/EnvElemenUserRelServiceImpl.java

@@ -0,0 +1,57 @@
+package com.dragoninfo.dcuc.auth.element.service.impl;
+
+import com.dragoninfo.dcuc.auth.element.entity.ElementUserRel;
+import com.dragoninfo.dcuc.auth.element.entity.EnvElement;
+import com.dragoninfo.dcuc.auth.element.repo.EnvElementRepository;
+import com.dragoninfo.dcuc.auth.element.repo.EnvElementUserRelRepository;
+import com.dragoninfo.dcuc.auth.element.service.IElementUserRelService;
+import com.dragoninfo.dcuc.auth.element.service.IEnvElementService;
+import com.dragonsoft.duceap.core.search.Searchable;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author mazq
+ * @date 2022/8/25
+ */
+@Service
+public class EnvElemenUserRelServiceImpl implements IElementUserRelService {
+
+    @Autowired
+    private EnvElementUserRelRepository repository;
+
+    @Override
+    public void batchSave(Collection<ElementUserRel> collections) {
+        repository.saveAll(collections);
+    }
+
+    @Override
+    public void deleteById(String id) {
+        if (StringUtils.isBlank(id)) {
+            return;
+        }
+        repository.deleteById(id);
+    }
+
+    @Override
+    public Page<ElementUserRel> pageSearch(Searchable searchable) {
+        return repository.paging(searchable);
+    }
+
+    @Override
+    public void deleteByElementId(String elementId) {
+        repository.deleteByElementId(elementId);
+    }
+
+    @Override
+    public List<String> getUserIdByElementId(String elementId) {
+        return repository.getUserIdByElementId(elementId)
+                .stream().map(ElementUserRel::getUserId).collect(Collectors.toList());
+    }
+}

+ 7 - 0
dcuc-auth-service/src/main/java/com/dragoninfo/dcuc/auth/token/facade/AuthTokenFacade.java

@@ -3,6 +3,7 @@ package com.dragoninfo.dcuc.auth.token.facade;
 import com.dragoninfo.dcuc.auth.api.vo.zerotrust.ZeroTrustMessageRespVO;
 import com.dragoninfo.dcuc.auth.business.zerotrust.IAuthTokenBusiness;
 import com.dragoninfo.dcuc.auth.token.vo.TokenReceiveVO;
+import com.dragoninfo.duceap.core.response.Result;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -26,4 +27,10 @@ public class AuthTokenFacade implements IAuthTokenFacade {
     public ZeroTrustMessageRespVO tokenReceive(TokenReceiveVO receiveVO) {
         return tokenBusiness.tokenReceive(receiveVO);
     }
+
+    @Override
+    public Result<TokenOnlineRespVo> tokenOnlineQuery(TokenOnlineReqVo reqVo) {
+        return tokenBusiness.tokenOnlineQuery(reqVo);
+    }
+
 }

+ 59 - 0
dcuc-auth-service/src/main/resources/config/mysql/V4_3_0031__UpdateEnvment.sql

@@ -0,0 +1,59 @@
+alter table t_auth_env_ele
+    add ENV_ELEMENT_VALUE varchar(256) null comment '环境要素值';
+
+create table T_AUTH_ELEMENT_USER_REL
+(
+    ID          varchar(32)            not null comment '主键',
+    ELEMENT_ID  varchar(32)            null comment '环境要素id',
+    USER_ID     varchar(32)            null comment '人员id',
+    CREATE_USER varchar(32)            null comment '创建人',
+    CREATE_TIME datetime               null comment '创建时间',
+    DELETED     varchar(5) default '0' null comment '是否删除',
+    DELETE_USER varchar(32)            null comment '删除人',
+    DELETE_TIME datetime               null comment '删除时间',
+    constraint T_AUTH_ELEMENT_USER_REL_pk
+        primary key (ID)
+)
+    comment '环境要素关联关系表';
+
+create index T_AUTH_ELEMENT_USER_REL_ELEMENT_ID_USER_ID_index
+    on T_AUTH_ELEMENT_USER_REL (ELEMENT_ID, USER_ID);
+
+
+CREATE TABLE `DM_WARNING_PROGRAMME_TYPE`
+(
+    `CODE`  varchar(32) NOT NULL,
+    `VALUE` varchar(32) NOT NULL,
+    PRIMARY KEY (`CODE`)
+) COMMENT ='预警类型';
+
+INSERT INTO `DM_WARNING_PROGRAMME_TYPE`(`CODE`, `VALUE`)
+VALUES ('YHYCSJJQYJ', '用户异常时间鉴权预警');
+INSERT INTO `DM_WARNING_PROGRAMME_TYPE`(`CODE`, `VALUE`)
+VALUES ('YHYCIPJQYJ', '用户异常IP鉴权预警');
+
+INSERT INTO `T_MD_SYS_CODE_DIC`(`CODE_ID`, `NAME`, `ENTITY_NAME`, `CODE_FIELD`, `NAME_FIELD`, `LOAD_TYPE`)
+VALUES ('DM_WARNING_PROGRAMME_TYPE', '预警类型', 'DM_WARNING_PROGRAMME_TYPE', 'CODE', 'VALUE', '1');
+
+UPDATE t_audit_warning_programme
+SET rule_content   = '{"limitIp":""}',
+    rule_explain   = '用户鉴权的IP处于被限制的ip段内',
+    content_format = '#主体#鉴权时,使用IP是:#ip#,处于被限制的ip段内。'
+WHERE type = 'YHYCIPJQYJ';
+
+INSERT INTO `t_md_sys_code_dic`(`code_id`, `datasource_id`, `name`, `entity_name`, `code_field`, `name_field`,
+                                `py_field`, `wb_field`, `order_field`, `segment_rule`, `view_sql`, `load_type`,
+                                `parent_code_field`)
+VALUES ('DM_ACTIVE_STATUS', NULL, '起停用状态', 'DM_ACTIVE_STATUS', 'CODE', 'VALUE', NULL, NULL, NULL, NULL, NULL,
+        '1', NULL);
+
+CREATE TABLE `DM_ACTIVE_STATUS`
+(
+    `CODE`  varchar(10) NOT NULL,
+    `VALUE` varchar(20) NOT NULL,
+    PRIMARY KEY (`CODE`)
+);
+INSERT INTO DM_ACTIVE_STATUS(CODE, VALUE)
+VALUES ('0', '停用');
+INSERT INTO DM_ACTIVE_STATUS(CODE, VALUE)
+VALUES ('1', '启用');