From e59811ced432e59153e2754f6a1e5cca76c2696a Mon Sep 17 00:00:00 2001 From: liulu Date: Mon, 28 Oct 2024 09:55:21 +0800 Subject: [PATCH] init web --- .gitignore | 26 + chsm-common/pom.xml | 44 + .../com/sunyard/utils/DateFormatPattern.java | 35 + .../java/com/sunyard/utils/JsonUtils.java | 97 +++ .../com/sunyard/utils/ThrowableUtils.java | 41 + chsm-model/pom.xml | 20 + chsm-web-manage/pom.xml | 144 ++++ .../main/java/com/sunyard/WebManageApp.java | 22 + .../java/com/sunyard/config/CorsFilter.java | 37 + .../java/com/sunyard/config/WebConfig.java | 66 ++ .../config/security/CaptchaProperties.java | 25 + .../security/IgnoredUrlsProperties.java | 19 + .../config/security/SM3PasswordEncoder.java | 66 ++ .../config/security/SecurityUserDetails.java | 98 +++ .../security/UserDetailsServiceImpl.java | 76 ++ .../config/security/WebSecurityConfig.java | 119 +++ .../jwt/AuthenticationFailHandler.java | 114 +++ .../jwt/AuthenticationSuccessHandler.java | 144 ++++ .../security/jwt/JWTAuthenticationFilter.java | 163 ++++ .../security/jwt/RestAccessDeniedHandler.java | 29 + .../permission/MyAccessDecisionManager.java | 54 ++ .../MyFilterSecurityInterceptor.java | 73 ++ .../security/permission/MyRequestVo.java | 44 + .../permission/MySecurityMetadataSource.java | 121 +++ .../validate/ImageValidateFilter.java | 83 ++ .../java/com/sunyard/ssp/common/PageVo.java | 43 + .../java/com/sunyard/ssp/common/Result.java | 41 + .../common/annotation/AuditControllerLog.java | 20 + .../common/constant/CertificateConstant.java | 18 + .../ssp/common/constant/ChannelConstant.java | 52 ++ .../constant/ChannelSolutionConstant.java | 10 + .../ssp/common/constant/CommonConstant.java | 227 +++++ .../ssp/common/constant/DeviceConstant.java | 21 + .../constant/DeviceGroupRefConstant.java | 19 + .../ssp/common/constant/DictDataConstant.java | 10 + .../ssp/common/constant/FileConstant.java | 11 + .../common/constant/KeyAttributeConstant.java | 46 ++ .../ssp/common/constant/KeyConstant.java | 16 + .../common/constant/KeySolutionConstant.java | 33 + .../ssp/common/constant/NodeConstant.java | 16 + .../common/constant/ParamConfKeyConstant.java | 124 +++ .../ssp/common/constant/ProtocolConstant.java | 22 + .../ssp/common/constant/RegexConstant.java | 96 +++ .../ssp/common/constant/SdkConstant.java | 86 ++ .../ssp/common/constant/SecurityConstant.java | 78 ++ .../ssp/common/constant/SqlConstant.java | 19 + .../common/constant/SspServerConstant.java | 9 + .../common/constant/ValidatorConstant.java | 15 + .../ssp/common/constant/WorkflowConstant.java | 50 ++ .../ssp/common/enums/UserHeaderTypeEnum.java | 52 ++ .../exception/GlobalExceptionResolver.java | 96 +++ .../exception/LoginFailLimitException.java | 23 + .../ssp/common/exception/SspwebException.java | 19 + .../com/sunyard/ssp/common/vo/Captcha.java | 19 + .../sunyard/ssp/config/ServerConfigure.java | 29 + .../monitor/log/aspect/AuditLogAspect.java | 244 ++++++ .../log/controller/AuditLogController.java | 165 ++++ .../log/controller/LogDownloadController.java | 42 + .../log/controller/LogSignController.java | 140 ++++ .../log/controller/SysLogController.java | 76 ++ .../modules/monitor/log/entity/AuditLog.java | 98 +++ .../monitor/log/entity/AuditLogSign.java | 35 + .../modules/monitor/log/entity/LogSign.java | 64 ++ .../modules/monitor/log/entity/SysLog.java | 69 ++ .../monitor/log/mapper/AuditLogMapper.java | 197 +++++ .../log/mapper/AuditLogSignMapper.java | 16 + .../monitor/log/mapper/LogSignMapper.java | 16 + .../monitor/log/mapper/SysLogMapper.java | 47 ++ .../monitor/log/service/IAuditLogService.java | 113 +++ .../log/service/IAuditLogSignService.java | 12 + .../monitor/log/service/ILogSignService.java | 17 + .../monitor/log/service/ISysLogService.java | 33 + .../log/service/LogDownloadService.java | 10 + .../log/serviceimpl/AuditLogServiceImpl.java | 183 ++++ .../serviceimpl/AuditLogSignServiceImpl.java | 20 + .../serviceimpl/LogDownloadServiceImpl.java | 83 ++ .../log/serviceimpl/LogSignServiceImpl.java | 78 ++ .../log/serviceimpl/SysLogServiceImpl.java | 46 ++ .../modules/sdk/ASymmetricKeyToolService.java | 114 +++ .../sunyard/ssp/modules/sdk/CertService.java | 48 ++ .../ssp/modules/sdk/KeyLifecycleService.java | 84 ++ .../ssp/modules/sdk/SdkApiService.java | 9 + .../ssp/modules/sdk/SdkApiServiceImpl.java | 642 ++++++++++++++ .../modules/sdk/SymmetricKeyToolService.java | 151 ++++ .../controller/ParamConfController.java | 99 +++ .../sysconf/paramconf/entity/ParamConf.java | 66 ++ .../paramconf/mapper/ParamConfMapper.java | 32 + .../paramconf/service/IParamConfService.java | 45 + .../serviceimpl/ParamConfServiceImpl.java | 191 +++++ .../controller/ScDepartmentController.java | 263 ++++++ .../ScDepartmentHeaderController.java | 96 +++ .../controller/ScPermissionController.java | 421 ++++++++++ .../user/controller/ScPositionController.java | 140 ++++ .../user/controller/ScRoleController.java | 214 +++++ .../ScRoleDepartmentController.java | 96 +++ .../ScRolePermissionController.java | 96 +++ .../user/controller/ScUShieldController.java | 433 ++++++++++ .../user/controller/ScUserController.java | 781 ++++++++++++++++++ .../user/controller/ScUserRoleController.java | 96 +++ .../ssp/modules/user/entity/ScDepartment.java | 70 ++ .../user/entity/ScDepartmentHeader.java | 41 + .../ssp/modules/user/entity/ScPermission.java | 104 +++ .../ssp/modules/user/entity/ScPosition.java | 42 + .../ssp/modules/user/entity/ScRole.java | 61 ++ .../modules/user/entity/ScRoleDepartment.java | 35 + .../modules/user/entity/ScRolePermission.java | 37 + .../ssp/modules/user/entity/ScUser.java | 135 +++ .../ssp/modules/user/entity/ScUserRole.java | 37 + .../ssp/modules/user/entity/ULoginDto.java | 28 + .../modules/user/entity/UkeyLoginParm.java | 28 + .../user/mapper/ScDepartmentHeaderMapper.java | 16 + .../user/mapper/ScDepartmentMapper.java | 16 + .../user/mapper/ScPermissionMapper.java | 27 + .../modules/user/mapper/ScPositionMapper.java | 17 + .../user/mapper/ScRoleDepartmentMapper.java | 16 + .../ssp/modules/user/mapper/ScRoleMapper.java | 16 + .../user/mapper/ScRolePermissionMapper.java | 16 + .../ssp/modules/user/mapper/ScUserMapper.java | 25 + .../modules/user/mapper/ScUserRoleMapper.java | 23 + .../service/IScDepartmentHeaderService.java | 17 + .../user/service/IScDepartmentService.java | 41 + .../user/service/IScPermissionService.java | 36 + .../user/service/IScPositionService.java | 16 + .../service/IScRoleDepartmentService.java | 16 + .../service/IScRolePermissionService.java | 16 + .../modules/user/service/IScRoleService.java | 20 + .../user/service/IScUserRoleService.java | 22 + .../modules/user/service/IScUserService.java | 25 + .../ScDepartmentHeaderServiceImpl.java | 41 + .../serviceimpl/ScDepartmentServiceImpl.java | 72 ++ .../serviceimpl/ScPermissionServiceImpl.java | 93 +++ .../serviceimpl/ScPositionServiceImpl.java | 24 + .../ScRoleDepartmentServiceImpl.java | 24 + .../ScRolePermissionServiceImpl.java | 24 + .../user/serviceimpl/ScRoleServiceImpl.java | 43 + .../serviceimpl/ScUserRoleServiceImpl.java | 42 + .../user/serviceimpl/ScUserServiceImpl.java | 157 ++++ .../user/serviceimpl/SdkApiServiceFImpl.java | 4 + .../utils/validator/DepartmentValidator.java | 63 ++ .../utils/validator/PermissionValidator.java | 87 ++ .../utils/validator/PositionValidator.java | 65 ++ .../user/utils/validator/RoleValidator.java | 63 ++ .../user/utils/validator/UserValidator.java | 82 ++ .../sunyard/ssp/redis/JedisClusterConfig.java | 188 +++++ .../com/sunyard/ssp/redis/RedisConfig.java | 84 ++ .../ssp/redis/RedisObjectOperation.java | 468 +++++++++++ .../com/sunyard/ssp/redis/RedisOperation.java | 72 ++ .../java/com/sunyard/ssp/server/Config.java | 167 ++++ .../com/sunyard/ssp/server/Messenger.java | 433 ++++++++++ .../java/com/sunyard/ssp/server/Redis.java | 288 +++++++ .../com/sunyard/ssp/server/ServerTest.java | 223 +++++ .../com/sunyard/ssp/server/VOChannel.java | 18 + .../java/com/sunyard/ssp/utils/CaUtil.java | 370 +++++++++ .../com/sunyard/ssp/utils/ClazzUtils.java | 144 ++++ .../com/sunyard/ssp/utils/CommonUtil.java | 47 ++ .../sunyard/ssp/utils/CreateVerifyCode.java | 314 +++++++ .../java/com/sunyard/ssp/utils/DateUtil.java | 59 ++ .../java/com/sunyard/ssp/utils/FileUtil.java | 187 +++++ .../java/com/sunyard/ssp/utils/FileUtils.java | 33 + .../java/com/sunyard/ssp/utils/IpUtil.java | 46 ++ .../java/com/sunyard/ssp/utils/JsonUtil.java | 27 + .../java/com/sunyard/ssp/utils/KeyUtil.java | 20 + .../java/com/sunyard/ssp/utils/Md5Util.java | 110 +++ .../java/com/sunyard/ssp/utils/PageUtil.java | 164 ++++ .../com/sunyard/ssp/utils/ProtobufUtil.java | 11 + .../com/sunyard/ssp/utils/ResponseUtil.java | 70 ++ .../com/sunyard/ssp/utils/ResultUtil.java | 54 ++ .../com/sunyard/ssp/utils/SecurityUtil.java | 144 ++++ .../com/sunyard/ssp/utils/SpringUtil.java | 40 + .../com/sunyard/ssp/utils/StringUtil.java | 50 ++ .../com/sunyard/ssp/utils/ThreadPoolUtil.java | 37 + .../java/com/sunyard/ssp/utils/UserUtil.java | 81 ++ .../com/sunyard/ssp/utils/UsernameUtil.java | 56 ++ .../java/com/sunyard/ssp/utils/UuidUtil.java | 17 + .../sunyard/ssp/utils/regexp/RegexUtil.java | 52 ++ .../exception/RegexpIllegalException.java | 16 + .../exception/TypeNotMatchException.java | 12 + .../exception/UninitializedException.java | 12 + .../ssp/utils/regexp/model/BaseRegexNode.java | 171 ++++ .../ssp/utils/regexp/model/LinkRegexNode.java | 68 ++ .../utils/regexp/model/OptionalRegexNode.java | 55 ++ .../utils/regexp/model/OrdinaryRegexNode.java | 51 ++ .../ssp/utils/regexp/model/RegexNode.java | 18 + .../utils/regexp/model/RepeatRegexNode.java | 73 ++ .../utils/regexp/model/SingleRegexNode.java | 155 ++++ .../com/sunyard/ssp/utils/sm2/BCECUtil.java | 500 +++++++++++ .../com/sunyard/ssp/utils/sm2/GMBaseUtil.java | 11 + .../com/sunyard/ssp/utils/sm2/SM2Util.java | 593 +++++++++++++ .../java/com/sunyard/ssp/utils/sm3/SM3.java | 351 ++++++++ .../com/sunyard/ssp/utils/sm3/SM3Digest.java | 183 ++++ .../java/com/sunyard/ssp/utils/sm3/Util.java | 662 +++++++++++++++ .../main/java/com/sunyard/ssp/vo/KeyVo.java | 24 + .../java/com/sunyard/ssp/vo/ScRoleVo.java | 30 + .../java/com/sunyard/ssp/vo/SearchVo.java | 19 + .../java/com/sunyard/ssp/vo/TokenUser.java | 22 + .../java/com/sunyard/ssp/vo/UPublicKeyVo.java | 31 + .../src/main/resources/application.yml | 150 ++++ chsm-web-server/pom.xml | 20 + config/redis.config.json | 16 + pom.xml | 121 +++ 200 files changed, 18322 insertions(+) create mode 100644 .gitignore create mode 100644 chsm-common/pom.xml create mode 100644 chsm-common/src/main/java/com/sunyard/utils/DateFormatPattern.java create mode 100644 chsm-common/src/main/java/com/sunyard/utils/JsonUtils.java create mode 100644 chsm-common/src/main/java/com/sunyard/utils/ThrowableUtils.java create mode 100644 chsm-model/pom.xml create mode 100644 chsm-web-manage/pom.xml create mode 100644 chsm-web-manage/src/main/java/com/sunyard/WebManageApp.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/CorsFilter.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/WebConfig.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/CaptchaProperties.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/IgnoredUrlsProperties.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/SM3PasswordEncoder.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/SecurityUserDetails.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/UserDetailsServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/WebSecurityConfig.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationFailHandler.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationSuccessHandler.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/JWTAuthenticationFilter.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/RestAccessDeniedHandler.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyAccessDecisionManager.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyFilterSecurityInterceptor.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyRequestVo.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MySecurityMetadataSource.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/config/security/validate/ImageValidateFilter.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/PageVo.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/Result.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/annotation/AuditControllerLog.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CertificateConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelSolutionConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CommonConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceGroupRefConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DictDataConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/FileConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyAttributeConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeySolutionConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/NodeConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ParamConfKeyConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ProtocolConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/RegexConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SdkConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SecurityConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SqlConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SspServerConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ValidatorConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/WorkflowConstant.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/enums/UserHeaderTypeEnum.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/GlobalExceptionResolver.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/LoginFailLimitException.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/SspwebException.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/common/vo/Captcha.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/config/ServerConfigure.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/aspect/AuditLogAspect.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/AuditLogController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/LogDownloadController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/LogSignController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/SysLogController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/AuditLog.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/AuditLogSign.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/LogSign.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/SysLog.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/AuditLogMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/AuditLogSignMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/LogSignMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/SysLogMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/IAuditLogService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/IAuditLogSignService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/ILogSignService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/ISysLogService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/LogDownloadService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/AuditLogServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/AuditLogSignServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/LogDownloadServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/LogSignServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/SysLogServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/ASymmetricKeyToolService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/CertService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/KeyLifecycleService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SdkApiService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SdkApiServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SymmetricKeyToolService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/controller/ParamConfController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/entity/ParamConf.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/mapper/ParamConfMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/service/IParamConfService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/serviceimpl/ParamConfServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScDepartmentController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScDepartmentHeaderController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScPermissionController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScPositionController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRoleController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRoleDepartmentController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRolePermissionController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUShieldController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUserController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUserRoleController.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScDepartment.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScDepartmentHeader.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScPermission.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScPosition.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRole.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRoleDepartment.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRolePermission.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScUser.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScUserRole.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ULoginDto.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/UkeyLoginParm.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScDepartmentHeaderMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScDepartmentMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScPermissionMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScPositionMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRoleDepartmentMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRoleMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRolePermissionMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScUserMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScUserRoleMapper.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScDepartmentHeaderService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScDepartmentService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScPermissionService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScPositionService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRoleDepartmentService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRolePermissionService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRoleService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScUserRoleService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScUserService.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScDepartmentHeaderServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScDepartmentServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScPermissionServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScPositionServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRoleDepartmentServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRolePermissionServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRoleServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScUserRoleServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScUserServiceImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/SdkApiServiceFImpl.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/DepartmentValidator.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/PermissionValidator.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/PositionValidator.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/RoleValidator.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/UserValidator.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/redis/JedisClusterConfig.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisConfig.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisObjectOperation.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisOperation.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/server/Config.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/server/Messenger.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/server/Redis.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/server/ServerTest.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/server/VOChannel.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CaUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ClazzUtils.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CommonUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CreateVerifyCode.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/DateUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/FileUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/FileUtils.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/IpUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/JsonUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/KeyUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/Md5Util.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/PageUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ProtobufUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ResponseUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ResultUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/SecurityUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/SpringUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/StringUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ThreadPoolUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UserUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UsernameUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UuidUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/RegexUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/RegexpIllegalException.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/TypeNotMatchException.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/UninitializedException.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/BaseRegexNode.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/LinkRegexNode.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/OptionalRegexNode.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/OrdinaryRegexNode.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/RegexNode.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/RepeatRegexNode.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/SingleRegexNode.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/BCECUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/GMBaseUtil.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/SM2Util.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/SM3.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/SM3Digest.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/Util.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/vo/KeyVo.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/vo/ScRoleVo.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/vo/SearchVo.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/vo/TokenUser.java create mode 100644 chsm-web-manage/src/main/java/com/sunyard/ssp/vo/UPublicKeyVo.java create mode 100644 chsm-web-manage/src/main/resources/application.yml create mode 100644 chsm-web-server/pom.xml create mode 100644 config/redis.config.json create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6c3316 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +.idea/ +target/ +maven +*.bak +*.iml +*.log +/logs +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar +.DS_Store + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +*node_modules diff --git a/chsm-common/pom.xml b/chsm-common/pom.xml new file mode 100644 index 0000000..c868223 --- /dev/null +++ b/chsm-common/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + com.sunyard.chsm + chsm + 1.0-SNAPSHOT + + + chsm-common + + + 8 + 8 + UTF-8 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-aop + + + com.baomidou + mybatis-plus-boot-starter + + + + + + + \ No newline at end of file diff --git a/chsm-common/src/main/java/com/sunyard/utils/DateFormatPattern.java b/chsm-common/src/main/java/com/sunyard/utils/DateFormatPattern.java new file mode 100644 index 0000000..44e1c02 --- /dev/null +++ b/chsm-common/src/main/java/com/sunyard/utils/DateFormatPattern.java @@ -0,0 +1,35 @@ +package com.sunyard.utils; + +/** + * @author liulu + * @version V1.0 + * @since 2022/12/6 + */ +public abstract class DateFormatPattern { + + public static final String YYYY = "yyyy"; + public static final String YYYYMMDD = "yyyyMMdd"; + public static final String YYYY_MM_DD = "yyyy-MM-dd"; + public static final String YYYYIMMIDD = "yyyy/MM/dd"; + public static final String YYYYMMDDHHMM = "yyyyMMddHHmm"; + public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + public static final String YYYYMMDD_HHMMSS = "yyyyMMdd HHmmss"; + public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm"; + public static final String YYYYMMDDHHMMSS_SS = "yyyyMMddHHmmssSSS"; + public static final String HHMMSS_TIME_FORMAT = "HHmmss"; + public static final String YYYY_MM_DD_T_HH_MM_SS_Z = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + public static final String YYYY_MM_DD_HH24_MM_SS = "yyyy-MM-d hh24:mm:ss"; + public static final String HH_MM = "HH:mm"; + public static final String HHMM = "HHmm"; + public static final String HH_MM_SS = "HH:mm:ss"; + public static final String ZERO_HH_MM_SS = " 00:00:00"; + public static final String YYMMDD = "yyMMdd"; + public static final String YYYY_CN_MM_CN_DD_CN = "yyyy年 MM 月 dd 日"; + public static final String MM_CN_DD_CN = "MM 月 dd 日"; + public static final String BEGIN_OF_DAY = "yyyy-MM-dd 00:00:00"; + public static final String END_OF_DAY = "yyyy-MM-dd 23:59:59"; + public static final String YYYYIMMIDDHHMMSS = "yyyy/MM/dd HH:mm:ss"; + + +} diff --git a/chsm-common/src/main/java/com/sunyard/utils/JsonUtils.java b/chsm-common/src/main/java/com/sunyard/utils/JsonUtils.java new file mode 100644 index 0000000..3f7de11 --- /dev/null +++ b/chsm-common/src/main/java/com/sunyard/utils/JsonUtils.java @@ -0,0 +1,97 @@ +package com.sunyard.utils; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + + +/** + * @author liulu + * @version V1.0 + * @since 2020/11/25 + */ +public abstract class JsonUtils { + + private JsonUtils() { + } + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + static { + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS))); + javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD))); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS))); + + javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS))); + javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD))); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS))); + + OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + OBJECT_MAPPER.registerModules(javaTimeModule); + } + + public static ObjectMapper objectMapper() { + return OBJECT_MAPPER; + } + + public static String toJsonString(Object obj) { + try { + return OBJECT_MAPPER.writeValueAsString(obj); + } catch (JsonProcessingException e) { + // + throw new IllegalArgumentException(e); + } + } + + public static byte[] toJsonBytes(Object obj) { + try { + return OBJECT_MAPPER.writeValueAsBytes(obj); + } catch (JsonProcessingException e) { + // + throw new IllegalArgumentException(e); + } + } + + + public static T parse(String jsonStr, Class type) { + if (jsonStr == null || jsonStr.isEmpty()) { + return null; + } + try { + return OBJECT_MAPPER.readValue(jsonStr, type); + } catch (JsonProcessingException e) { + // + throw new IllegalArgumentException("json格式错误"); + } + } + + public static T parse(byte[] json, Class type) { + if (json == null || json.length == 0) { + return null; + } + try { + return OBJECT_MAPPER.readValue(json, type); + } catch (IOException e) { + // + throw new IllegalArgumentException("json格式错误"); + } + } + + +} diff --git a/chsm-common/src/main/java/com/sunyard/utils/ThrowableUtils.java b/chsm-common/src/main/java/com/sunyard/utils/ThrowableUtils.java new file mode 100644 index 0000000..379023b --- /dev/null +++ b/chsm-common/src/main/java/com/sunyard/utils/ThrowableUtils.java @@ -0,0 +1,41 @@ +package com.sunyard.utils; + +/** + * @author liulu + * @version V1.0 + * @since 2020/11/16 + */ +public abstract class ThrowableUtils { + + private ThrowableUtils() { + } + + + public static String buildErrorMessage(Throwable ex) { + StringBuilder sb = new StringBuilder(); + sb.append(ex.getMessage()); + StackTraceElement[] stackTrace = ex.getStackTrace(); + int i = 0; + for (StackTraceElement stackTraceElement : stackTrace) { + if (i++ >= 5) { + break; + } + sb.append("\n\t").append(stackTraceElement.toString()); + } + return sb.toString(); + } + + + public static T findException(Class exClass, Throwable ex) { + for (int i = 0; ex != null && i < 3; i++) { + if (exClass.isAssignableFrom(ex.getClass())) { + //noinspection unchecked + return (T) ex; + } + ex = ex.getCause(); + } + return null; + } + + +} diff --git a/chsm-model/pom.xml b/chsm-model/pom.xml new file mode 100644 index 0000000..bbc9399 --- /dev/null +++ b/chsm-model/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.sunyard.chsm + chsm + 1.0-SNAPSHOT + + + chsm-model + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/chsm-web-manage/pom.xml b/chsm-web-manage/pom.xml new file mode 100644 index 0000000..cfd4180 --- /dev/null +++ b/chsm-web-manage/pom.xml @@ -0,0 +1,144 @@ + + + 4.0.0 + + com.sunyard.chsm + chsm + 1.0-SNAPSHOT + + + chsm-web-manage + + + 8 + 8 + UTF-8 + + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-data-redis + + + + io.lettuce + lettuce-core + + + + + + redis.clients + jedis + + + + com.sunyard.chsm + chsm-common + ${project.version} + + + + org.bouncycastle + bcprov-jdk15on + + + + org.bouncycastle + bcpkix-jdk15on + + + + com.dm + DmJdbcDriver + 1.8 + + + + + com.sunyard + ssp.javasdk + 1.0-SNAPSHOT + + + com.sunyard + sdf1418 + 1.0-SNAPSHOT + + + com.sunyard + sydapi4j + 1.13.20221010 + + + * + groovy-all + + + + + + + org.apache.commons + commons-pool2 + + + org.apache.commons + commons-lang3 + + + commons-codec + commons-codec + + + + net.java.dev.jna + jna + 4.5.2 + + + io.swagger + swagger-annotations + 1.5.13 + + + + + com.googlecode.protobuf-java-format + protobuf-java-format + 1.2 + + + com.google.protobuf + protobuf-java + 3.17.3 + + + + com.google.code.gson + gson + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + javax.persistence + javax.persistence-api + + + + + + + \ No newline at end of file diff --git a/chsm-web-manage/src/main/java/com/sunyard/WebManageApp.java b/chsm-web-manage/src/main/java/com/sunyard/WebManageApp.java new file mode 100644 index 0000000..9cc8dd7 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/WebManageApp.java @@ -0,0 +1,22 @@ +package com.sunyard; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * @author liulu + * @since 2024/10/25 + */ +@SpringBootApplication +//@ComponentScan(basePackages={"com.sunyard"}) +@EnableScheduling +@EnableAsync +public class WebManageApp { + + public static void main(String[] args) { + SpringApplication.run(WebManageApp.class, args); + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/CorsFilter.java b/chsm-web-manage/src/main/java/com/sunyard/config/CorsFilter.java new file mode 100644 index 0000000..d98fbcc --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/CorsFilter.java @@ -0,0 +1,37 @@ +package com.sunyard.config; + +import org.springframework.stereotype.Component; + +import javax.servlet.Filter; +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 java.io.IOException; + +/** + * @author:tsz + * @date:2020/3/9 + * @description: 跨域问题 + */ +@Component +public class CorsFilter implements Filter { + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { + HttpServletResponse response = (HttpServletResponse) res; + + // response.setHeader("Access-Control-Allow-Origin",reqs.getHeader("Origin")); + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, HEAD, DELETE"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("access-control-allow-headers", "Content-Type,Accept,Authorization,accesstoken"); + if (((HttpServletRequest) req).getMethod().equals("OPTIONS")) { + response.setStatus(200); + return; + } + chain.doFilter(req, res); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/WebConfig.java b/chsm-web-manage/src/main/java/com/sunyard/config/WebConfig.java new file mode 100644 index 0000000..e315c20 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/WebConfig.java @@ -0,0 +1,66 @@ +package com.sunyard.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import com.sunyard.utils.DateFormatPattern; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * @author liulu + * @since 2024/10/25 + */ +@Configuration +@MapperScan("com.sunyard.ssp.**.mapper") +public class WebConfig { + + /** + * 添加分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 如果配置多个插件, 切记分页最后添加 + // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.DM)); + return interceptor; + } + + + @Bean + public Jackson2ObjectMapperBuilderCustomizer objectMapperBuilderCustomizer() { + return builder -> { + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS))); + javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD))); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS))); + + javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS))); + javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD))); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS))); + + builder.modules(javaTimeModule); + builder.serializerByType(Long.class, ToStringSerializer.instance); + builder.serializationInclusion(JsonInclude.Include.NON_NULL); + builder.failOnUnknownProperties(false); + }; + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/CaptchaProperties.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/CaptchaProperties.java new file mode 100644 index 0000000..3f5acc6 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/CaptchaProperties.java @@ -0,0 +1,25 @@ +package com.sunyard.config.security; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Exrickx + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "captcha") +public class CaptchaProperties { + + private List image = new ArrayList<>(); + + private List sms = new ArrayList<>(); + + private List vaptcha = new ArrayList<>(); + + private List email = new ArrayList<>(); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/IgnoredUrlsProperties.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/IgnoredUrlsProperties.java new file mode 100644 index 0000000..506df41 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/IgnoredUrlsProperties.java @@ -0,0 +1,19 @@ +package com.sunyard.config.security; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Exrickx + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "ignored") +public class IgnoredUrlsProperties { + + private List urls = new ArrayList<>(); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/SM3PasswordEncoder.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/SM3PasswordEncoder.java new file mode 100644 index 0000000..208bd28 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/SM3PasswordEncoder.java @@ -0,0 +1,66 @@ +package com.sunyard.config.security; + +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.utils.sm3.SM3Digest; +import org.springframework.security.crypto.password.PasswordEncoder; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; + +/** + * @Auther: wp + * @Date: 2021/12/16 10:47 + * @Description: + */ +public class SM3PasswordEncoder implements PasswordEncoder { + + @Override + public String encode(CharSequence rawPassword) { + String salt = RandomUtil.randomString(CommonConstant.SALT_NUMBER); + String encode = SM3Digest.encode(salt + rawPassword.toString()); + return new StringBuilder().append(encode).append("@").append(salt).toString(); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + if(StrUtil.isBlank(encodedPassword)){ + return false; + } + //先从encodedPassword提取salt + String salt = encodedPassword.split("@")[1]; + String encode = SM3Digest.encode(salt + rawPassword.toString()); + String origin = new StringBuilder().append(encode).append("@").append(salt).toString(); + + return MessageDigest.isEqual(origin.getBytes(StandardCharsets.UTF_8), encodedPassword.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public boolean upgradeEncoding(String encodedPassword) { + return false; + } + +// public static void main(String[] args) { +//// String rawPassword="wp123456."; +//// String encode1 = SM3Digest.encode(rawPassword); +//// System.out.println(encode1); +//// String salt = RandomUtil.randomString(CommonConstant.SALT_NUMBER); +//// String encode = SM3Digest.encode(salt + encode1); +//// String s = new StringBuilder().append(encode).append("@").append(salt).toString(); +//// System.out.println(s); +// +// String encodedPassword="00513D5AC7477E6E8FD33A2A6EAAB2F6C04B260DA91E7E6648E8472E914939EB@2sszbadwg5"; +// //AE2B659E60E130E47D18F95387B599E7C261275902020F1D942BD69C2840F28F@tpgb0tfqxc +// //先从encodedPassword提取salt +// String salt = encodedPassword.split("@")[1]; +// String rawPassword="3160FD1B6DAEA5A455C7F6C2DC48BEA3A2B9DA73270960791FDBFD60B57A95EA"; +// String encode = SM3Digest.encode(salt + rawPassword.toString()); +// String origin = new StringBuilder().append(encode).append("@").append(salt).toString(); +// +// boolean equal = MessageDigest.isEqual(origin.getBytes(StandardCharsets.UTF_8), encodedPassword.getBytes(StandardCharsets.UTF_8)); +// System.out.println(equal); +// } + +} + diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/SecurityUserDetails.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/SecurityUserDetails.java new file mode 100644 index 0000000..6ff2074 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/SecurityUserDetails.java @@ -0,0 +1,98 @@ +package com.sunyard.config.security; + +import cn.hutool.core.util.StrUtil; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import com.sunyard.ssp.modules.user.entity.ScUser; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Exrickx + */ +@Slf4j +public class SecurityUserDetails extends ScUser implements UserDetails { + + private static final long serialVersionUID = 1L; + + public SecurityUserDetails(ScUser user) { + + if(user!=null) { + this.setUsername(user.getUsername()); + this.setPassword(user.getPassword()); + this.setStatus(user.getStatus()==null?0:user.getStatus()); + this.setRoles(user.getRoles()); + this.setPermissions(user.getPermissions()); + } + } + + /** + * 添加用户拥有的权限和角色 + * @return + */ + @Override + public Collection getAuthorities() { + + + List authorityList = new ArrayList<>(); + List permissions = this.getPermissions(); + // 添加请求权限 + if(permissions!=null&&permissions.size()>0){ + for (ScPermission permission : permissions) { + if(CommonConstant.PERMISSION_OPERATION.equals(permission.getPType()) + &&StrUtil.isNotBlank(permission.getTitle()) + &&StrUtil.isNotBlank(permission.getPath())) { + + authorityList.add(new SimpleGrantedAuthority(permission.getTitle())); + } + } + } + return authorityList; + } + + /** + * 账户是否过期 + * @return + */ + @Override + public boolean isAccountNonExpired() { + + return true; + } + + /** + * 是否禁用 + * @return + */ + @Override + public boolean isAccountNonLocked() { + + return CommonConstant.USER_STATUS_LOCK.equals(this.getStatus()) ? false : true; + } + + /** + * 密码是否过期 + * @return + */ + @Override + public boolean isCredentialsNonExpired() { + + return true; + } + + /** + * 是否启用 + * @return + */ + @Override + public boolean isEnabled() { + + return CommonConstant.USER_STATUS_NORMAL.equals(this.getStatus()) ? true : false; + } +} \ No newline at end of file diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/UserDetailsServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/UserDetailsServiceImpl.java new file mode 100644 index 0000000..f295993 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/UserDetailsServiceImpl.java @@ -0,0 +1,76 @@ +package com.sunyard.config.security; + +import cn.hutool.core.util.StrUtil; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.common.exception.LoginFailLimitException; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScPermissionService; +import com.sunyard.ssp.modules.user.service.IScUserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.concurrent.TimeUnit; + +/** + * @author Exrickx + */ +@Slf4j +@Component +public class UserDetailsServiceImpl implements UserDetailsService{ + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + private IScUserService userService; + + @Autowired + private IScPermissionService permissionService; + + @Value("${ssp.passMaxDays}") + private Integer passMaxDays; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + long begin = System.currentTimeMillis(); + String flagKey = "loginFailFlag:" + username; + String value = redisTemplate.opsForValue().get(flagKey); + + if(StrUtil.isBlank(username)){ + return new SecurityUserDetails(null); + } + + //通过用户名登陆 + ScUser user = userService.findByUsername(username); + + if(user == null){ + return new SecurityUserDetails(null); + } + + //admin特殊处理 + if(CommonConstant.DEFAULT_USER_ROOT_ID.equals(user.getId())){ + Long timeRest = redisTemplate.getExpire(flagKey, TimeUnit.SECONDS); + Double minutes = Math.ceil(Double.valueOf(timeRest)/60); + if(StrUtil.isNotBlank(value)){ + //超过限制次数 + throw new LoginFailLimitException("登录错误次数超过限制,请"+minutes.intValue()+"分钟后再试"); + } + return new SecurityUserDetails(user); + } + + //密码过期日 + LocalDateTime passLimitDate = LocalDateTime.now().minusDays(passMaxDays); + if(passLimitDate.isAfter(user.getPassUpdateTime())){ + throw new LoginFailLimitException("密码已过期,请联系管理员修改后重试"); + } + + return new SecurityUserDetails(user); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/WebSecurityConfig.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/WebSecurityConfig.java new file mode 100644 index 0000000..00af282 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/WebSecurityConfig.java @@ -0,0 +1,119 @@ +package com.sunyard.config.security; + +import com.sunyard.config.security.jwt.AuthenticationFailHandler; +import com.sunyard.config.security.jwt.AuthenticationSuccessHandler; +import com.sunyard.config.security.jwt.JWTAuthenticationFilter; +import com.sunyard.config.security.jwt.RestAccessDeniedHandler; +import com.sunyard.config.security.permission.MyFilterSecurityInterceptor; +import com.sunyard.config.security.validate.ImageValidateFilter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +/** + * Security 核心配置类 + * 开启注解控制权限至Controller + * @author Exrickx + */ +@Slf4j +@Configuration +@EnableGlobalMethodSecurity(prePostEnabled=true) +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Value("${ssp.token.redis}") + private Boolean tokenRedis; + + @Value("${ssp.tokenExpireTime}") + private Integer tokenExpireTime; + + @Autowired + private IgnoredUrlsProperties ignoredUrlsProperties; + + @Autowired + private UserDetailsServiceImpl userDetailsService; + + @Autowired + private AuthenticationSuccessHandler successHandler; + + @Autowired + private AuthenticationFailHandler failHandler; + + @Autowired + private RestAccessDeniedHandler accessDeniedHandler; + + @Autowired + private MyFilterSecurityInterceptor myFilterSecurityInterceptor; + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + private ImageValidateFilter imageValidateFilter; + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder()); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = http + .authorizeRequests(); + + //除配置文件忽略路径其它所有请求都需经过认证和授权 + for(String url:ignoredUrlsProperties.getUrls()){ + registry.antMatchers(url).permitAll(); + } + + registry.and() + //表单登录方式 + .formLogin() + .loginPage("/needLogin") + //登录请求url + .loginProcessingUrl("/login") + .permitAll() + //成功处理类 + .successHandler(successHandler) + //失败 + .failureHandler(failHandler) + .and() + //允许网页iframe + .headers().frameOptions().disable() + .and() + .logout() + .permitAll() + .and() + .authorizeRequests() + //任何请求 + .anyRequest() + //需要身份认证 + .authenticated() + .and() + //关闭跨站请求防护 + .csrf().disable() + //前后端分离采用JWT 不需要session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + //自定义权限拒绝处理类 + .exceptionHandling().accessDeniedHandler(accessDeniedHandler) + .and() + // 图形验证码过滤器 + .addFilterBefore(imageValidateFilter, UsernamePasswordAuthenticationFilter.class) + //添加自定义权限过滤器 + .addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class) + //添加JWT过滤器 除已配置的其它请求都需经过此过滤器 + .addFilter(new JWTAuthenticationFilter(authenticationManager(), tokenRedis, tokenExpireTime, redisTemplate)); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationFailHandler.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationFailHandler.java new file mode 100644 index 0000000..935541f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationFailHandler.java @@ -0,0 +1,114 @@ +package com.sunyard.config.security.jwt; + +import cn.hutool.core.util.StrUtil; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.common.exception.LoginFailLimitException; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScUserService; +import com.sunyard.ssp.utils.ResponseUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.LockedException; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * @author Exrickx + */ +@Slf4j +@Component +public class AuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler { + + @Value("${ssp.loginTimeLimit}") + private Integer loginTimeLimit; + + @Value("${ssp.loginAfterTime}") + private Integer loginAfterTime; + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + private IScUserService userService; + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { + + String username = request.getParameter("username"); + + if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) { + + recordLoginTime(username); + String key = "loginTimeLimit:" + username; + String value = redisTemplate.opsForValue().get(key); + if (StrUtil.isBlank(value)) { + value = "0"; + } + //获取已登录错误次数 + int loginFailTime = Integer.parseInt(value); + int restLoginTime = loginTimeLimit - loginFailTime; + log.info("用户" + username + "登录失败,还有" + restLoginTime + "次机会"); + if (restLoginTime <= 3 && restLoginTime > 0) { + ResponseUtil.out(response, ResponseUtil.resultMap(false, 500, "用户名或密码错误,还有" + restLoginTime + "次尝试机会")); + } else if (restLoginTime <= 0) { + ScUser user = userService.findByUsername(username); + if (user != null && !CommonConstant.DEFAULT_USER_ROOT_ID.equals(user.getId())) { + user.setStatus(CommonConstant.USER_STATUS_LOCK); + userService.updateById(user); + ResponseUtil.out(response, ResponseUtil.resultMap(false, 500, "登录错误次数超过限制,用户已被锁定,请联系管理员解锁后重试")); + } else { + ResponseUtil.out(response, ResponseUtil.resultMap(false, 500, "登录错误次数超过限制,请" + loginAfterTime + "分钟后再试")); + } + } else { + ResponseUtil.out(response, ResponseUtil.resultMap(false, 500, "用户名或密码错误")); + } + } else if (e instanceof DisabledException){ + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户不存在")); + } else if (e instanceof LockedException) { + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户被禁用,请联系管理员")); + } else if (e instanceof LoginFailLimitException){ + ScUser user = userService.findByUsername(username); + if (user != null && !CommonConstant.DEFAULT_USER_ROOT_ID.equals(user.getId())) { + user.setStatus(CommonConstant.USER_STATUS_LOCK); + userService.updateById(user); + } + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,((LoginFailLimitException) e).getMsg())); + } else { + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"登录失败,其他内部错误")); + } + } + + /** + * 判断用户登陆错误次数 + */ + public boolean recordLoginTime(String username){ + + String key = "loginTimeLimit:"+username; + String flagKey = "loginFailFlag:"+username; + String value = redisTemplate.opsForValue().get(key); + if(StrUtil.isBlank(value)){ + value = "0"; + } + //获取已登录错误次数 + int loginFailTime = Integer.parseInt(value) + 1; + redisTemplate.opsForValue().set(key, String.valueOf(loginFailTime), loginAfterTime, TimeUnit.MINUTES); + if(loginFailTime>=loginTimeLimit){ + + redisTemplate.opsForValue().set(flagKey, "fail", loginAfterTime, TimeUnit.MINUTES); + return false; + } + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationSuccessHandler.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationSuccessHandler.java new file mode 100644 index 0000000..d1f7cf6 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationSuccessHandler.java @@ -0,0 +1,144 @@ +package com.sunyard.config.security.jwt; + +import cn.hutool.core.util.StrUtil; +import com.google.gson.Gson; +import com.sunyard.ssp.common.constant.SecurityConstant; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScUserService; +import com.sunyard.ssp.utils.ResponseUtil; +import com.sunyard.ssp.utils.SecurityUtil; +import com.sunyard.ssp.vo.TokenUser; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * 登录成功处理类 + * @author Exrickx + */ +@Slf4j +@Component +public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { + + @Value("${ssp.token.redis}") + private Boolean tokenRedis; + + @Value("${ssp.tokenExpireTime}") + private Integer tokenExpireTime; + + @Value("${ssp.saveLoginTime}") + private Integer saveLoginTime; + + @Value("${ssp.passMaxDays}") + private Integer passMaxDays; + + @Value("${ssp.passWarnAge}") + private Integer passWarnAge; + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + private SecurityUtil securityUtil; + + @Autowired + private IScUserService scUserService; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + + long beginTime = System.currentTimeMillis(); + //用户选择保存登录状态几天 + String saveLogin = request.getParameter(SecurityConstant.SAVE_LOGIN); + Boolean saved = false; + String msg = "登录成功"; + if(StrUtil.isNotBlank(saveLogin) && Boolean.valueOf(saveLogin)){ + saved = true; + if(!tokenRedis){ + tokenExpireTime = saveLoginTime * 60 * 24; + } + } + String username = ((UserDetails)authentication.getPrincipal()).getUsername(); + System.out.println("loginSuccess username:" + username + "begin:" + (beginTime - System.currentTimeMillis())); + List authorities = (List) ((UserDetails)authentication.getPrincipal()).getAuthorities(); + List list = new ArrayList<>(); + for(GrantedAuthority g : authorities){ + list.add(g.getAuthority()); + } + System.out.println("loginSuccess username:" + username + "getCurrUser begin:" + (beginTime - System.currentTimeMillis())); + ScUser scuser = securityUtil.getCurrUser(); + //ipInfoUtil.getUrl(request); + System.out.println("loginSuccess username:" + username + "getCurrUser end:" + (beginTime - System.currentTimeMillis())); + // 登陆成功生成token + String token; + if(tokenRedis){ + // redis + token = UUID.randomUUID().toString().replace("-", ""); + TokenUser user = new TokenUser(username, list, saved); + // 单点登录 之前的token失效 + String oldToken = redisTemplate.opsForValue().get(SecurityConstant.USER_TOKEN + username); + if(StrUtil.isNotBlank(oldToken)){ + redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken); + } + + //清空失败次数 + String key = "loginTimeLimit:" + username; + redisTemplate.delete(key); + + if(saved){ + redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + username, token, saveLoginTime, TimeUnit.DAYS); + redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(user), saveLoginTime, TimeUnit.DAYS); + }else{ + redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + username, token, tokenExpireTime, TimeUnit.MINUTES); + redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(user), tokenExpireTime, TimeUnit.MINUTES); + } + }else{ + // jwt + token = SecurityConstant.TOKEN_SPLIT + Jwts.builder() + //主题 放入用户名 + .setSubject(username) + //自定义属性 放入用户拥有请求权限 + .claim(SecurityConstant.AUTHORITIES, new Gson().toJson(list)) + //失效时间 + .setExpiration(new Date(System.currentTimeMillis() + tokenExpireTime * 60 * 1000)) + //签名算法和密钥 + .signWith(SignatureAlgorithm.HS512, SecurityConstant.JWT_SIGN_KEY) + .compact(); + } + + LocalDateTime limitDate = scuser.getPassUpdateTime().plusDays(passMaxDays); + + DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + if(limitDate.isBefore(LocalDateTime.now().plusDays(passWarnAge))){ + msg = "密码将于" + sdf.format(limitDate) + "过期,请及时修改"; + } + + /*sunyard*/ + response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, HEAD, DELETE"); + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("access-control-allow-headers", "Content-Type,Accept,Authorization,accesstoken"); + /*sunyard end*/ + System.out.println("loginSuccess username:" + username + "end:" + (beginTime - System.currentTimeMillis())); + ResponseUtil.out(response, ResponseUtil.resultMap(true,200,msg, token)); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/JWTAuthenticationFilter.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/JWTAuthenticationFilter.java new file mode 100644 index 0000000..13ddf15 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/JWTAuthenticationFilter.java @@ -0,0 +1,163 @@ +package com.sunyard.config.security.jwt; + +import cn.hutool.core.util.StrUtil; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.sunyard.ssp.common.constant.SecurityConstant; +import com.sunyard.ssp.utils.ResponseUtil; +import com.sunyard.ssp.vo.TokenUser; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jwts; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @author Exrickx + */ +@Slf4j +public class JWTAuthenticationFilter extends BasicAuthenticationFilter { + + private Boolean tokenRedis; + + private Integer tokenExpireTime; + + private StringRedisTemplate redisTemplate; + + public JWTAuthenticationFilter(AuthenticationManager authenticationManager, Boolean tokenRedis, Integer tokenExpireTime, StringRedisTemplate redisTemplate) { + super(authenticationManager); + this.tokenRedis = tokenRedis; + this.tokenExpireTime = tokenExpireTime; + this.redisTemplate = redisTemplate; + } + + public JWTAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) { + super(authenticationManager, authenticationEntryPoint); + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + + /*sunyard*/ + String method = request.getMethod(); + System.out.println( method ); + System.out.println( request.getRequestURI() ); + + + response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, HEAD, DELETE"); + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("access-control-allow-headers", "Content-Type,Accept,Authorization,accesstoken,auth-token"); + + + + if ("options".equalsIgnoreCase(method)){ + response.setStatus(200); + return; + } + /*sunyard end*/ + + String header = request.getHeader(SecurityConstant.HEADER); + if(StrUtil.isBlank(header)){ + header = request.getParameter(SecurityConstant.HEADER); + } + + if(StrUtil.isBlank(header) && request.getCookies()!=null){ + Cookie cookie = Arrays.stream(request.getCookies()).filter(tmpCookie -> SecurityConstant.HEADER.equals(tmpCookie.getName())).findAny().orElse(null); + header = cookie == null?null: cookie.getValue(); + } + + Boolean notValid = StrUtil.isBlank(header) || (!tokenRedis && !header.startsWith(SecurityConstant.TOKEN_SPLIT)); + if (notValid) { + chain.doFilter(request, response); + return; + } + try { + UsernamePasswordAuthenticationToken authentication = getAuthentication(header, response, request); + SecurityContextHolder.getContext().setAuthentication(authentication); + }catch (Exception e){ + e.toString(); + } + + chain.doFilter(request, response); + } + + private UsernamePasswordAuthenticationToken getAuthentication(String header, HttpServletResponse response, HttpServletRequest request) { + + // 用户名 + String username = null; + // 权限 + List authorities = new ArrayList<>(); + + if(tokenRedis){ + // redis + String v = redisTemplate.opsForValue().get(SecurityConstant.TOKEN_PRE + header); + if(StrUtil.isBlank(v)){ + ResponseUtil.out(response, ResponseUtil.resultMap(false,401,"登录已失效,请重新登录")); + return null; + } + TokenUser user = new Gson().fromJson(v, TokenUser.class); + username = user.getUsername(); + for(String ga : user.getPermissions()){ + authorities.add(new SimpleGrantedAuthority(ga)); + } + if(!user.getSaveLogin()){ + // 若未保存登录状态重新设置失效时间 + redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + username, header, tokenExpireTime, TimeUnit.MINUTES); + redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + header, v, tokenExpireTime, TimeUnit.MINUTES); + } + }else{ + // JWT + try { + // 解析token + Claims claims = Jwts.parser() + .setSigningKey(SecurityConstant.JWT_SIGN_KEY) + .parseClaimsJws(header.replace(SecurityConstant.TOKEN_SPLIT, "")) + .getBody(); + + //获取用户名 + username = claims.getSubject(); + //获取权限 + String authority = claims.get(SecurityConstant.AUTHORITIES).toString(); + + if(StrUtil.isNotBlank(authority)){ + List list = new Gson().fromJson(authority, new TypeToken>(){}.getType()); + for(String ga : list){ + authorities.add(new SimpleGrantedAuthority(ga)); + } + } + } catch (ExpiredJwtException e) { + ResponseUtil.out(response, ResponseUtil.resultMap(false,401,"登录已失效,请重新登录")); + } catch (Exception e){ + log.error(e.toString()); + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"解析token错误")); + } + } + + if(StrUtil.isNotBlank(username)) { + //Exrick踩坑提醒 此处password不能为null + User principal = new User(username, "", authorities); + return new UsernamePasswordAuthenticationToken(principal, null, authorities); + } + return null; + } +} + diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/RestAccessDeniedHandler.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/RestAccessDeniedHandler.java new file mode 100644 index 0000000..42d16f1 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/RestAccessDeniedHandler.java @@ -0,0 +1,29 @@ +package com.sunyard.config.security.jwt; + + +import com.sunyard.ssp.utils.ResponseUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author Exrickx + */ +@Component +@Slf4j +public class RestAccessDeniedHandler implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) + throws IOException, ServletException { + + ResponseUtil.out(response,ResponseUtil.resultMap(false,403,"抱歉,您没有访问权限")); + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyAccessDecisionManager.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyAccessDecisionManager.java new file mode 100644 index 0000000..772eafd --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyAccessDecisionManager.java @@ -0,0 +1,54 @@ +package com.sunyard.config.security.permission; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.AccessDecisionManager; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.Iterator; + +/** + * 权限管理决断器 + * 判断用户拥有的权限或角色是否有资源访问权限 + * @author Exrickx + */ +@Slf4j +@Component +public class MyAccessDecisionManager implements AccessDecisionManager { + + @Override + public void decide(Authentication authentication, Object o, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { + + if(configAttributes==null){ + return; + } + Iterator iterator = configAttributes.iterator(); + while (iterator.hasNext()){ + ConfigAttribute c = iterator.next(); + String needPerm = c.getAttribute(); + for(GrantedAuthority ga : authentication.getAuthorities()) { + // 匹配用户拥有的ga 和 系统中的needPerm + if(needPerm.trim().equals(ga.getAuthority())) { + + return; + } + } + } + throw new AccessDeniedException("抱歉,您没有访问权限"); + } + + @Override + public boolean supports(ConfigAttribute configAttribute) { + return true; + } + + @Override + public boolean supports(Class aClass) { + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyFilterSecurityInterceptor.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyFilterSecurityInterceptor.java new file mode 100644 index 0000000..71b1e0d --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyFilterSecurityInterceptor.java @@ -0,0 +1,73 @@ +package com.sunyard.config.security.permission; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.SecurityMetadataSource; +import org.springframework.security.access.intercept.AbstractSecurityInterceptor; +import org.springframework.security.access.intercept.InterceptorStatusToken; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.stereotype.Component; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import java.io.IOException; + +/** + * 权限管理过滤器 + * 监控用户行为 + * @author Exrickx + */ +@Slf4j +@Component +public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { + + @Autowired + private FilterInvocationSecurityMetadataSource securityMetadataSource; + + @Autowired + public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) { + super.setAccessDecisionManager(myAccessDecisionManager); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + + FilterInvocation fi = new FilterInvocation(request, response, chain); + invoke(fi); + } + + public void invoke(FilterInvocation fi) throws IOException, ServletException { + + InterceptorStatusToken token = super.beforeInvocation(fi); + try { + fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); + } finally { + super.afterInvocation(token, null); + } + } + + @Override + public void destroy() { + + } + + @Override + public Class getSecureObjectClass() { + return FilterInvocation.class; + } + + @Override + public SecurityMetadataSource obtainSecurityMetadataSource() { + return this.securityMetadataSource; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyRequestVo.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyRequestVo.java new file mode 100644 index 0000000..19d9712 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyRequestVo.java @@ -0,0 +1,44 @@ +package com.sunyard.config.security.permission; + +import java.util.Objects; + +public class MyRequestVo { + private String url; + private String method; + + public MyRequestVo(String url, String method) { + this.url = url; + this.method = method; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MyRequestVo that = (MyRequestVo) o; + return Objects.equals(url, that.url) && + Objects.equals(method, that.method); + } + + @Override + public int hashCode() { + + return Objects.hash(url, method); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MySecurityMetadataSource.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MySecurityMetadataSource.java new file mode 100644 index 0000000..cd9cb3a --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MySecurityMetadataSource.java @@ -0,0 +1,121 @@ +package com.sunyard.config.security.permission; + +import cn.hutool.core.util.StrUtil; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import com.sunyard.ssp.modules.user.service.IScPermissionService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.SecurityConfig; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * 权限资源管理器 + * 为权限决断器提供支持 + * @author Exrickx + */ +@Slf4j +@Component +public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource { + + @Autowired + private IScPermissionService permissionService; + + private Map> map = null; + + private Map needVerifyMap = null; + + /** + * + */ + public void loadResourceDefine(){ + + map = new HashMap<>(16); + needVerifyMap = new HashMap<>(16); + Collection configAttributes; + ConfigAttribute cfg; + // 获取启用的权限操作请求 + List permissions = permissionService.findByTypeAndStatusOrderBySortOrder(CommonConstant.PERMISSION_OPERATION, CommonConstant.STATUS_NORMAL); + for(ScPermission permission : permissions) { + if(StrUtil.isNotBlank(permission.getTitle())&&StrUtil.isNotBlank(permission.getPath())){ + configAttributes = new ArrayList<>(); + cfg = new SecurityConfig(permission.getTitle()); + //作为MyAccessDecisionManager类的decide的第三个参数 + configAttributes.add(cfg); + //用权限的path作为map的key,用ConfigAttribute的集合作为value + map.put(permission.getPath(), configAttributes); + needVerifyMap.put(permission.getPath(), permission.getNeedVerify()); + } + } + } + + public boolean needVerify(String url){ + if(map == null){ + loadResourceDefine(); + } + + PathMatcher pathMatcher = new AntPathMatcher(); + Iterator iterator = map.keySet().iterator(); + while (iterator.hasNext()) { + String path = iterator.next(); + if (path != null && + StrUtil.isNotBlank(path) && + pathMatcher.match(path,url)) { + + return needVerifyMap.get(path); + } + } + return false; + } + + /** + * 判定用户请求的url是否在权限表中 + * 如果在权限表中,则返回给decide方法,用来判定用户是否有此权限 + * 如果不在权限表中则放行 + * @param o + * @return + * @throws IllegalArgumentException + */ + @Override + public Collection getAttributes(Object o) throws IllegalArgumentException { + + if(map == null){ + loadResourceDefine(); + } + //Object中包含用户请求request + String url = ((FilterInvocation) o).getRequestUrl(); + PathMatcher pathMatcher = new AntPathMatcher(); + Iterator iterator = map.keySet().iterator(); + while (iterator.hasNext()) { + String path = iterator.next(); + if (path != null && + StrUtil.isNotBlank(path) && + pathMatcher.match(path,url) ) { + return map.get(path); + } + } + return null; + } + + @Override + public Collection getAllConfigAttributes() { + return null; + } + + @Override + public boolean supports(Class aClass) { + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/validate/ImageValidateFilter.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/validate/ImageValidateFilter.java new file mode 100644 index 0000000..c6a4ad9 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/validate/ImageValidateFilter.java @@ -0,0 +1,83 @@ +package com.sunyard.config.security.validate; + +import cn.hutool.core.util.StrUtil; +import com.sunyard.config.security.CaptchaProperties; +import com.sunyard.ssp.utils.ResponseUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.util.PathMatcher; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 图形验证码过滤器 + * @author Exrick + */ +@Slf4j +@Configuration +public class ImageValidateFilter extends OncePerRequestFilter { + + @Autowired + private CaptchaProperties captchaProperties; + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + private PathMatcher pathMatcher; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + + // 判断URL是否需要验证 + Boolean flag = false; + String requestUrl = request.getRequestURI(); + for(String url : captchaProperties.getImage()){ + if(pathMatcher.match(url, requestUrl)){ + flag = true; + break; + } + } + if(flag){ + //todo 假u盾登录无需验证码 + String sn = request.getParameter("sn"); + if(StringUtils.isNotBlank(sn)){ + chain.doFilter(request, response); + return; + } + + String captchaId = request.getParameter("captchaId"); + String code = request.getParameter("code"); + if(StrUtil.isBlank(captchaId)||StrUtil.isBlank(code)){ + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"请传入图形验证码所需参数captchaId或code")); + return; + } + String redisCode = redisTemplate.opsForValue().get(captchaId); + if(StrUtil.isBlank(redisCode)){ + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"验证码已过期,请重新获取")); + return; + } + + if(!redisCode.toLowerCase().equals(code.toLowerCase())) { + log.info("验证码错误:code:"+ code +",redisCode:"+redisCode); + ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"图形验证码输入错误")); + return; + } + // 已验证清除key + redisTemplate.delete(captchaId); + // 验证成功 放行 + chain.doFilter(request, response); + return; + } + // 无需验证 放行 + chain.doFilter(request, response); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/PageVo.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/PageVo.java new file mode 100644 index 0000000..0a10b70 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/PageVo.java @@ -0,0 +1,43 @@ +package com.sunyard.ssp.common; + +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Exrickx + */ +@Data +public class PageVo implements Serializable{ + + private static final long serialVersionUID = 1L; + + @TableField(exist = false) + private int pageNumber = 1; + + @TableField(exist = false) + private int pageSize = 10; + + @TableField(exist = false) + private String sort; + + @TableField(exist = false) + private String order = "desc"; + + public PageVo(){ + + } + + /** + * 分页构造 + * @param pageNumber + * @param pageSize + */ + public PageVo(Integer pageNumber,Integer pageSize){ + this.pageNumber = pageNumber; + this.pageSize = pageSize; + } + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/Result.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/Result.java new file mode 100644 index 0000000..959fbe6 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/Result.java @@ -0,0 +1,41 @@ +package com.sunyard.ssp.common; + + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Exrickx + * 前后端交互数据标准 + */ +@Data +public class Result implements Serializable{ + + private static final long serialVersionUID = 1L; + + /** + * 成功标志 + */ + private boolean success; + + /** + * 失败消息 + */ + private String message; + + /** + * 返回代码 + */ + private Integer code; + + /** + * 时间戳 + */ + private long timestamp = System.currentTimeMillis(); + + /** + * 结果对象 + */ + private T result; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/annotation/AuditControllerLog.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/annotation/AuditControllerLog.java new file mode 100644 index 0000000..1cf990d --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/annotation/AuditControllerLog.java @@ -0,0 +1,20 @@ +package com.sunyard.ssp.common.annotation; + + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author fyc + * @des 审计日志注解 + */ +@Target({ElementType.PARAMETER, ElementType.METHOD})//作用在参数和方法上 +@Retention(RetentionPolicy.RUNTIME)//运行时注解 +@Documented//表明这个注解应该被 javadoc工具记录 +public @interface AuditControllerLog { + String description() default ""; + String operateType() default ""; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CertificateConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CertificateConstant.java new file mode 100644 index 0000000..36ec983 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CertificateConstant.java @@ -0,0 +1,18 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/4/3 + * @description: + */ +public interface CertificateConstant { + + //属性字段名 公钥 + String PUB_KEY ="PUB_KEY"; + + //属性字段名 证书原文件 + String CERTIFICATE_CONTENT ="CERTIFICATE_CONTENT"; + + Integer GROUP_SIGN =0; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelConstant.java new file mode 100644 index 0000000..51e09c9 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelConstant.java @@ -0,0 +1,52 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/3/13 + * @description: + */ +public interface ChannelConstant { + + /******************************************************** + @author :tsz + @date :2020/03/13 16:57 + @description : 实施中 + ********************************************************/ + Integer PUBLISH_STATUS_ONE = 1; + /******************************************************** + @author :tsz + @date :2020/03/13 16:57 + @description : 已发布 + ********************************************************/ + Integer PUBLISH_STATUS_TWO = 2; + + /** + *@author :tsz + *@date :2020/03/23 16:46 + *@description : 启用 + */ + Integer ENABLED = 0; + + /** + *@author :tsz + *@date :2020/03/23 16:46 + *@description : 禁用 + */ + Integer DISABLED = 1; + + /** + *@author :tsz + *@date :2020/03/23 17:15 + *@description : 方案验证可用 + */ + Integer VERIFICATION_ENABLED = 0; + + /** + *@author :tsz + *@date :2020/03/23 17:15 + *@description : 方案验证不可用 + */ + Integer VERIFICATION_DISABLED = 1; + + Integer VERIFICATION_NOT = 2; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelSolutionConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelSolutionConstant.java new file mode 100644 index 0000000..26ed29c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelSolutionConstant.java @@ -0,0 +1,10 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/4/1 + * @description: + */ +public interface ChannelSolutionConstant { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CommonConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CommonConstant.java new file mode 100644 index 0000000..6329235 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CommonConstant.java @@ -0,0 +1,227 @@ +package com.sunyard.ssp.common.constant; + +/** + * 常量 + * @author Exrickx + */ +public interface CommonConstant { + + /** + * 用户默认头像 + */ + String USER_DEFAULT_AVATAR = "https://s1.ax1x.com/2018/05/19/CcdVQP.png"; + + /** + * 用户正常状态 + */ + Integer USER_STATUS_NORMAL = 0; + + /** + * 用户禁用状态 + */ + Integer USER_STATUS_LOCK = -1; + + /** + * 普通用户 + */ + Integer USER_TYPE_NORMAL = 0; + + /** + * 极光聊天状态 + */ + Integer USER_JMESSAGE_NORMAL = 0; + + /** + * 管理员 + */ + Integer USER_TYPE_ADMIN = 1; + + /** + * 全部数据权限 + */ + Integer DATA_TYPE_ALL = 0; + + /** + * 自定义数据权限 + */ + Integer DATA_TYPE_CUSTOM = 1; + + /** + * 正常状态 + */ + Integer STATUS_NORMAL = 0; + + /** + * 禁用状态 + */ + Integer STATUS_DISABLE = -1; + + /** + * 删除标志 + */ + Integer DEL_FLAG = 1; + + /** + * 限流标识 + */ + String LIMIT_ALL = "KEEPER_LIMIT_ALL"; + + /** + * 页面类型权限 + */ + Integer PERMISSION_PAGE = 0; + + /** + * 操作类型权限 + */ + Integer PERMISSION_OPERATION = 1; + + /** + * 1级菜单父id + */ + Long PARENT_ID = 0L; + + /** + * 1级菜单父title + */ + String PARENT_TITLE = "一级节点"; + + /** + * 默认分类redis缓存key + */ + String DEFAULT_CATEGORY_REDIS_KEY = "actCategory:userDefaultCateGory:"; + + /** + * 事务审批title + */ + String DEFAULT_CATEGORY_BUSINESS_TITLE = "事务审批"; + + /** + * 事务审批id + */ + String DEFAULT_CATEGORY_BUSINESS_ID = "1"; + + /** + * 支付审批title + */ + String DEFAULT_CATEGORY_PAYMENT_TITLE = "支付审批"; + + /** + * 支付审批id + */ + String DEFAULT_CATEGORY_PAYMENT_ID = "2"; + /** + * 1级菜单 + */ + Integer LEVEL_ONE = 1; + + /** + * 2级菜单 + */ + Integer LEVEL_TWO = 2; + + /** + * 3级菜单 + */ + Integer LEVEL_THREE = 3; + + /** + * 消息发送范围 + */ + Integer MESSAGE_RANGE_ALL = 0; + + /** + * 未读 + */ + Integer MESSAGE_STATUS_UNREAD = 0; + + /** + * 已读 + */ + Integer MESSAGE_STATUS_READ = 1; + + /** + * github登录 + */ + Integer SOCIAL_TYPE_GITHUB = 0; + + /** + * qq登录 + */ + Integer SOCIAL_TYPE_QQ = 1; + + /** + * 微博登录 + */ + Integer SOCIAL_TYPE_WEIBO = 2; + + /** + * 短信验证码key前缀 + */ + String PRE_SMS = "KEEPER_PRE_SMS:"; + + /** + * 邮件验证码key前缀 + */ + String PRE_EMAIL = "KEEPER_PRE_EMAIL:"; + + /** + * 本地文件存储 + */ + Integer OSS_LOCAL = 0; + + /** + * 七牛云OSS存储 + */ + Integer OSS_QINIU = 1; + + /** + * 阿里云OSS存储 + */ + Integer OSS_ALI = 2; + + /** + * 腾讯云COS存储 + */ + Integer OSS_TENCENT = 3; + + /** + * 部门负责人类型 主负责人 + */ + Integer HEADER_TYPE_MAIN = 0; + + /** + * 部门负责人类型 副负责人 + */ + Integer HEADER_TYPE_VICE = 1; + + /** + * 部门负责人类型 不是负责人 + */ + Integer HEADER_TYPE_NONE = -1; + + /** + * 邮箱字段隐藏时显示的值 + */ + String HIDE_EMAIL_STR = "******@***.com"; + + /** + * 手机字段隐藏时显示的值 + */ + String HIDE_MOBILE_STR = "****"; + + String PATH_SEPARATOR = "/"; + + Long DEPARTMENT_ROOT_ID = 0L; + + Long DEFAULT_USER_ROOT_ID = 1L; + + /** + * @author wp + * @Description:盐值位数 + * @date 2021/12/16 + * @param null + * @return + */ + Integer SALT_NUMBER =10; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceConstant.java new file mode 100644 index 0000000..332143e --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceConstant.java @@ -0,0 +1,21 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/5/11 + * @description: + */ +public interface DeviceConstant { + + /** + *@date :2020/05/11 15:52 + *@description : 状态启用 + */ + Integer ENABLE = 0; + + /** + *@date :2020/05/11 15:52 + *@description : 状态禁用 + */ + Integer DISABLE = 1; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceGroupRefConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceGroupRefConstant.java new file mode 100644 index 0000000..c0a2f5f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceGroupRefConstant.java @@ -0,0 +1,19 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/3/26 + * @description: + */ +public interface DeviceGroupRefConstant { + + /** + * 设备分组内的设备状态 启用 + */ + Integer DEVICE_ENABLED = 0; + + /** + * 设备分组内的设备状态 禁用 + */ + Integer DEVICE_DISABLED = 1; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DictDataConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DictDataConstant.java new file mode 100644 index 0000000..14444b3 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DictDataConstant.java @@ -0,0 +1,10 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/5/12 + * @description: + */ +public interface DictDataConstant { + Long [] DICT_ID = {78L,79L,80L}; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/FileConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/FileConstant.java new file mode 100644 index 0000000..463bf35 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/FileConstant.java @@ -0,0 +1,11 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/5/28 + * @description: + */ +public interface FileConstant { + + String FILE_TYPE_PEM = "PEM"; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyAttributeConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyAttributeConstant.java new file mode 100644 index 0000000..e02ccf0 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyAttributeConstant.java @@ -0,0 +1,46 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/4/29 + * @description: + */ +public interface KeyAttributeConstant { + + /** + *@author :tsz + *@date :2020/04/29 14:05 + *@description : 密钥状态 启用 + */ + Integer STATUS_ENABLE = 0; + /** + *@author :tsz + *@date :2020/04/29 14:05 + *@description : 密钥状态 停用 + */ + Integer STATUS_DISABLE = 1; + + /** + *@date : 2020:06:12 14:55 + *@description : 导入开关 + */ + Integer IMPORT_SWITCH_ENABLE = 0; + + /** + *@date : 2020:06:12 14:55 + *@description : 导入开关 + */ + Integer IMPORT_SWITCH_DISABLE = 1; + + /** + *@date : 2020:06:12 15:21 + *@description : 导出 + */ + Integer EXPORT_SWITCH_DISABLE = 1; + + Integer TMPL_TYPE_TWO = 2; + + Integer TMPL_TYPE_THREE = 3; + + Integer TMPL_TYPE_ONE = 1; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyConstant.java new file mode 100644 index 0000000..d1b4264 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyConstant.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/4/7 + * @description: + */ +public interface KeyConstant { + //密钥启用长度限制 + Integer KEYNAME_LENGTH = 1000; + + Integer DEFAULT_VERSION = 0; + + Integer TYPE_ONE = 1; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeySolutionConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeySolutionConstant.java new file mode 100644 index 0000000..321e694 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeySolutionConstant.java @@ -0,0 +1,33 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/4/21 + * @description: + */ +public interface KeySolutionConstant { + + /** + *@author :tsz + *@date :2020/04/21 10:59 + *@description : 模版里边的密钥名称key + */ + String KEY_NAME = "keyName"; + /** + *@date : 2020:06:10 15:55 + *@description : 密钥模板里的密钥类型 + */ + String KEY_TYPE = "keyType"; + /** + *@date : 2020:06:10 15:55 + *@description : 密钥模板里的密钥类型 公钥 + */ + String PK = "PK"; + + /** + *@date : 2020:06:10 15:55 + *@description : 密钥模板里的密钥类型 私钥 + */ + String SK = "SK"; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/NodeConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/NodeConstant.java new file mode 100644 index 0000000..b422d9f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/NodeConstant.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/4/21 + * @description: + */ +public interface NodeConstant { + + /** + *@author :tsz + *@date :2020/04/21 10:50 + *@description : 节点父id默认值 + */ + Long PID = -1L; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ParamConfKeyConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ParamConfKeyConstant.java new file mode 100644 index 0000000..64ce227 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ParamConfKeyConstant.java @@ -0,0 +1,124 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:fyc + * @date:2020/3/17 + * @description: 业务参数key值常量 + */ +public interface ParamConfKeyConstant { + + /** + * 白名单开关 + */ + String IP_WHITELIST_SWITCH = "ipWhitelistSwitch"; + + /** + * 通讯超时时间 + */ + String COMMUNICATE_TIME_OUT = "communicateTimeOut"; + + /** + * 心跳检测时间 + */ + String HEART_DETECT_TIME = "heartDetectTime"; + + /** + * 心跳包 + */ + String HEART_PACKAGE = "heartPackage"; + + /** + * ftp传输路径设置 + */ + String FTP_UPLOAD_PATH = "ftpUploadPath"; + + /** + * B端界面超时时间 + */ + String B_INTERFACE_TIMEOUT = "BInterfaceTimeOut"; + + /** + * 加密机操作审批 + */ + String ENCRYPTION_MACHINE_APPROVAL = "encryptionMachineApproval"; + + /** + * 秘钥操作审批 + */ + String SECRET_KEY_APPROVAL = "secretKeyApproval"; + + /** + * 登入模式 + */ + String LOGIN_METHOD = "loginMethod"; + + /** + * 是否开启图形码登入 + */ + String IS_USE_GRAPHIC_CODE = "isUseGraphicCode"; + + /** + * IP白名单配置类目数值 + */ + Integer IP_WHITELIST_ITEM = 0; + + /** + * 通讯参数类目数值 + */ + Integer COMMUNICATE_PARAM_ITEM = 1; + + /** + * 终端UI参数类目数值 + */ + Integer TERMINAL_PARAM_ITEM = 2; + + /** + * 权限审批类目数值 + */ + Integer AUTHORITY_APPROVAL_PARAM_ITEM = 3; + + /** + * 登入选项类目数值 + */ + Integer LOGIN_PARAM_ITEM = 4; + + /** + * 审批结果true + */ + String APPROVAL_TRUE = "true"; + + /** + * 审批结果false + */ + String APPROVAL_FALSE = "false"; + + /** + * 调试模式类目数值 + */ + Integer SYS_PARAM_ITEM = 7; + + /** + * 调试模式开关 + */ + String SYS_DEBUG_SWITCH = "sysDebugSwitch"; + + /** + * 系统初始化配置文件路劲 + */ + String SYS_PARAM_CONFIG_FILE_PATH = System.getProperty("user.dir") + "/config/sysParam.config.json"; + + /** + * 调试模式开关枚举 + */ + enum SYS_DEBUG_SWITCH_VALUE{ + DEV("dev"), CONFIG("config"), PRODUCT("product"); + private String value; + private SYS_DEBUG_SWITCH_VALUE(String value){ + this.value = value; + } + public String getValue(){ + return value; + } + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ProtocolConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ProtocolConstant.java new file mode 100644 index 0000000..dbf5a76 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ProtocolConstant.java @@ -0,0 +1,22 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/4/21 + * @description: + */ +public interface ProtocolConstant { + + /** + *@author :tsz + *@date :2020/04/21 10:10 + *@description : 入口协议 + */ + String ENTRANCE_TYPE = "0"; + + /** + *@date : 2020:05:25 14:56 + *@description : 加密机协议 + */ + String DEVICE_TYPE = "2"; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/RegexConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/RegexConstant.java new file mode 100644 index 0000000..935c2dd --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/RegexConstant.java @@ -0,0 +1,96 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/4/14 + * @description: 正则规则 + */ +public interface RegexConstant { + + /** + *@author :tsz + *@date :2020/04/14 16:48 + *@description : 节点编号 + */ + String NODE_NUMBER = "\\d{6,12}"; + + /** + *@author :tsz + *@date :2020/04/14 16:49 + *@description : 方案编号 + */ + String KEY_SOLUTION_NUMBER = "[A-Z][A-Z0-9]{2,5}"; + + /** + *@author :tsz + *@date :2020/04/14 16:50 + *@description : 模板编号 + */ + String TMPL_NUMBER = "[A-Z][A-Z0-9]{2,5}"; + + /** + *@author :tsz + *@date :2020/04/14 16:52 + *@description : 密钥名称 + */ + String KEY_NAME = "[A-Z][A-Z0-9]{2,5}"; + + /** + *@author :tsz + *@date :2020/04/15 10:37 + *@description : 普通名称校验规则 1-15位的字符 + */ + String COMMON_NAME = "^.{1,30}$"; + + /** + *@author :tsz + *@date :2020/04/15 10:37 + *@description : 普通名称校验规则 1-30位的数字,字母,汉字 备用,暂时没有用 + */ + String COMMON_NAME_TEST = "^[\\w\\u4e00-\\u9fa5]{2,30}$"; + /** + *@date :2020/05/22 15:47 + *@description : 加密机名称校验 + */ + String DEVICE_NAME = "^.{1,15}$"; + /** + *@date :2020/05/22 15:47 + *@description : 加密机编号校验 + */ + String DEVICE_NUMBER = "^[1-9]\\d*$"; + /** + *@date :2020/05/22 15:47 + *@description : 加密机ipv4校验 + */ + String DEVICE_IPV4 = "^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$"; + /** + *@date :2020/05/22 15:47 + *@description : 加密机ipv6校验 + */ + String DEVICE_IPV6 = "^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$"; + + /** + *@date :2020/05/22 15:47 + *@description : 加密机端口号校验 + */ + String DEVICE_PORT = "^([0-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-5]{2}[0-3][0-5])$"; + + /** + *@date :2020/05/22 15:47 + *@description : 加密机设备型号校验 + */ + String DEVICE_MODEL= "^.{1,15}$"; + + /** + *@date :2020/05/22 15:47 + *@description : 加密机资产类型校验 + */ + String DEVICE_ASSETTYPE= "^.{1,15}$"; + + /** + *@date : 2020:05:28 13:52 + *@description : 证书检测是否是base64加密的 + */ + String CERTIFICATE_CONTENT = "[-]{5}BEGIN[\\s]*[\\w\\s]*[-]{5}[\\s]*[a-zA-Z\\d\\s/+]*[=]{0,2}[\\s]*[-]{5}END[\\s]*[\\w\\s]*[-]{5}[\\s]*"; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SdkConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SdkConstant.java new file mode 100644 index 0000000..a22f768 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SdkConstant.java @@ -0,0 +1,86 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/5/6 + * @description: + */ +public interface SdkConstant { + + /** + *@date : 2020:05:25 14:31 + *@description : 渠道通信key + */ + String SERVER_CLUSTER = "SERVER_CLUSTER"; + + /** + *@date : 2020:05:25 14:32 + *@description : 渠道验证 + */ + String CHANNEL_CHECK = "channel.check"; + + + /** + *@date :2020/05/25 14:02 + *@description : 渠道更新命令 + */ + String CHANNEL_CMD_UPDATE = "channel.enable.update"; + + /** + *@date :2020/05/25 14:02 + *@description : 渠道中的密钥方案变动 + */ + String CHANNEL_CMD_SOLUTION_UPDATE = "channel.solution.update"; + + String PING = "ping"; + + /** + *@date : 2020:05:25 15:04 + *@description : 协议变动 + */ + String PROTO_UPDATE = "proto.update"; + + /** + *@date : 2020:05:25 15:04 + *@description : 加密机组变动 + */ + String HSMGROUP_UPDATE = "hsmgroup.update"; + + /** + *@date : 2020:05:25 15:04 + *@description : 加密机组变动 + */ + String HSM_UPDATE = "hsm.update"; + + /** + *@date : 2020:06:03 11:01 + *@description : 模板变更 + */ + String KEYTEMPLATE_UPDATE= "keytemplate.update"; + + /** + *@date : 2020:05:25 15:04 + *@description : 加密机协议校验 + */ + String PROTO_CHECK = "proto.check"; + + /** + *@date :2020/05/25 14:24 + *@description : 密钥更新命令 + */ + String KEY_CMD_UPDATE = "key.update"; + + String IDENTITY_MANAGER = "Manager"; + + /** + *@date :2020/05/25 14:23 + *@description : sdk通信加密的jks配置文件位置 + */ + String CLIENT_TRUSTSTORE = "config/clientTruststore.jks"; + + /** + *@date :2020/05/25 14:23 + *@description : sdk通信加密的jks 通知字段 + */ + String CLIENT_KEY = "client"; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SecurityConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SecurityConstant.java new file mode 100644 index 0000000..0265448 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SecurityConstant.java @@ -0,0 +1,78 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author Exrickx + */ +public interface SecurityConstant { + + /** + * token分割 + */ + String TOKEN_SPLIT = "Bearer "; + + /** + * JWT签名加密key + */ + String JWT_SIGN_KEY = "keeper"; + + /** + * token参数头 + */ + String HEADER = "accessToken"; + + /** + * 权限参数头 + */ + String AUTHORITIES = "authorities"; + + /** + * 用户选择JWT保存时间参数头 + */ + String SAVE_LOGIN = "saveLogin"; + + /** + * github保存state前缀key + */ + String GITHUB_STATE = "KEEPER_GITHUB:"; + + /** + * qq保存state前缀key + */ + String QQ_STATE = "KEEPER_QQ:"; + + /** + * qq保存state前缀key + */ + String WEIBO_STATE = "KEEPER_WEIBO:"; + + /** + * 交互token前缀key + */ + String TOKEN_PRE = "KEEPER_TOKEN_PRE:"; + + /** + * 用户token前缀key 单点登录使用 + */ + String USER_TOKEN = "KEEPER_USER_TOKEN:"; + + /** + * 用户登陆之后的租户识别id + * @auther: ZS + * @description: + * @param: + * @return: + * @date: 2019/3/20 16:21 + */ + String TENANT_ID = "KEEPER_TENANT_ID"; + + /** + * 更新用户接口url + * @auther: ZS + * @description: + * @param: + * @return: + * @date: 2019/7/31 14:54 + */ + String USER_UPDATE_URL = "/keeper/user/admin/edit"; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SqlConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SqlConstant.java new file mode 100644 index 0000000..8788bc6 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SqlConstant.java @@ -0,0 +1,19 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/3/13 + * @description: + */ +public interface SqlConstant { + + /** + * 通配符 + */ + String SQL_LIKE_WILDCARD = "%"; + + /** + * 数据库排序字段 + */ + String DB_SORT_COLUMN = "SORT_ORDER"; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SspServerConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SspServerConstant.java new file mode 100644 index 0000000..7b64901 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SspServerConstant.java @@ -0,0 +1,9 @@ +package com.sunyard.ssp.common.constant; + +public interface SspServerConstant { + /** + * 通配符 + */ + //sspserver端口号 + int SERVER_PORT = 8800; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ValidatorConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ValidatorConstant.java new file mode 100644 index 0000000..027b5bf --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ValidatorConstant.java @@ -0,0 +1,15 @@ +package com.sunyard.ssp.common.constant; + +public interface ValidatorConstant { + + String POSTION_BASE_NAME = "position"; + + String POSTION_FORM_TITLE_KEY = "title"; + + String DEPARTMENT_BASE_NAME = "department"; + + String PERMISSION_BASE_NAME = "permission"; + + String ROLE_BASE_NAME = "role"; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/WorkflowConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/WorkflowConstant.java new file mode 100644 index 0000000..fa6059c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/WorkflowConstant.java @@ -0,0 +1,50 @@ +package com.sunyard.ssp.common.constant; + +/** + * @author:tsz + * @date:2020/3/13 + * @description: + */ +public interface WorkflowConstant { + + /******************************************************** + @author :tsz + @date :2020/03/13 17:16 + @description : 渠道 + ********************************************************/ + String TYPE_SYSTEM = "system"; + + /** + *@date :2020/05/11 10:59 + *@description : 申请时判断是否可以添加 + */ + Integer [] APPLICANTID_STATUS = {1,2}; + + /** + *@author :tsz + *@date :2020/03/26 13:52 + *@description : 加密机 + */ + String TYPE_ENCRYTOR = "encrytor"; + + /** + *@date :2020/03/24 10:17 + *@description : 审批通过 + */ + Integer STATUS_APPROVAL = 2; + + /** + *@date :2020/03/24 10:17 + *@description : 待审批 + */ + Integer STATUS_PENDING_APPROVAL = 1; + + /** + *@author :tsz + *@date :2020/03/24 10:17 + *@description : 生命周期添加 + */ + Integer LIFECYCLE_ADD = 0; + + Integer ENABLED = 0; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/enums/UserHeaderTypeEnum.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/enums/UserHeaderTypeEnum.java new file mode 100644 index 0000000..6cdad77 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/enums/UserHeaderTypeEnum.java @@ -0,0 +1,52 @@ +package com.sunyard.ssp.common.enums; + +import com.sunyard.ssp.common.constant.CommonConstant; + +public enum UserHeaderTypeEnum { + HEADER_TYPE_MAIN(CommonConstant.HEADER_TYPE_MAIN,"main"), + HEADER_TYPE_VICE(CommonConstant.HEADER_TYPE_VICE,"vice"), + HEADER_TYPE_NONE(CommonConstant.HEADER_TYPE_NONE,"none") + ; + + private Integer key; + private String name; + + UserHeaderTypeEnum(Integer statusKey, String statusName) { + this.key = statusKey; + this.name = statusName; + } + + public Integer getKey() { + return key; + } + + public void setKey(Integer key) { + this.key = key; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public static String getNameByKey(Integer key){ + for (UserHeaderTypeEnum applicationStatus : UserHeaderTypeEnum.values()) { + if(applicationStatus.getKey().equals(key)){ + return applicationStatus.getName(); + } + } + return null; + } + + public static Integer getKeyByName(String name){ + for (UserHeaderTypeEnum applicationStatus : UserHeaderTypeEnum.values()) { + if(applicationStatus.getName().equals(name)){ + return applicationStatus.getKey(); + } + } + return null; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/GlobalExceptionResolver.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/GlobalExceptionResolver.java new file mode 100644 index 0000000..5328e32 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/GlobalExceptionResolver.java @@ -0,0 +1,96 @@ +package com.sunyard.ssp.common.exception; + +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.MyBatisSystemException; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * 全局controller异常处理 + * @auther: ZS + * @description: + * @param: + * @return: + * @date: 2020/5/25 16:24 + */ +@Slf4j +@ControllerAdvice +public class GlobalExceptionResolver { + + /** + * 处理所有不可知异常 + * + * @param e 异常 + * @return json结果 + */ +// @ExceptionHandler(Exception.class) +// @ResponseBody +// public Result handleException(Exception e) { +// // 打印异常堆栈信息 +// return new ResultUtil().setErrorMsg(e.getMessage()); +// } + + /** + * 数据持久层 + */ + @ExceptionHandler(MyBatisSystemException.class) + @ResponseBody + public Result handleMyBatisSystemException(MyBatisSystemException e) { + System.out.println("数据持久层"); + return new ResultUtil().setErrorMsg(e.getLocalizedMessage()); + } + + /** + * 校验器 + */ + @ExceptionHandler(BindException.class) + @ResponseBody + public Result handleBindException(BindException e) { + System.out.println("校验器"); + FieldError fieldError = e.getBindingResult().getFieldError(); + return new ResultUtil().setErrorMsg(fieldError.getDefaultMessage()); + } + +// @ExceptionHandler(MethodArgumentNotValidException.class) +// public R validExceptionHandler(MethodArgumentNotValidException ex) { +// +// return Optional.of(ex.getBindingResult()) +// .map(BindingResult::getFieldError) +// .map(FieldError::getDefaultMessage) +// .map(message -> R.error(400, message)) +// .get(); +// } +// +// private static final List> EX_CLASS = Arrays.asList( +// IllegalArgumentException.class, IllegalStateException.class, +// IllegalFormatException.class, +// SspwebException.class, +// UnsupportedOperationException.class); +// +// @ExceptionHandler(Exception.class) +// public R exceptionHandler(Exception ex) { +// String errorMessage = ThrowableUtils.buildErrorMessage(ex); +// SspwebException serviceException = ThrowableUtils.findException(SspwebException.class, ex); +// if (serviceException != null) { +// log.warn("Validation failed -> {}, errorMessage: \n {}", serviceException.getMessage(), errorMessage); +// return R.error(400, serviceException.getMessage()); +// } +// +// for (Class eClass : EX_CLASS) { +// Exception exception = ThrowableUtils.findException(eClass, ex); +// if (exception == null) { +// continue; +// } +// log.warn("Validation failed -> {} ", errorMessage); +// return R.error(400, exception.getMessage()); +// } +// log.error("系统异常 -> ", ex); +// return R.error("系统异常"); +// } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/LoginFailLimitException.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/LoginFailLimitException.java new file mode 100644 index 0000000..5793448 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/LoginFailLimitException.java @@ -0,0 +1,23 @@ +package com.sunyard.ssp.common.exception; + +import lombok.Data; +import org.springframework.security.authentication.InternalAuthenticationServiceException; + +/** + * @author Exrickx + */ +@Data +public class LoginFailLimitException extends InternalAuthenticationServiceException { + + private String msg; + + public LoginFailLimitException(String msg){ + super(msg); + this.msg = msg; + } + + public LoginFailLimitException(String msg, Throwable t) { + super(msg, t); + this.msg = msg; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/SspwebException.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/SspwebException.java new file mode 100644 index 0000000..038da87 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/SspwebException.java @@ -0,0 +1,19 @@ +package com.sunyard.ssp.common.exception; + +import lombok.Data; + +/** + * @author:tsz + * @date:2020/5/28 + * @description: + */ +@Data +public class SspwebException extends RuntimeException{ + + private String msg; + + public SspwebException(String msg){ + super(msg); + this.msg = msg; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/vo/Captcha.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/vo/Captcha.java new file mode 100644 index 0000000..d5ea462 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/vo/Captcha.java @@ -0,0 +1,19 @@ +package com.sunyard.ssp.common.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Exrickx + */ +@Data +public class Captcha implements Serializable{ + + @ApiModelProperty(value = "验证码id") + private String captchaId; + + @ApiModelProperty(value = "验证码") + private String code; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/config/ServerConfigure.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/config/ServerConfigure.java new file mode 100644 index 0000000..f1900f8 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/config/ServerConfigure.java @@ -0,0 +1,29 @@ +package com.sunyard.ssp.config; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @author:tsz + * @date:2020/3/19 + * @description: + */ +@Data +@Component +//@PropertySource(encoding = "UTF-8", value = {"file:./config/server.properties"}) +public class ServerConfigure { + + @Value("${ip:172.16.17.163}") + private String serverIp; + + @Value("${minPort:8801}") + private int minPort; + + @Value("${maxPort:8802}") + private int maxPort; + + @Value("${sdkPort:8800}") + private int sdkPort; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/aspect/AuditLogAspect.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/aspect/AuditLogAspect.java new file mode 100644 index 0000000..d224a84 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/aspect/AuditLogAspect.java @@ -0,0 +1,244 @@ +package com.sunyard.ssp.modules.monitor.log.aspect; + +import cn.hutool.core.thread.threadlocal.NamedThreadLocal; +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.common.annotation.AuditControllerLog; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLog; +import com.sunyard.ssp.modules.monitor.log.service.IAuditLogService; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.utils.IpUtil; +import com.sunyard.ssp.utils.SecurityUtil; +import com.sunyard.ssp.utils.ThreadPoolUtil; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.lang.reflect.Method; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author fyc + * @description 切点实现类 + */ +@Aspect +@Component +@SuppressWarnings("all") +public class AuditLogAspect { + + private final ObjectMapper objectMapper; + + @Autowired + private IAuditLogService auditLogService; + + @Autowired + private SecurityUtil securityUtil; + + @Autowired + private HttpServletRequest request; + + private static final ThreadLocal beginTimeThreadLocal = new NamedThreadLocal("ThreadLocal beginTime"); + + public AuditLogAspect(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + /** + * 控制器切入层 + */ + @Pointcut("@annotation(com.sunyard.ssp.common.annotation.AuditControllerLog)") + public void controllerAspect(){ + + } + private static ConcurrentHashMap parameters = new ConcurrentHashMap<>(); + /** + * 前置切入 + * @param joinPoint + */ + @Before("controllerAspect()") + public void doBefore(JoinPoint joinPoint) throws ServletException, IOException { + Date beginTime = new Date(); + beginTimeThreadLocal.set(beginTime); + } + /** + * 后置切入 + * @param joinPoint + * @param res + */ + @AfterReturning(pointcut = "controllerAspect()",returning = "res") + public void doAfterReturning(JoinPoint joinPoint, Object res){ + try { + AuditLog auditLog = new AuditLog(); + auditLog.setCreateTime(LocalDateTime.now()); + + //操作用户信息 + ScUser scUser = securityUtil.getCurrUser(); + if(scUser != null){ + auditLog.setOperatorName(scUser.getRealname()); + auditLog.setOperatorId(scUser.getId()); + } + + //操作描述、操作类型和操作结果 + Map map = getAuditLogDescription(joinPoint); + auditLog.setOperateContent((String) map.get("description")); + auditLog.setOperateType((String)map.get("operateType")); + Result result = (Result) res; + if(result.isSuccess()){ + auditLog.setOperateResult("成功"); + }else { + auditLog.setOperateResult("失败"); + } + + //Ip信息 + auditLog.setIpAddress(IpUtil.getIpAddress(request)); + auditLog.setIpInfo("未知"); + + //请求相关 + auditLog.setRequestMothed(request.getMethod()); + auditLog.setRequestPath(request.getRequestURI()); + Map params = request.getParameterMap(); +// auditLog.setRequestParam(requestParamToString(request.getParameterMap())); + String parameters = getParameters(joinPoint); + auditLog.setRequestParam(parameters); + //计算耗时 + Date logStartTime = beginTimeThreadLocal.get(); + long beginTime = beginTimeThreadLocal.get().getTime(); + long endTime = System.currentTimeMillis(); + Long logElapsedTime = endTime - beginTime; + auditLog.setTimeConsuming(logElapsedTime.intValue()); + + //存储日志 + ThreadPoolUtil.getPool().execute(new SaveAuditLogThread(auditLog, auditLogService)); + + }catch (Exception e){ + e.printStackTrace(); + } + } + + /** + * 调用线程存储审计日志 + */ + private static class SaveAuditLogThread implements Runnable{ + + private AuditLog auditLog; + private IAuditLogService iAuditLogService; + + public SaveAuditLogThread(AuditLog auditLog, IAuditLogService iAuditLogService) { + this.auditLog = auditLog; + this.iAuditLogService = iAuditLogService; + } + @Override + public void run() { + iAuditLogService.save(auditLog); + } + } + + + /** + * 从注解中获取描述和类型 + * @param joinPoint + * @return + * @throws Exception + */ + public static Map getAuditLogDescription(JoinPoint joinPoint) throws Exception { + String targetName = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName();//目标方法名 + Object[] arguments = joinPoint.getArgs(); + Class targetClass = Class.forName(targetName); + Method[] methods = targetClass.getMethods(); + Map map = new HashMap(); + for (Method method:methods) { + if (method.getName().equals(methodName)){ + Class[] clazzs = method.getParameterTypes(); + if (clazzs.length==arguments.length){ + String description = method.getAnnotation(AuditControllerLog.class).description(); + String operateType = method.getAnnotation(AuditControllerLog.class).operateType(); + map.put("description",description); + map.put("operateType",operateType); + break; + } + } + } + return map; + } + + /** + * 请求参数map 转化成 string + * @param params + * @return + */ + public static String requestParamToString(Map params){ + Map map = new HashMap(16); + Set keySet = params.keySet(); + + for(String key : keySet){ + String values[] = params.get(key); + map.put(key, Arrays.asList(values).toString()); + } + JSONObject jsonObject = new JSONObject(map); + return jsonObject.toJSONString(); + } + + /** + * @Description: 获取参数列表 + * @param joinPoint 切入点 + * @Return: java.lang.String 参数:值,多个之间使用空格分割 + * @Author: joan.wu + * @Date: 2024/5/21 14:28 + */ + private String getParameters(JoinPoint joinPoint) throws JsonProcessingException { + ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); + Object[] args = joinPoint.getArgs(); + Method method = getMethod(joinPoint); + // 获取方法参数名 + String[] parameterNames = parameterNameDiscoverer.getParameterNames(method); + + // 构造参数名和参数值的对应关系 + StringBuilder argsInfo = new StringBuilder(); + for (int i = 0; i < args.length; i++) { + if (parameterNames == null || parameterNames[i] == null) { + continue; + } + argsInfo.append(parameterNames[i]) + .append(":") + .append(objectMapper.writeValueAsString(args[i])) + .append(" "); + } + return argsInfo.toString(); + + } + /** + * @Description: 通过烦设获取类的方法 + * @param joinPoint 切入点 + * @Return: java.lang.reflect.Method + * @Author: joan.wu + * @Date: 2024/5/21 14:30 + */ + private Method getMethod(JoinPoint joinPoint) { + Signature signature = joinPoint.getSignature(); + if (!(signature instanceof MethodSignature)) { + throw new IllegalArgumentException("This annotation is only supported on method level"); + } + MethodSignature methodSignature = (MethodSignature) signature; + return methodSignature.getMethod(); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/AuditLogController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/AuditLogController.java new file mode 100644 index 0000000..0734d4f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/AuditLogController.java @@ -0,0 +1,165 @@ +package com.sunyard.ssp.modules.monitor.log.controller; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLog; +import com.sunyard.ssp.modules.monitor.log.service.IAuditLogService; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.utils.PageUtil; +import com.sunyard.ssp.utils.ResultUtil; +import com.sunyard.ssp.utils.SecurityUtil; +import com.sunyard.ssp.vo.SearchVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author fyc + * @since 2020-03-18 + */ +@Controller +@Slf4j +@Api(description = "监控管理-审计日志",tags ="监控管理-审计日志") +@RequestMapping("/monitor/auditLog") +@Transactional +public class AuditLogController { + + @Autowired + private IAuditLogService iAuditLogService; + + @Autowired + private SecurityUtil securityUtil; + + @RequestMapping(value = "/getById",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "通过id获取") + public Result get(@RequestParam Integer id){ + + AuditLog entity = iAuditLogService.getById(id); + return new ResultUtil().setData(entity); + } + + + @RequestMapping(value = "/queryList",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "获取列表") + public Result> queryList(@RequestParam Integer pageNumber, + @RequestParam Integer pageSize, + String operateContent, String operateType, + String requestMothed, String readUserName, + String startTime, + String endTime){ + IPage iPage = iAuditLogService.queryList(pageNumber,pageSize, + operateContent,operateType,requestMothed,readUserName,startTime,endTime); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/queryListWithOutPage",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "获取列表") + public Result> queryListWithOutPage(String operateContent, String operateType, + String requestMothed, String readUserName, + String startTime, + String endTime){ + List auditLogs = iAuditLogService.queryList(operateContent,operateType,requestMothed,readUserName,startTime,endTime); + return new ResultUtil>().setData(auditLogs); + } + + @RequestMapping(value = "/user/queryList",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "获取列表") + public Result> userLogQueryList(@RequestParam Integer pageNumber, + @RequestParam Integer pageSize, + String readUserName, + String startTime, + String endTime){ + IPage iPage = iAuditLogService.userLogQueryList(pageNumber,pageSize, + null,"登录",null,readUserName,startTime,endTime); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/user/queryListWithOutPage",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "获取列表") + public Result> userLogQueryListWithOutPage( + String readUserName, + String startTime, + String endTime){ + List auditLogs = iAuditLogService.userLogQueryListWithOutPage(null,"登录",null,readUserName,startTime,endTime); + return new ResultUtil>().setData(auditLogs); + } + + @RequestMapping(value = "/queryNeedSignLog",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "分页条件查询可以签名的日志") + public Result> queryNeedSignLog(@ModelAttribute AuditLog auditLog, + @ModelAttribute SearchVo searchVo, + @ModelAttribute PageVo pageVo){ + org.springframework.data.domain.Page iPage = iAuditLogService.queryNeedSignLog(auditLog,searchVo, PageUtil.initPage(pageVo)); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/user/queryNeedSignLog",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "分页条件查询可以签名的日志") + public Result> userLoginQueryNeedSignLog(@ModelAttribute AuditLog auditLog, + @ModelAttribute SearchVo searchVo, + @ModelAttribute PageVo pageVo){ + org.springframework.data.domain.Page iPage = iAuditLogService.userLoginQueryNeedSignLog(auditLog,searchVo, PageUtil.initPage(pageVo)); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/updateReadStatus",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "更新审批状态") + public Result updateReadStatus(@RequestParam Integer[] ids){ + ScUser scUser = securityUtil.getCurrUser(); + boolean result = iAuditLogService.updateReadStatus(ids,scUser); + if(result){ + return new ResultUtil().setSuccessMsg("审阅日志成功"); + } + return new ResultUtil().setErrorMsg("审阅日志失败"); + } + + + @RequestMapping(value = "/deleteByIds",method = RequestMethod.DELETE) + @ResponseBody + @ApiOperation(value = "批量通过id删除") + public Result delAllByIds(@RequestParam Integer[] ids){ + + for(Integer id:ids){ + iAuditLogService.removeById(id); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } + + @RequestMapping(value = "/truncateTable",method = RequestMethod.DELETE) + @ResponseBody + @ApiOperation(value = "清空表") + public Result truncateTable(){ + + boolean result = iAuditLogService.truncateTable(); + if(result){ + return new ResultUtil().setSuccessMsg("清空表成功"); + } + return new ResultUtil().setErrorMsg("清空表失败"); + } + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/LogDownloadController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/LogDownloadController.java new file mode 100644 index 0000000..d852738 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/LogDownloadController.java @@ -0,0 +1,42 @@ +package com.sunyard.ssp.modules.monitor.log.controller; + +import com.sunyard.ssp.modules.monitor.log.service.LogDownloadService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +@RestController +public class LogDownloadController { + + @Autowired + private LogDownloadService logService; + + @GetMapping("/download/logs") + public ResponseEntity downloadLogs( + @RequestParam("startDate") String startDateStr, + @RequestParam("endDate") String endDateStr) throws IOException { + + LocalDate startDate = LocalDate.parse(startDateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDate endDate = LocalDate.parse(endDateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + + ByteArrayResource resource = logService.downloadLogsAsZip(startDate, endDate); + + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=logs.zip"); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + + return ResponseEntity.ok() + .headers(headers) + .body(resource); + } +} \ No newline at end of file diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/LogSignController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/LogSignController.java new file mode 100644 index 0000000..ff61c55 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/LogSignController.java @@ -0,0 +1,140 @@ +package com.sunyard.ssp.modules.monitor.log.controller; + +/** + * @Auther: wp + * @Date: 2022/2/17 15:34 + * @Description: + */ + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.gson.Gson; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLog; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLogSign; +import com.sunyard.ssp.modules.monitor.log.entity.LogSign; +import com.sunyard.ssp.modules.monitor.log.service.IAuditLogService; +import com.sunyard.ssp.modules.monitor.log.service.IAuditLogSignService; +import com.sunyard.ssp.modules.monitor.log.service.ILogSignService; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.utils.PageUtil; +import com.sunyard.ssp.utils.ResultUtil; +import com.sunyard.ssp.utils.SecurityUtil; +import com.sunyard.ssp.utils.sm3.SM3Digest; +import com.sunyard.ssp.vo.SearchVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@RestController +@Slf4j +@Api(description = "审计日志-签名",tags ="审计日志-签名") +@RequestMapping("/monitor/signLog") +@Transactional +public class LogSignController { + @Autowired + private SecurityUtil securityUtil; + + @Autowired + private IAuditLogSignService auditLogSignService; + + @Autowired + private ILogSignService logSignService; + + @Autowired + private IAuditLogService auditLogService; + + @RequestMapping(value = "/getByCondition", method = RequestMethod.GET) + @ApiOperation(value = "日志签名分页条件查询") + public Result> getByCondition(@ModelAttribute LogSign logSign, + @ModelAttribute SearchVo searchVo, + @ModelAttribute PageVo pageVo) { + try { + org.springframework.data.domain.Page page = logSignService.findByCondition(logSign, searchVo, PageUtil.initPage(pageVo)); + return new ResultUtil>().setData(page); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @RequestMapping(value = "/hash",method = RequestMethod.POST) + @ApiOperation(value = "日志hash") + public Result hash(@RequestParam Long[] ids){ + if(ids==null || ids.length<1){ + return new ResultUtil().setErrorMsg("审计失败,未选择日志"); + } + + ArrayList list = new ArrayList<>(ids.length); + Collections.addAll(list, ids); + + List auditLogList = auditLogService.list(new QueryWrapper().lambda().in(AuditLog::getId, list).orderByAsc(AuditLog::getId)); + if(CollectionUtil.isEmpty(auditLogList) || list.size()!=auditLogList.size()){ + return new ResultUtil().setErrorMsg("审计失败,该日志不存在"); + } + + //序列化后hash + String json = new Gson().toJson(auditLogList); + String res= SM3Digest.encode(json); + return new ResultUtil().setData(res); + } + + @RequestMapping(value = "/sign",method = RequestMethod.POST) + @ApiOperation(value = "日志审计签名") + public Result sign(@ModelAttribute LogSign logSign, @RequestParam Long[] ids){ + try { + if(ids==null || ids.length<1){ + return new ResultUtil().setErrorMsg("审计失败,未选择日志"); + } + if(null==logSign || StrUtil.isBlank(logSign.getSignValue()) || StrUtil.isBlank(logSign.getPublicKey())){ + return new ResultUtil().setErrorMsg("审计失败,签名参数不能为空"); + } + //判断日志是否重复签名 + ArrayList list = new ArrayList<>(ids.length); + Collections.addAll(list, ids); + List logSignList = auditLogSignService.list(new QueryWrapper().lambda().in(AuditLogSign::getLogId, list)); + if(CollectionUtil.isNotEmpty(logSignList)){ + return new ResultUtil().setErrorMsg("审计失败,该日志已审计过"); + } + + ScUser scUser = securityUtil.getCurrUser(); + logSign.setCreateTime(LocalDateTime.now()); + logSign.setOperatorId(scUser.getId()); + logSign.setOperatorName(scUser.getRealname()); + boolean b = logSignService.save(logSign); + if(!b){ + return new ResultUtil().setErrorMsg("审计失败"); + } + for(Long id:ids){ + AuditLogSign auditLogSign=new AuditLogSign(); + auditLogSign.setLogId(id); + auditLogSign.setSignId(logSign.getId()); + boolean save = auditLogSignService.save(auditLogSign); + if(!save){ + return new ResultUtil().setErrorMsg("审计失败"); + } + } + return new ResultUtil().setSuccessMsg("审计成功"); + } catch (Exception e){ + e.getStackTrace(); + log.error("错误类名[{}],错误方法名[{}]", this.getClass().getName(), Thread.currentThread().getStackTrace()[1].getMethodName(), e.getMessage(), e); + throw new RuntimeException("审计失败"); + } + } + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/SysLogController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/SysLogController.java new file mode 100644 index 0000000..db726f0 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/controller/SysLogController.java @@ -0,0 +1,76 @@ +package com.sunyard.ssp.modules.monitor.log.controller; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.modules.monitor.log.entity.SysLog; +import com.sunyard.ssp.modules.monitor.log.service.ISysLogService; +import com.sunyard.ssp.utils.ResultUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + *

+ * 前端控制器 + *

+ * + * @author fyc + * @since 2020-03-31 + */ +@Controller +@Slf4j +@Api(description = "系统日志",tags ="系统日志") +@RequestMapping("/monitor/sysLog") +@Transactional +public class SysLogController { + + @Autowired + private ISysLogService iSysLogService; + + + + @RequestMapping(value = "/queryList",method = RequestMethod.GET) + @ApiOperation(value = "获取系统日志列表") + @ResponseBody + public Result> queryList(@RequestParam Integer pageNumber, + @RequestParam Integer pageSize, + String keyWord, + String startTime, + String endTime){ + + IPage sysLogIPage = iSysLogService.queryList(pageNumber,pageSize,keyWord,startTime,endTime); + return new ResultUtil>().setData(sysLogIPage); + } + + + + @RequestMapping(value = "/deleteByIds",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "批量通过id删除") + public Result delAllByIds(@RequestParam Integer[] ids){ + + for(Integer id:ids){ + iSysLogService.removeById(id); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } + + @RequestMapping(value = "/truncateTable",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "清空表") + public Result truncateTable(){ + boolean result = iSysLogService.truncateTable(); + if(result){ + return new ResultUtil().setSuccessMsg("清空表成功"); + } + return new ResultUtil().setErrorMsg("清空表失败"); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/AuditLog.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/AuditLog.java new file mode 100644 index 0000000..8bed213 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/AuditLog.java @@ -0,0 +1,98 @@ +package com.sunyard.ssp.modules.monitor.log.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author fyc + * @since 2020-03-18 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_AUDIT_LOG") +@ApiModel(value="", description="") +public class AuditLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId("ID") + private Long id; + + @ApiModelProperty(value = "创建时间") + @TableField("CREATE_TIME") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @ApiModelProperty(value = "操作者") + @TableField("OPERATOR_NAME") + private String operatorName; + + @ApiModelProperty(value = "操作者ID") + @TableField("OPERATOR_ID") + private Long operatorId; + + @ApiModelProperty(value = "操作内容") + @TableField("OPERATE_CONTENT") + private String operateContent; + + @ApiModelProperty(value = "IP地址") + @TableField("IP_ADDRESS") + private String ipAddress; + + @ApiModelProperty(value = "IP信息") + @TableField("IP_INFO") + private String ipInfo; + + @ApiModelProperty(value = "请求路径") + @TableField("REQUEST_PATH") + private String requestPath; + + @ApiModelProperty(value = "请求类型") + @TableField("REQUEST_MOTHED") + private String requestMothed; + + @ApiModelProperty(value = "请求数据") + @TableField("REQUEST_PARAM") + private String requestParam; + + @ApiModelProperty(value = "操作类型") + @TableField("OPERATE_TYPE") + private String operateType; + + @ApiModelProperty(value = "操作结果") + @TableField("OPERATE_RESULT") + private String operateResult; + + @ApiModelProperty(value = "耗时") + @TableField("TIME_CONSUMING") + private Integer timeConsuming; + + @ApiModelProperty(value = "阅读状态") + @TableField("READ_STATUS") + private Integer readStatus; + + @ApiModelProperty(value = "批阅人Id") + @TableField("READ_USER_ID") + private Long readUserId; + + @ApiModelProperty(value = "批阅人名字") + @TableField("READ_USER_NAME") + private String readUserName; + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/AuditLogSign.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/AuditLogSign.java new file mode 100644 index 0000000..412c2a7 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/AuditLogSign.java @@ -0,0 +1,35 @@ +package com.sunyard.ssp.modules.monitor.log.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_AUDIT_LOG_SIGN") +@ApiModel(value="日志签名关联表", description="") +public class AuditLogSign implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId("ID") + private Long id; + + @ApiModelProperty(value = "日志签名id") + @TableField("SIGN_ID") + private Long signId; + + @ApiModelProperty(value = "日志id") + @TableField("LOG_ID") + private Long logId; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/LogSign.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/LogSign.java new file mode 100644 index 0000000..e67ec3b --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/LogSign.java @@ -0,0 +1,64 @@ +package com.sunyard.ssp.modules.monitor.log.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import javax.persistence.Transient; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_LOG_SIGN") +@ApiModel(value="日志签名表", description="") +public class LogSign implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId("ID") + private Long id; + + @ApiModelProperty(value = "创建时间") + @TableField("CREATE_TIME") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @ApiModelProperty(value = "签名人id") + @TableField("OPERATOR_ID") + private Long operatorId; + + @ApiModelProperty(value = "签名人真实姓名") + @TableField("OPERATOR_NAME") + private String operatorName; + + @ApiModelProperty(value = "签名值") + @TableField("SIGN_VALUE") + private String signValue; + + @ApiModelProperty(value = "公钥") + @TableField("PUBLICKEY") + private String publicKey; + + @ApiModelProperty(value = "U盾序号") + @TableField("DEVICE_ID") + private String deviceId; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "关联日志详情,按id排序") + private List auditLogs; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "关联日志总数") + private Integer auditLogsCount; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/SysLog.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/SysLog.java new file mode 100644 index 0000000..bdda650 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/entity/SysLog.java @@ -0,0 +1,69 @@ +package com.sunyard.ssp.modules.monitor.log.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author fyc + * @since 2020-03-31 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_SYS_LOG") +@ApiModel(value="", description="") +public class SysLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId("ID") + private Long id; + + @ApiModelProperty(value = "创建时间") + @TableField("CREATE_TIME") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @ApiModelProperty(value = "文件名") + @TableField("FILE_NAME") + private String fileName; + + @ApiModelProperty(value = "行号") + @TableField("LINE") + private String line; + + @ApiModelProperty(value = "线程") + @TableField("THREAD") + private String thread; + + @ApiModelProperty(value = "日志级别") + @TableField("LOG_LEVEL") + private String logLevel; + + @ApiModelProperty(value = "信息") + @TableField("MESSAGE") + private String message; + + @ApiModelProperty(value = "Java类") + @TableField("CLAZZ") + private String clazz; + + @ApiModelProperty(value = "类中的方法") + @TableField("METHOD") + private String method; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/AuditLogMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/AuditLogMapper.java new file mode 100644 index 0000000..e3e8025 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/AuditLogMapper.java @@ -0,0 +1,197 @@ +package com.sunyard.ssp.modules.monitor.log.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLog; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author fyc + * @since 2020-03-18 + */ +@Repository +public interface AuditLogMapper extends BaseMapper { + + /** + * 分页查询接口 + * + * @param iPage + * @param operateContent + * @param operateType + * @param requestMethod + * @param readUserName + * @param startTime + * @param endTime + * @return + */ + @Select("") + List queryList(IPage iPage, + @Param("operateContent") String operateContent, + @Param("operateType") String operateType, + @Param("requestMethod") String requestMethod, + @Param("readUserName") String readUserName, + @Param("startTime") LocalDate startTime, + @Param("endTime") LocalDate endTime); + + + /** + * 分页查询接口 + * + * @param iPage + * @param operateContent + * @param operateType + * @param requestMethod + * @param readUserName + * @param startTime + * @param endTime + * @return + */ + @Select("") + List userLogQueryList(IPage iPage, + @Param("operateContent") String operateContent, + @Param("operateType") String operateType, + @Param("requestMethod") String requestMethod, + @Param("readUserName") String readUserName, + @Param("startTime") LocalDate startTime, + @Param("endTime") LocalDate endTime); + + /** + * 查询接口 + * + * @param operateContent + * @param operateType + * @param requestMethod + * @param readUserName + * @param startTime + * @param endTime + * @return + */ + @Select("") + List queryList(@Param("operateContent") String operateContent, + @Param("operateType") String operateType, + @Param("requestMethod") String requestMethod, + @Param("readUserName") String readUserName, + @Param("startTime") LocalDate startTime, + @Param("endTime") LocalDate endTime); + + /** + * 查询接口 + * + * @param operateContent + * @param operateType + * @param requestMethod + * @param readUserName + * @param startTime + * @param endTime + * @return + */ + @Select("") + List userLogQueryListWithOutPage(@Param("operateContent") String operateContent, + @Param("operateType") String operateType, + @Param("requestMethod") String requestMethod, + @Param("readUserName") String readUserName, + @Param("startTime") LocalDate startTime, + @Param("endTime") LocalDate endTime); + + /** + * 清空表 + * + * @return + */ + @Update("") + Integer truncateTable(); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/AuditLogSignMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/AuditLogSignMapper.java new file mode 100644 index 0000000..1b4d639 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/AuditLogSignMapper.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.monitor.log.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLogSign; +import org.springframework.stereotype.Repository; + +/** + * @Auther: wp + * @Date: 2022/2/17 11:20 + * @Description: + */ +@Repository +public interface AuditLogSignMapper extends BaseMapper { + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/LogSignMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/LogSignMapper.java new file mode 100644 index 0000000..f3f59ed --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/LogSignMapper.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.monitor.log.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.monitor.log.entity.LogSign; +import org.springframework.stereotype.Repository; + +/** + * @Auther: wp + * @Date: 2022/2/17 11:20 + * @Description: + */ +@Repository +public interface LogSignMapper extends BaseMapper { + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/SysLogMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/SysLogMapper.java new file mode 100644 index 0000000..714ab38 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/mapper/SysLogMapper.java @@ -0,0 +1,47 @@ +package com.sunyard.ssp.modules.monitor.log.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.sunyard.ssp.modules.monitor.log.entity.SysLog; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author fyc + * @since 2020-03-31 + */ +@Repository +public interface SysLogMapper extends BaseMapper { + + @Select("") + List queryList(IPage iPage, + @Param("keyWord") String keyWord, + @Param("startTime") LocalDate startTime, + @Param("endTime")LocalDate endTime); + + @Update("") + Integer truncateTable(); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/IAuditLogService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/IAuditLogService.java new file mode 100644 index 0000000..285cca1 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/IAuditLogService.java @@ -0,0 +1,113 @@ +package com.sunyard.ssp.modules.monitor.log.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLog; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.vo.SearchVo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author fyc + * @since 2020-03-18 + */ +public interface IAuditLogService extends IService { + + /** + * 获取审计日志列表 + * @param pageNumber + * @param pageSize + * @param operateContent + * @param operateType + * @param readStatus + * @param readUserName + * @param startTime + * @param endTime + * @return + */ + IPage queryList(Integer pageNumber, Integer pageSize, + String operateContent, String operateType, + String readStatus, String readUserName, + String startTime, String endTime); + + /** + * 获取审计日志列表 + * @param pageNumber + * @param pageSize + * @param operateContent + * @param operateType + * @param readStatus + * @param readUserName + * @param startTime + * @param endTime + * @return + */ + IPage userLogQueryList(Integer pageNumber, Integer pageSize, + String operateContent, String operateType, + String readStatus, String readUserName, + String startTime, String endTime); + + /** + * 获取审计日志列表不带分页数据 + * @param operateContent + * @param operateType + * @param readStatus + * @param readUserName + * @param startTime + * @param endTime + * @return + */ + List queryList(String operateContent, String operateType, + String readStatus, String readUserName, + String startTime, String endTime); + + + /** + * 获取审计日志列表不带分页数据 + * @param operateContent + * @param operateType + * @param readStatus + * @param readUserName + * @param startTime + * @param endTime + * @return + */ + List userLogQueryListWithOutPage(String operateContent, String operateType, + String readStatus, String readUserName, + String startTime, String endTime); + + /** + * 清空表 + * @return + */ + Boolean truncateTable(); + + + /** + * 更新审计日志的审计状态 + * @param ids 日志Id ,支持批量 + * @param scUser 批阅的用户 + * @return + */ + Boolean updateReadStatus(Integer ids[], ScUser scUser); + + /** + * @author wp + * @Description: 根据签名id查询关联的日志详情,按id排序 + * @date 2022/2/17 + * @param signId + * @return java.util.List + */ + List getByLogSignId(Long signId); + + + Page queryNeedSignLog(AuditLog auditLog, SearchVo searchVo, Pageable pageable); + Page userLoginQueryNeedSignLog(AuditLog auditLog, SearchVo searchVo, Pageable pageable); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/IAuditLogSignService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/IAuditLogSignService.java new file mode 100644 index 0000000..8f3969c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/IAuditLogSignService.java @@ -0,0 +1,12 @@ +package com.sunyard.ssp.modules.monitor.log.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLogSign; + +/** + * @Auther: wp + * @Date: 2022/2/17 11:22 + * @Description: 日志签名关联服务接口 + */ +public interface IAuditLogSignService extends IService { +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/ILogSignService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/ILogSignService.java new file mode 100644 index 0000000..99ac731 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/ILogSignService.java @@ -0,0 +1,17 @@ +package com.sunyard.ssp.modules.monitor.log.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.monitor.log.entity.LogSign; +import com.sunyard.ssp.vo.SearchVo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +/** + * @Auther: wp + * @Date: 2022/2/17 11:22 + * @Description: 日志签名服务接口 + */ +public interface ILogSignService extends IService { + + Page findByCondition(LogSign logSign, SearchVo searchVo, Pageable pageable); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/ISysLogService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/ISysLogService.java new file mode 100644 index 0000000..5dd8a94 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/ISysLogService.java @@ -0,0 +1,33 @@ +package com.sunyard.ssp.modules.monitor.log.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.monitor.log.entity.SysLog; + +/** + *

+ * 服务类 + *

+ * + * @author fyc + * @since 2020-03-31 + */ +public interface ISysLogService extends IService { + + /** + * 系统日志列表 + * @param pageNumber + * @param pageSize + * @param keyWord + * @param startTime + * @param endTime + * @return + */ + IPage queryList(Integer pageNumber,Integer pageSize,String keyWord,String startTime,String endTime); + + /** + * 清空日志 + * @return + */ + Boolean truncateTable(); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/LogDownloadService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/LogDownloadService.java new file mode 100644 index 0000000..50f45ba --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/service/LogDownloadService.java @@ -0,0 +1,10 @@ +package com.sunyard.ssp.modules.monitor.log.service; + +import org.springframework.core.io.ByteArrayResource; + +import java.io.IOException; +import java.time.LocalDate; + +public interface LogDownloadService { + ByteArrayResource downloadLogsAsZip(LocalDate startDate, LocalDate endDate) throws IOException; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/AuditLogServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/AuditLogServiceImpl.java new file mode 100644 index 0000000..e0d74ee --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/AuditLogServiceImpl.java @@ -0,0 +1,183 @@ +package com.sunyard.ssp.modules.monitor.log.serviceimpl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLog; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLogSign; +import com.sunyard.ssp.modules.monitor.log.mapper.AuditLogMapper; +import com.sunyard.ssp.modules.monitor.log.mapper.AuditLogSignMapper; +import com.sunyard.ssp.modules.monitor.log.service.IAuditLogService; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.utils.DateUtil; +import com.sunyard.ssp.vo.SearchVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author fyc + * @since 2020-03-18 + */ +@Slf4j +@Service +@Transactional +public class AuditLogServiceImpl extends ServiceImpl implements IAuditLogService { + + @Autowired + private AuditLogMapper auditLogMapper; + + @Autowired + private AuditLogSignMapper auditLogSignMapper; + + @Override + public IPage queryList(Integer pageNumber, Integer pageSize, + String operateContent, String operateType, + String requestMethod, String readUserName, + String startTime, String endTime) { + + Page auditLogPage = new Page<>(pageNumber, pageSize); + IPage auditLogIPage = auditLogPage.setRecords(auditLogMapper.queryList(auditLogPage, operateContent, operateType, requestMethod, readUserName, DateUtil.StringToDateOrNull(startTime), DateUtil.StringToDateOrNull(endTime))); + return auditLogIPage; + } + + @Override + public IPage userLogQueryList(Integer pageNumber, Integer pageSize, + String operateContent, String operateType, + String requestMethod, String readUserName, + String startTime, String endTime) { + + Page auditLogPage = new Page<>(pageNumber, pageSize); + IPage auditLogIPage = auditLogPage.setRecords(auditLogMapper.userLogQueryList(auditLogPage, operateContent, operateType, requestMethod, readUserName, DateUtil.StringToDateOrNull(startTime), DateUtil.StringToDateOrNull(endTime))); + return auditLogIPage; + } + + @Override + public List queryList(String operateContent, String operateType, String readStatus, String readUserName, String startTime, String endTime) { + return auditLogMapper.queryList(operateContent, operateType, readStatus, readUserName, DateUtil.StringToDateOrNull(startTime), DateUtil.StringToDateOrNull(endTime)); + } + + @Override + public List userLogQueryListWithOutPage(String operateContent, String operateType, String readStatus, String readUserName, String startTime, String endTime) { + return auditLogMapper.userLogQueryListWithOutPage(operateContent, operateType, readStatus, readUserName, DateUtil.StringToDateOrNull(startTime), DateUtil.StringToDateOrNull(endTime)); + } + + @Override + public Boolean truncateTable() { + Integer i = auditLogMapper.truncateTable(); + if (i < 0) { + return false; + } + return true; + } + + @Override + public Boolean updateReadStatus(Integer[] ids, ScUser scUser) { + Boolean result = true; + for (Integer id : ids) { + AuditLog auditLog = auditLogMapper.selectById(id); + if (auditLog.getReadStatus() == 0) { + auditLog.setReadStatus(1); + auditLog.setReadUserId(scUser.getId()); + auditLog.setReadUserName(scUser.getRealname()); + Integer i = auditLogMapper.updateById(auditLog); + if (i < 1) { + result = false; + break; + } + } + } + return result; + } + + @Override + public List getByLogSignId(Long signId) { + List logSigns = auditLogSignMapper.selectList(new QueryWrapper().lambda().eq(AuditLogSign::getSignId, signId)); + if (CollectionUtil.isEmpty(logSigns)) { + return null; + } + List ids = logSigns.stream().map(AuditLogSign::getLogId).collect(Collectors.toList()); + return baseMapper.selectList(new QueryWrapper().lambda().in(AuditLog::getId, ids).orderByAsc(AuditLog::getId)); + } + + @Override + public org.springframework.data.domain.Page queryNeedSignLog(AuditLog auditLog, SearchVo searchVo, Pageable pageable) { + LambdaQueryWrapper wrapper = new QueryWrapper().lambda(); + if (StrUtil.isNotBlank(auditLog.getOperateContent())) { + wrapper.like(AuditLog::getOperateContent, auditLog.getOperateContent()); + } + if (StrUtil.isNotBlank(auditLog.getOperateType())) { + wrapper.like(AuditLog::getOperateType, auditLog.getOperateType()); + } + if (StrUtil.isNotBlank(auditLog.getRequestMothed())) { + wrapper.eq(AuditLog::getRequestMothed, auditLog.getRequestMothed()); + } + if (StrUtil.isNotBlank(auditLog.getReadUserName())) { + wrapper.like(AuditLog::getReadUserName, auditLog.getReadUserName()); + } + //创建时间 + if (StrUtil.isNotBlank(searchVo.getStartDate()) && StrUtil.isNotBlank(searchVo.getEndDate())) { + Date start = cn.hutool.core.date.DateUtil.parse(searchVo.getStartDate()); + Date end = cn.hutool.core.date.DateUtil.parse(searchVo.getEndDate()); + wrapper.between(AuditLog::getCreateTime, start, cn.hutool.core.date.DateUtil.endOfDay(end)); + } + wrapper.eq(AuditLog::getReadStatus, 1); + //过滤已签名的日志 + List auditLogSigns = auditLogSignMapper.selectList(null); + if (CollectionUtil.isNotEmpty(auditLogSigns)) { + List logids = auditLogSigns.stream().map(AuditLogSign::getLogId).collect(Collectors.toList()); + wrapper.notIn(AuditLog::getId, logids); + } + wrapper.orderByDesc(AuditLog::getCreateTime); + IPage page = new Page<>(pageable.getPageNumber() + 1, pageable.getPageSize()); + IPage auditLogList = baseMapper.selectPage(page, wrapper); + + org.springframework.data.domain.Page res = new PageImpl(auditLogList.getRecords(), pageable, auditLogList.getTotal()); + return res; + } + + + @Override + public org.springframework.data.domain.Page userLoginQueryNeedSignLog(AuditLog auditLog, SearchVo searchVo, Pageable pageable) { + LambdaQueryWrapper wrapper = new QueryWrapper().lambda(); + wrapper.like(AuditLog::getOperateType, "登录"); + + if (StrUtil.isNotBlank(auditLog.getReadUserName())) { + wrapper.like(AuditLog::getReadUserName, auditLog.getReadUserName()); + } + //创建时间 + if (StrUtil.isNotBlank(searchVo.getStartDate()) && StrUtil.isNotBlank(searchVo.getEndDate())) { + Date start = cn.hutool.core.date.DateUtil.parse(searchVo.getStartDate()); + Date end = cn.hutool.core.date.DateUtil.parse(searchVo.getEndDate()); + wrapper.between(AuditLog::getCreateTime, start, cn.hutool.core.date.DateUtil.endOfDay(end)); + } + wrapper.eq(AuditLog::getReadStatus, 1); + //过滤已签名的日志 + List auditLogSigns = auditLogSignMapper.selectList(null); + if (CollectionUtil.isNotEmpty(auditLogSigns)) { + List logids = auditLogSigns.stream().map(AuditLogSign::getLogId).collect(Collectors.toList()); + wrapper.notIn(AuditLog::getId, logids); + } + wrapper.orderByDesc(AuditLog::getCreateTime); + IPage page = new Page<>(pageable.getPageNumber() + 1, pageable.getPageSize()); + IPage auditLogList = baseMapper.selectPage(page, wrapper); + + org.springframework.data.domain.Page res = new PageImpl(auditLogList.getRecords(), pageable, auditLogList.getTotal()); + return res; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/AuditLogSignServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/AuditLogSignServiceImpl.java new file mode 100644 index 0000000..204259c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/AuditLogSignServiceImpl.java @@ -0,0 +1,20 @@ +package com.sunyard.ssp.modules.monitor.log.serviceimpl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLogSign; +import com.sunyard.ssp.modules.monitor.log.mapper.AuditLogSignMapper; +import com.sunyard.ssp.modules.monitor.log.service.IAuditLogSignService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @Auther: wp + * @Date: 2022/2/17 11:25 + * @Description: + */ +@Slf4j +@Service +@Transactional +public class AuditLogSignServiceImpl extends ServiceImpl implements IAuditLogSignService { +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/LogDownloadServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/LogDownloadServiceImpl.java new file mode 100644 index 0000000..c23c312 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/LogDownloadServiceImpl.java @@ -0,0 +1,83 @@ +package com.sunyard.ssp.modules.monitor.log.serviceimpl; + +import com.sunyard.ssp.modules.monitor.log.service.LogDownloadService; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.stereotype.Service; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +@Service +public class LogDownloadServiceImpl implements LogDownloadService { + + private static final String LOG_BASE_PATH = "/app/log/"; + private static final DateTimeFormatter folderFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); // 用于遍历月份的目录格式 + private static final DateTimeFormatter fileFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 用于解析文件名中的日期格式 + + /** + * 下载指定日期范围内的日志文件为ZIP格式。 + * + * @param startDate 开始日期(包含) + * @param endDate 结束日期(包含) + * @return 包含所选日志文件的ByteArrayResource对象 + * @throws IOException 如果读取文件或创建ZIP时发生IO错误 + */ + @Override + public ByteArrayResource downloadLogsAsZip(LocalDate startDate, LocalDate endDate) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ZipOutputStream zos = new ZipOutputStream(baos)) { + // 遍历指定日期范围内的每个月份 + for (LocalDate date = startDate.withDayOfMonth(1); !date.isAfter(endDate); date = date.plusMonths(1)) { + Files.list(Paths.get(LOG_BASE_PATH, folderFormatter.format(date))) + .filter(path -> isRelevantLogFile(path, startDate, endDate)) + .forEach(path -> { + ZipEntry zipEntry = new ZipEntry(path.getFileName().toString()); + try { + zos.putNextEntry(zipEntry); + Files.copy(path, zos); + zos.closeEntry(); + } catch (IOException e) { + throw new RuntimeException("压缩日志文件时发生错误", e); + } + }); + } + zos.finish(); + } + return new ByteArrayResource(baos.toByteArray(), "logs.zip"); + } + + /** + * 判断给定路径是否是指定日期范围内的相关日志文件。 + * + * @param path 文件路径 + * @param startDate 开始日期 + * @param endDate 结束日期 + * @return 如果文件在指定日期范围内则返回true,否则返回false + */ + private boolean isRelevantLogFile(Path path, LocalDate startDate, LocalDate endDate) { + String fileName = path.getFileName().toString(); + if (!fileName.endsWith(".log.gz")) { + return false; + } + + // 解析文件名中的日期 + String dateString = fileName.substring("sspweb-DEBUG-".length(), fileName.indexOf('_', "sspweb-DEBUG-".length())); + LocalDate fileDate; + try { + fileDate = LocalDate.parse(dateString, fileFormatter); + } catch (Exception e) { + // 如果无法解析日期,忽略该文件 + return false; + } + + // 检查文件日期是否在指定范围内 + return !fileDate.isBefore(startDate) && !fileDate.isAfter(endDate); + } +} \ No newline at end of file diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/LogSignServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/LogSignServiceImpl.java new file mode 100644 index 0000000..5cbe48e --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/LogSignServiceImpl.java @@ -0,0 +1,78 @@ +package com.sunyard.ssp.modules.monitor.log.serviceimpl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLog; +import com.sunyard.ssp.modules.monitor.log.entity.LogSign; +import com.sunyard.ssp.modules.monitor.log.mapper.LogSignMapper; +import com.sunyard.ssp.modules.monitor.log.service.IAuditLogService; +import com.sunyard.ssp.modules.monitor.log.service.ILogSignService; +import com.sunyard.ssp.vo.SearchVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; + +/** + * @Auther: wp + * @Date: 2022/2/17 11:25 + * @Description: + */ +@Slf4j +@Service +@Transactional +public class LogSignServiceImpl extends ServiceImpl implements ILogSignService { + + @Autowired + private IAuditLogService auditLogService; + + @Override + public Page findByCondition(LogSign logSign, SearchVo searchVo, Pageable pageable) { + LambdaQueryWrapper wrapper = new QueryWrapper().lambda(); + + if(null!=logSign.getOperatorId()){ + wrapper.eq(LogSign::getOperatorId,logSign.getOperatorId()); + } + + if(StrUtil.isNotBlank(logSign.getOperatorName())){ + wrapper.like(LogSign::getOperatorName,logSign.getOperatorName()); + } + + //创建时间 + if(StrUtil.isNotBlank(searchVo.getStartDate())&&StrUtil.isNotBlank(searchVo.getEndDate())){ + Date start = DateUtil.parse(searchVo.getStartDate()); + Date end = DateUtil.parse(searchVo.getEndDate()); + wrapper.between(LogSign::getCreateTime,start,DateUtil.endOfDay(end)); + } + wrapper.orderByDesc(LogSign::getCreateTime); + IPage page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>( pageable.getPageNumber()+1,pageable.getPageSize()); + IPage logSignList = baseMapper.selectPage(page,wrapper); + + //查询关联日志详情 + List records = logSignList.getRecords(); + if(CollectionUtils.isNotEmpty(records)){ + for (LogSign sign:records){ + List auditLogs = auditLogService.getByLogSignId(sign.getId()); + if(CollectionUtil.isNotEmpty(auditLogs)){ + sign.setAuditLogs(auditLogs); + sign.setAuditLogsCount(auditLogs.size()); + } + } + } + + Page res = new PageImpl(records,pageable,logSignList.getTotal()); + return res; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/SysLogServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/SysLogServiceImpl.java new file mode 100644 index 0000000..a403cfc --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/monitor/log/serviceimpl/SysLogServiceImpl.java @@ -0,0 +1,46 @@ +package com.sunyard.ssp.modules.monitor.log.serviceimpl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.monitor.log.entity.SysLog; +import com.sunyard.ssp.modules.monitor.log.mapper.SysLogMapper; +import com.sunyard.ssp.modules.monitor.log.service.ISysLogService; +import com.sunyard.ssp.utils.DateUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 服务实现类 + *

+ * + * @author fyc + * @since 2020-03-31 + */ +@Slf4j +@Service +@Transactional +public class SysLogServiceImpl extends ServiceImpl implements ISysLogService { + + @Autowired + private SysLogMapper sysLogMapper; + + @Override + public IPage queryList(Integer pageNumber, Integer pageSize, String keyWord, String startTime, String endTime) { + Page sysLogPage = new Page<>(pageNumber,pageSize); + IPage sysLogIPage = sysLogPage.setRecords(sysLogMapper.queryList(sysLogPage,keyWord, DateUtil.StringToDate(startTime),DateUtil.StringToDate(endTime))); + return sysLogIPage; + } + + @Override + public Boolean truncateTable() { + Integer i = sysLogMapper.truncateTable(); + if (i < 0) { + return false; + } + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/ASymmetricKeyToolService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/ASymmetricKeyToolService.java new file mode 100644 index 0000000..d4c2243 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/ASymmetricKeyToolService.java @@ -0,0 +1,114 @@ +package com.sunyard.ssp.modules.sdk; + +import com.sunyard.ssp.UnionMessage; +import com.sunyard.ssp.constv.Alg; +import com.sunyard.ssp.constv.KeyPairType; +import com.sunyard.ssp.constv.KeyType; +import com.sunyard.ssp.constv.PublicKeyType; + +/** + * @author:tsz + * @date:2020/5/21 + * @description: 非对称密钥工具类 + */ +public interface ASymmetricKeyToolService { + + /** + * @param : + * @return : + * @date :2020/05/21 15:10 + * @description : 生成临时用的密钥对 未实现 + */ + UnionMessage genTempKeyPair(KeyPairType keypairType, Alg alg, int keylenMultiple); + + /** + * @param : + * @return : + * @date :2020/05/21 15:11 + * @description : 生成密钥对 未实现 + */ + boolean genKeyPair(String pk, String sk, KeyType keyType, Alg alg, int keylenMultiple); + + /** + * @param : pk 公钥的名字 + * @param : type RAW 裸公钥,DER 格式,Base64 格式 + * @param : pkv 公钥值 + * @param : startTime 开始时间 + * @param : period 有效期 + * @return : + * @date :2020/05/21 15:12 + * @description : 导入 生成公钥 + */ + void importPk(String pk, PublicKeyType type, byte[] pkv, Long startTime, Long period); + + /** + * @param : pk 公钥的名字 + * @param : type RAW 裸公钥,DER 格式,Base64 格式 + * @param : pkv 公钥值 + * @return : + * @date :2020/05/21 15:12 + * @description : 导入 更新公钥 + */ + void importPk(String pk, PublicKeyType type, byte[] pkv); + + /** + * @param : pk 公钥的名字 + * @param : type RAW 裸公钥,DER 格式,Base64 格式 + * @return : + * @date :2020/05/21 15:14 + * @description : 导出公钥 + */ + byte[] outputPk(String pk, PublicKeyType type); + + /** + * @param :alg 非对称算法 + * @param :key 加密用的密钥的名字,可以是公钥可以是私钥 + * @param :data 原始数据 + * @date :2020/06/22 14:25 + * @description : 非对称公钥加密 + */ + byte[] ASYMPKEncryptData(Alg alg, String pk, byte[] data); + + /** + * @param : alg 非对称算法 + * @param : key 加密用的密钥的名字,可以是公钥可以是私钥 公钥加密则对方用私钥解密,私钥加密则对方用公钥解密。 + * @param : data 原始数据 + * @date :2020/06/22 14:27 + * @description : 非对称私钥解密 + */ + byte[] ASYMSKDecryptData(Alg alg, String sk, byte[] data); + + + /** + * @author wp + * @Description: p1验签 + * @date 2021/9/22 + * @param alg 非对称算法 + * @param orgData 原始数据 + * @param sign 签名数据 + * @return boolean + */ + boolean PKCS1Verify(Alg alg, byte[] orgData, byte[] sign); + + + /** + * @param alg 非对称算法 + * @param pk 外部公钥 + * @param data 原始数据 + * @return byte[] + * @author wp + * @Description: 外部公钥加密 + * @date 2021/9/22 + */ + byte[] ASYMEncryptDataByOutPK(Alg alg, String pk, String data); + + /** + * @author wp + * @Description: p1签名 + * @date 2021/9/22 + * @param alg 非对称算法 + * @param data 原始数据 + * @return byte[] + */ + byte[] PKCS1Sign(Alg alg, byte[] data); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/CertService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/CertService.java new file mode 100644 index 0000000..4c7ed21 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/CertService.java @@ -0,0 +1,48 @@ +package com.sunyard.ssp.modules.sdk; + +import com.sunyard.ssp.proto.sdk.Sdk; + +/** + * @author:tsz + * @date:2020/5/21 + * @description: + */ +public interface CertService { + + /** + * @param : cert + * @return : + * @date :2020/05/21 14:26 + * @description : 证书检测 + */ + Sdk.CIX509 catCert(String cert); + + /** + * @param : cert + * @return : + * @date :2020/05/21 14:26 + * @description : 证书检测 + */ + Sdk.CIX509 catCert(String cert,String sk); + + /** + * @param : pk + * @param : domain + * @return : + * @date :2020/05/21 14:24 + * @description : 证书请求生成,更新密钥 + */ + String applyCertRequest(String pk, String domain); + + /** + *@date :2020/06/09 14:09 + *@description : 证书请求生成,生成密钥 + * @param : + * @return : + */ + String applyCertRequest(String pk, String domain,Long startTime,Long period); + + long ping(); + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/KeyLifecycleService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/KeyLifecycleService.java new file mode 100644 index 0000000..24471ff --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/KeyLifecycleService.java @@ -0,0 +1,84 @@ +package com.sunyard.ssp.modules.sdk; + +import com.sunyard.ssp.UnionMessage; + +/** + * @author:tsz + * @date:2020/5/21 + * @description: + */ +public interface KeyLifecycleService { + /** + * @param : sln 密钥方案 + * @param : tmpl 密钥模板 + * @param : startTime 开始时间 + * @param : period 有效期 + * @return : + * @date :2020/05/21 14:50 + * @description : 根据密钥方案密钥模板批量生成密钥 + */ + Long genBatchKeyByTmpl(String sln, String tmpl, Long startTime, Long period); + + /** + * @param : sln 密钥方案 + * @param : tmpl 密钥模板 + * @return : + * @date :2020/05/21 14:50 + * @description : 根据密钥方案密钥模板批量更新密钥 + */ + Long genBatchKeyByTmpl(String sln, String tmpl); + + /** + * @param : sln 密钥方案 + * @param : tmpl 密钥模板 + * @param : node 密钥节点 + * @param : startTime 开始时间 + * @param : period 有效期 + * @return : + * @date :2020/05/21 14:52 + * @description : 根据密钥方案密钥模板生成指定节点密钥 + */ + UnionMessage genKeyByTmpl(String sln, String tmpl, String node, Long startTime, Long period); + + /** + * @param : sln 密钥方案 + * @param : tmpl 密钥模板 + * @param : node 密钥节点 + * @return : + * @date :2020/05/21 14:52 + * @description : 根据密钥方案密钥模板 更新指定节点密钥 + */ + UnionMessage genKeyByTmpl(String sln, String tmpl, String node); + + /** + * @param : + * @return : + * @date :2020/05/21 15:06 + * @description : 工作密钥更新 web暂时不需要 + */ + UnionMessage applyKeyByZMK(String zmk, String node, String tmpl); + + /** + * @param : + * @return : + * @date :2020/05/21 15:06 + * @description : 保护密钥更新 web暂时不需要 + */ + UnionMessage applyZMKByZMK(String zmk, String tmpl); + + /** + *@date :2020/05/21 15:07 + *@description : 保护密钥回滚 + * @param : + * @return : + */ + void rollbackZMK(String zmk); + + /** + *@date :2020/05/21 15:07 + *@description : 密钥作废 + * @param : key 完整密钥名称 + * @return : + */ + void disableKeyNow(String key); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SdkApiService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SdkApiService.java new file mode 100644 index 0000000..f5092f7 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SdkApiService.java @@ -0,0 +1,9 @@ +package com.sunyard.ssp.modules.sdk; + +/** + * @author:tsz + * @date:2020/5/21 + * @description: sdk接口类 + */ +public interface SdkApiService extends CertService,SymmetricKeyToolService,ASymmetricKeyToolService,KeyLifecycleService { +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SdkApiServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SdkApiServiceImpl.java new file mode 100644 index 0000000..330d759 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SdkApiServiceImpl.java @@ -0,0 +1,642 @@ +package com.sunyard.ssp.modules.sdk; + +import com.sunyard.ssp.SSPApi; +import com.sunyard.ssp.SSPApi4jBuilder; +import com.sunyard.ssp.UnionMessage; +import com.sunyard.ssp.common.constant.SdkConstant; +import com.sunyard.ssp.common.exception.SspwebException; +import com.sunyard.ssp.config.ServerConfigure; +import com.sunyard.ssp.constv.Alg; +import com.sunyard.ssp.constv.KeyPairType; +import com.sunyard.ssp.constv.KeyType; +import com.sunyard.ssp.constv.PublicKeyType; +import com.sunyard.ssp.constv.SplitMode; +import com.sunyard.ssp.proto.sdk.Sdk; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Random; + +/** + * @author:tsz + * @date:2020/5/21 + * @description: sdk实现类 + */ +@Service +public class SdkApiServiceImpl implements SdkApiService { + + @Autowired + private ServerConfigure serverConfigure; + + private SSPApi api() { + SSPApi api = null; + try { + api = new SSPApi4jBuilder() +// .setJks(new File(SdkConstant.CLIENT_TRUSTSTORE)) +// .setJksKey(SdkConstant.CLIENT_KEY) + .setIdentity(SdkConstant.IDENTITY_MANAGER) + .setIp(serverConfigure.getServerIp()) + .setPort(serverConfigure.getSdkPort()) + .setConnectTimeout(3000) + .build(); + } catch (Exception e) { + e.printStackTrace(); + // TODO: 2020/5/28 这一块异常是返回sdk的?还是自定义? + throw new SspwebException("sdk连接失败"); + } + return api; + } + + @Override + public UnionMessage genTempKeyPair(KeyPairType keypairType, Alg alg, int keylenMultiple) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.genTempKeyPair(keypairType, alg, keylenMultiple); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public boolean genKeyPair(String pk, String sk, KeyType keyType, Alg alg, int keylenMultiple) { + SSPApi api = null; + try { + api = api(); + boolean b = genKeyPair(pk, sk, keyType, alg, keylenMultiple); + return b; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public void importPk(String pk, PublicKeyType type, byte[] pkv, Long startTime, Long period) { + SSPApi api = null; + try { + api = api(); + api.importPk(pk, type, pkv, startTime, period); + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public void importPk(String pk, PublicKeyType type, byte[] pkv) { + SSPApi api = null; + try { + api = api(); + api.importPk(pk, type, pkv); + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public byte[] outputPk(String pk, PublicKeyType type) { + SSPApi api = null; + try { + api = api(); + byte[] bytes = api.outputPk(pk, type).getBytes(); + return bytes; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public Sdk.CIX509 catCert(String cert) { + SSPApi api = null; + try { + api = api(); + Sdk.CIX509 cix509 = api.catCert(cert); + return cix509; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public Sdk.CIX509 catCert(String cert, String sk) { + SSPApi api = null; + try { + api = api(); + Sdk.CIX509 cix509 = api.catCert(cert,sk); + return cix509; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public String applyCertRequest(String pk, String domain) { + SSPApi api = null; + try { + api = api(); + String s = api.applyCertRequest(pk, domain); + + return s; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public String applyCertRequest(String pk, String domain, Long startTime, Long period) { + SSPApi api = null; + try { + api = api(); + String s = api.applyCertRequest(pk, domain,startTime,period); + + return s; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public byte[] ASYMPKEncryptData(Alg alg, String pk, byte[] data) { + SSPApi api = null; + try { + api = api(); + byte[] bytes = api.ASYMPKEncryptData(alg, pk, data); + return bytes; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public byte[] ASYMSKDecryptData(Alg alg, String sk, byte[] data) { + SSPApi api = null; + try { + api = api(); + byte[] bytes = api.ASYMSKDecryptData(alg, sk, data); + return bytes; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public boolean PKCS1Verify(Alg alg, byte[] orgData, byte[] sign) { + return true; +// SSPApi api = null; +// try { +// api = api(); +// boolean b = api.PKCS1Verify(Alg.SM2, api.SM3Calc(orgData), sign, "CON.000000.SIGN.PK"); +// return b; +// } finally { +// //每笔交易必须释放api +// if (null != api) { +// api.free(); +// api = null; +// } +// } + } + + @Override + public byte[] ASYMEncryptDataByOutPK(Alg alg, String pk, String data) { + SSPApi api = null; + try { + api = api(); + byte[] bytes = api.ASYMPKEncryptData(Alg.SM2, pk, data.getBytes()); + return bytes; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public byte[] PKCS1Sign(Alg alg, byte[] data) { + byte[] sign = new byte[64]; + (new Random()).nextBytes( sign ); + return sign; +// SSPApi api = null; +// try { +// api = api(); +// byte[] bytes = api.PKCS1Sign(Alg.SM2, api.SM3Calc(data), "CON.000000.SIGN.SK"); +// return bytes; +// } finally { +// //每笔交易必须释放api +// if (null != api) { +// api.free(); +// api = null; +// } +// } + } + + @Override + public long ping() { + SSPApi api = null; + try { + api = api(); + Long aLong = api.ping(); + return aLong; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public Long genBatchKeyByTmpl(String sln, String tmpl, Long startTime, Long period) { + SSPApi api = null; + try { + api = api(); + Long aLong = api.genBatchKeyByTmpl(sln, tmpl, startTime, period); + return aLong; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public Long genBatchKeyByTmpl(String sln, String tmpl) { + SSPApi api = null; + try { + api = api(); + Long aLong = api.genBatchKeyByTmpl(sln, tmpl); + return aLong; + + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage genKeyByTmpl(String sln, String tmpl, String node, Long startTime, Long period) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.genKeyByTmpl(sln, tmpl, node, startTime, period); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage genKeyByTmpl(String sln, String tmpl, String node) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.genKeyByTmpl(sln, tmpl, node); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage applyKeyByZMK(String zmk, String node, String tmpl) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.applyKeyByZMK(zmk, node, tmpl); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage applyZMKByZMK(String zmk, String tmpl) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.applyZMKByZMK(zmk); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public void rollbackZMK(String zmk) { + SSPApi api = null; + try { + api = api(); + api.rollbackZMK(zmk); + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public void disableKeyNow(String key) { + SSPApi api = null; + try { + api = api(); + api.disableKeyNow(key); + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public String genRandom(int len) { + SSPApi api = null; + try { + api = api(); + String random = api.genRandom(len); + return random; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage genTempKey(KeyType keyType, Alg alg, int keylenMultiple) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.genTempKey(keyType, alg, keylenMultiple); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public boolean genKey(String key, KeyType keyType, Alg alg, int keylenMultiple) { + SSPApi api = null; + try { + api = api(); + boolean b = api.genKey(key, keyType, alg, keylenMultiple); + return b; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage genKeyByTmplAndPrint(String sln, String tmpl, String node, Long startTime, Long period) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.genKeyByTmplAndPrint(sln, tmpl, node, startTime, period); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage genKeyByTmplAndPrint(String sln, String tmpl, String node) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.genKeyByTmplAndPrint(sln, tmpl, node); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage synthKeyInput(String key, SplitMode splitMode, String[] splits, String kcv, Long startTime, Long period) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.synthKeyInput(key, splitMode, splits, kcv, startTime, period); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage synthKeyInput(String key, SplitMode splitMode, String[] splits, String kcv) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.synthKeyInput(key, splitMode, splits, kcv); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage encryptionKeyOutput(String key, String kek) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.encryptionKeyOutput(key, kek); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage decryptKeyInput(String key, String keyvalue, String kcv, String kek, Long startTime, Long period) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.decryptKeyInput(key, keyvalue, kcv, kek, startTime, period); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage decryptKeyInput(String key, String keyvalue, String kcv, String kek) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.decryptKeyInput(key, keyvalue, kcv, kek); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage encryptionKeyByPkOutput(String key, Alg alg, String pk) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.encryptionKeyByPkOutput(key, alg, pk); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public UnionMessage encryptionKeyByPkvOutput(String key, Alg alg, String pkv) { + SSPApi api = null; + try { + api = api(); + UnionMessage unionMessage = api.encryptionKeyByPkvOutput(key, alg, pkv); + return unionMessage; + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public void decryptKeyBySkInput(String key, String kcv, String sk) { + SSPApi api = null; + try { + api = api(); + api.decryptKeyBySkInput(key, kcv, sk); + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } + + @Override + public void decryptKeyBySkInput(String key, String kcv, String sk, Long startTime, Long period) { + SSPApi api = null; + try { + api = api(); + api.decryptKeyBySkInput(key, kcv, sk, startTime, period); + } finally { + //每笔交易必须释放api + if (null != api) { + api.free(); + api = null; + } + } + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SymmetricKeyToolService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SymmetricKeyToolService.java new file mode 100644 index 0000000..6eda15f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sdk/SymmetricKeyToolService.java @@ -0,0 +1,151 @@ +package com.sunyard.ssp.modules.sdk; + +import com.sunyard.ssp.UnionMessage; +import com.sunyard.ssp.constv.Alg; +import com.sunyard.ssp.constv.KeyType; +import com.sunyard.ssp.constv.SplitMode; + +/** + * @author:tsz + * @date:2020/5/21 + * @description: 对称密钥工具类 + */ +public interface SymmetricKeyToolService { + + /** + * @param :len 随机数长度 + * @return : + * @date :2020/05/21 14:27 + * @description : 生成指定长度的真随机数 + */ + String genRandom(int len); + + /** + * @param : keyType 密钥类型 + * @param : alg 指定此密钥用于什么算法 + * @param : keylenMultiple 密钥长度的倍数 + * @return : + * @date :2020/05/21 14:29 + * @description : 生成临时用的密钥 + */ + UnionMessage genTempKey(KeyType keyType, Alg alg, int keylenMultiple); + + /** + * @param : + * @return : + * @date :2020/05/21 14:31 + * @description : 暂时没实现的接口 + */ + boolean genKey(String key, KeyType keyType, Alg alg, int keylenMultiple); + + /** + * @param : sln 密钥方案 + * @param : tmpl 密钥模板 + * @param : node 密钥节点 + * @param : startTime 开始时间 + * @param : period 有效期 + * @return : + * @date :2020/05/21 14:32 + * @description : 根据密钥方案密钥模板生成指定节点密钥 并打印 + */ + UnionMessage genKeyByTmplAndPrint(String sln, String tmpl, String node, Long startTime, Long period); + + /** + * @param : sln 密钥方案 + * @param : tmpl 密钥模板 + * @param : node 密钥节点 + * @return : + * @date :2020/05/21 14:36 + * @description : 根据密钥方案密钥模板更新指定节点密钥 + */ + UnionMessage genKeyByTmplAndPrint(String sln, String tmpl, String node); + + /** + * @param : key 指定密钥名,例如 XXX.000000.T001.ZMK + * @param : splitMode XOR('异或模式', 1),SEG( '拼接模式', 2) + * @param : splits 所有的密钥分量 HEX格式 + * @param : kcv 密钥校验值 HEX 格式可选,如果没有 kcv 则不对密钥进行校验 + * @param : startTime 开始时间 + * @param : period 有效期 + * @return : + * @date :2020/05/21 14:39 + * @description : 分量导入 生成密钥 + */ + UnionMessage synthKeyInput(String key, SplitMode splitMode, String[] splits, String kcv, Long startTime, Long period); + + /** + * @param : key 指定密钥名,例如 XXX.000000.T001.ZMK + * @param : splitMode XOR('异或模式', 1),SEG( '拼接模式', 2) + * @param : splits 所有的密钥分量 HEX格式 + * @param : kcv 密钥校验值 HEX 格式可选,如果没有 kcv 则不对密钥进行校验 + * @return : + * @date :2020/05/21 14:39 + * @description : 分量导入 更新密钥 + */ + UnionMessage synthKeyInput(String key, SplitMode splitMode, String[] splits, String kcv); + + /** + * @param : key 指定密钥名,例如 XXX.000000.T001.ZMK + * @param : kek 保护密钥的名字 + * @return : + * @date :2020/05/21 14:43 + * @description : 通过保护密钥加密并导出密钥 + */ + UnionMessage encryptionKeyOutput(String key, String kek); + + /** + * @param : key 指定密钥名,例如 XXX.000000.T001.ZMK + * @param : keyvalue 密钥值 + * @param : kcv 密钥校验值,可选,如果为 null 则不进行校验 + * @param : kek 保护密钥的名字 + * @param : startTime 开始时间 + * @param : period 有效期 + * @return : + * @date :2020/05/21 14:44 + * @description : 通过保护密钥加密并导入 生成密钥 + */ + UnionMessage decryptKeyInput(String key, String keyvalue, String kcv, String kek, Long startTime, Long period); + + /** + * @param : key 指定密钥名,例如 XXX.000000.T001.ZMK + * @param : keyvalue 密钥值 + * @param : kcv 密钥校验值,可选,如果为 null 则不进行校验 + * @param : kek 保护密钥的名字 + * @return : + * @date :2020/05/21 14:43 + * @description : 通过保护密钥加密并导入 更新密钥 + */ + UnionMessage decryptKeyInput(String key, String keyvalue, String kcv, String kek); + + /** + *@date :2020/05/21 14:47 + *@description : 通过公钥保护导出密钥 未实现 + * @param : + * @return : + */ + UnionMessage encryptionKeyByPkOutput(String key, Alg alg, String pk); + + /** + *@date :2020/05/21 14:47 + *@description : 未实现接口 + * @param : + * @return : + */ + UnionMessage encryptionKeyByPkvOutput(String key, Alg alg, String pkv); + + /** + *@date :2020/05/21 14:48 + *@description : 通过私钥解密导入 生成密钥 未实现 + * @param : + * @return : + */ + void decryptKeyBySkInput(String key, String kcv, String sk); + + /** + *@date :2020/05/21 14:48 + *@description : 通过私钥解密导入 更新密钥 未实现 + * @param : + * @return : + */ + void decryptKeyBySkInput(String key, String kcv, String sk, Long startTime, Long period); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/controller/ParamConfController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/controller/ParamConfController.java new file mode 100644 index 0000000..6178cbd --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/controller/ParamConfController.java @@ -0,0 +1,99 @@ +package com.sunyard.ssp.modules.sysconf.paramconf.controller; + + +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.common.annotation.AuditControllerLog; +import com.sunyard.ssp.modules.sysconf.paramconf.entity.ParamConf; +import com.sunyard.ssp.modules.sysconf.paramconf.service.IParamConfService; +import com.sunyard.ssp.utils.ResultUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 前端控制器 + *

+ * + * @author fyc + * @since 2020-03-17 + */ +@Controller +@Slf4j +@Api(description = "系统配置-业务参数配置",tags ="系统配置-业务参数配置") +@RequestMapping("/sysconf/paramConf") +@Transactional +public class ParamConfController { + + @Autowired + IParamConfService iParamConfService; + + + + + @RequestMapping(value = "/getAll",method = RequestMethod.GET) + @ApiOperation(value = "获取全部数据") + @ResponseBody + public Result> getAll(){ + + List list = iParamConfService.list(); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/selectByItem",method = RequestMethod.GET) + @ApiOperation(value = "根据类目获取参数(通讯参数-1,终端UI参数-2, 白名单参数-0)") + @ResponseBody + public Result selectByItem(@RequestParam Integer item){ + Map data = iParamConfService.selectByItem(item); + return new ResultUtil().setData(data); + } + + @RequestMapping(value = "/selectByKey",method = RequestMethod.GET) + @ApiOperation(value = "根据key值获取数据") + @ResponseBody + public Result selectByItem(@RequestParam String key){ + ParamConf data = iParamConfService.selectByKey(key); + return new ResultUtil().setData(data); + } + + + + @RequestMapping(value = "/save",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "保存数据") + @AuditControllerLog(description = "更新业务参数",operateType = "更新") + public Result save(@RequestBody Map map){ + + boolean result = iParamConfService.save(map); + if(result){ + return new ResultUtil<>().setSuccessMsg("保存成功"); + }else { + return new ResultUtil<>().setErrorMsg("保存失败"); + } + + + } + + + @RequestMapping(value = "/deleteById",method = RequestMethod.DELETE) + @ResponseBody + @ApiOperation(value = "通过id删除") + public Result delAllByIds(@RequestParam String id){ + + iParamConfService.removeById(id); + return new ResultUtil().setSuccessMsg("删除数据成功"); + } + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/entity/ParamConf.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/entity/ParamConf.java new file mode 100644 index 0000000..aa98f2f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/entity/ParamConf.java @@ -0,0 +1,66 @@ +package com.sunyard.ssp.modules.sysconf.paramconf.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author fyc + * @since 2020-03-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_PARAM_CONF") +@ApiModel(value="", description="") +public class ParamConf implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "主键") + @TableId("ID") + private Long id; + + @ApiModelProperty(value = "数据大类") + @TableField("ITEM") + private Integer item; + + @ApiModelProperty(value = "数据名称") +// @TableField("`KEY`") mysql需加 + @TableField("KEY") + private String key; + + @ApiModelProperty(value = "数据值") + @TableField("VALUE") + private String value; + + @ApiModelProperty(value = "数据值类型") + @TableField("TYPE") + private String type; + + @ApiModelProperty(value = "状态") + @TableField("STATUS") + private Integer status; + + @ApiModelProperty(value = "创建时间") + @TableField("CREAT_TIME") + private LocalDateTime creatTime; + + @ApiModelProperty(value = "备注") + @TableField("MEMO") + private String memo; + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/mapper/ParamConfMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/mapper/ParamConfMapper.java new file mode 100644 index 0000000..ec16605 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/mapper/ParamConfMapper.java @@ -0,0 +1,32 @@ +package com.sunyard.ssp.modules.sysconf.paramconf.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.sysconf.paramconf.entity.ParamConf; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author fyc + * @since 2020-03-17 + */ +@Repository +public interface ParamConfMapper extends BaseMapper { + +// @Select("") + ParamConf selectByKey(@Param("key")String key); + + @Select("") + List selectByItem(@Param("item") Integer item); + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/service/IParamConfService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/service/IParamConfService.java new file mode 100644 index 0000000..59d776e --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/service/IParamConfService.java @@ -0,0 +1,45 @@ +package com.sunyard.ssp.modules.sysconf.paramconf.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.sysconf.paramconf.entity.ParamConf; + +import java.util.Map; + +/** + *

+ * 服务类 + *

+ * + * @author fyc + * @since 2020-03-17 + */ +public interface IParamConfService extends IService { + + /** + * 存储业务参数 + * @param map 参数集合 + * @return + */ + boolean save(Map map); + + /** + * 根据类别获取相应的系统参数 + * @param item + * @return + */ + Map selectByItem(Integer item); + + /** + * 根据Key值获取参数值 + * @param key + * @return + */ + ParamConf selectByKey(String key); + + /** + *@author :tsz + *@date :2020/04/12 10:23 + *@description : 根据item,key和value确定开关是否开启 + */ + Boolean findByItemAndKeyAndValue(Integer item,String key,String value); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/serviceimpl/ParamConfServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/serviceimpl/ParamConfServiceImpl.java new file mode 100644 index 0000000..82ce364 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/sysconf/paramconf/serviceimpl/ParamConfServiceImpl.java @@ -0,0 +1,191 @@ +package com.sunyard.ssp.modules.sysconf.paramconf.serviceimpl; + +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.common.constant.ParamConfKeyConstant; +import com.sunyard.ssp.modules.sysconf.paramconf.entity.ParamConf; +import com.sunyard.ssp.modules.sysconf.paramconf.mapper.ParamConfMapper; +import com.sunyard.ssp.modules.sysconf.paramconf.service.IParamConfService; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import com.sunyard.ssp.modules.user.service.IScPermissionService; +import com.sunyard.ssp.utils.JsonUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.interceptor.TransactionAspectSupport; + +import java.io.File; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.sunyard.ssp.common.constant.CommonConstant.STATUS_DISABLE; +import static com.sunyard.ssp.common.constant.CommonConstant.STATUS_NORMAL; +import static com.sunyard.ssp.common.constant.ParamConfKeyConstant.APPROVAL_TRUE; +import static com.sunyard.ssp.common.constant.ParamConfKeyConstant.AUTHORITY_APPROVAL_PARAM_ITEM; +import static com.sunyard.ssp.common.constant.ParamConfKeyConstant.ENCRYPTION_MACHINE_APPROVAL; +import static com.sunyard.ssp.common.constant.ParamConfKeyConstant.IP_WHITELIST_ITEM; +import static com.sunyard.ssp.common.constant.ParamConfKeyConstant.IP_WHITELIST_SWITCH; + +/** + *

+ * 服务实现类 + *

+ * + * @author fyc + * @since 2020-03-17 + */ +@Slf4j +@Service +@Transactional +public class ParamConfServiceImpl extends ServiceImpl implements IParamConfService, ApplicationRunner { + + @Autowired + private IScPermissionService permissionService; + + @Autowired + private ParamConfMapper paramConfMapper; + +// @Autowired +// private IIpWhitelistService iIpWhitelistService; + + + @Override + public boolean save(Map map) { + Integer item = (Integer) map.get("item"); + map.remove("item"); + Set keySet = map.keySet(); + boolean result = false; + for (String key : keySet) { + ParamConf paramConf = paramConfMapper.selectByKey(key); + if (paramConf == null) { + paramConf = new ParamConf(); + paramConf.setItem(item); + paramConf.setStatus(0); + System.out.println(LocalDateTime.now()); + paramConf.setCreatTime(LocalDateTime.now()); + paramConf.setKey(key); + paramConf.setValue(String.valueOf(map.get(key))); + paramConf.setType("OBJECT"); + result = save(paramConf); + } else { + paramConf.setValue(String.valueOf(map.get(key))); + result = updateById(paramConf); + } + if (!result) { + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + break; + } + //存储成功生效配置 + takeEffectConfiguration(paramConf); + } + return result; + } + + @Override + public Map selectByItem(Integer item) { + Map result = new HashMap(); + List paramConfs = paramConfMapper.selectByItem(item); + for (ParamConf paramConf : paramConfs) { + result.put(paramConf.getKey(), paramConf.getValue()); + } + return result; + } + + @Override + public ParamConf selectByKey(String key) { + return paramConfMapper.selectByKey(key); + } + + @Override + public Boolean findByItemAndKeyAndValue(Integer item, String key, String value) { + + List paramConfs = paramConfMapper.selectList(new QueryWrapper().lambda() + .eq(ParamConf::getItem, item) + .eq(ParamConf::getKey, key) + .eq(ParamConf::getValue, value) + ); + if (paramConfs.isEmpty()) { + return false; + } + return true; + } + + /** + * 参数修改后进行配置生效 + * @param paramConf + * @return + */ + @Async + public void takeEffectConfiguration(ParamConf paramConf) { + //审批权限 + if (AUTHORITY_APPROVAL_PARAM_ITEM.equals(paramConf.getItem()) + && ENCRYPTION_MACHINE_APPROVAL.equals(paramConf.getKey())) { + QueryWrapper wrapper = new QueryWrapper(); + String[] names = {"myApply", "approvalDev", "device"}; + wrapper.lambda().in(ScPermission::getName, names); + List permissions = permissionService.list(wrapper); + permissions.forEach(p -> { + if (APPROVAL_TRUE.equals(paramConf.getValue())) { + p.setPStatus(STATUS_NORMAL); + } else { + p.setPStatus(STATUS_DISABLE); + } + }); + permissionService.updateBatchById(permissions); + } + //白名单通知 + else if (IP_WHITELIST_ITEM.equals(paramConf.getItem()) + && IP_WHITELIST_SWITCH.equals(paramConf.getKey())) { +// iIpWhitelistService.messengerWhitelistUpdate(); + } + } + + /** + * 启动加载初始化系统参数 + * + * @param args + * @throws Exception + */ + @Override + public void run(ApplicationArguments args) throws Exception { + System.out.println("初始化系统参数-----------------"); +// List paramConfs = getParamConfByJsonFile(); +// paramConfs.forEach(paramConf -> { +// ParamConf temp = selectByKey(paramConf.getKey()); +// if (temp == null) { +// paramConf.setCreatTime(LocalDateTime.now()); +// save(paramConf); +// } else { +// temp.setValue(paramConf.getValue()); +// updateById(temp); +// } +// }); + } + + /** + * 从JSON 文件里获取初始化配置 + * + * @return + */ + private List getParamConfByJsonFile() { + String jsonStr = ""; + List paramConfs = new ArrayList<>(); + try { + File jsonFile = new File(ParamConfKeyConstant.SYS_PARAM_CONFIG_FILE_PATH); + jsonStr = JsonUtil.getJsonStrFromJsonFile(jsonFile); + paramConfs = JSON.parseArray(jsonStr, ParamConf.class); + return paramConfs; + } catch (Exception ex) { + return paramConfs; + } + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScDepartmentController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScDepartmentController.java new file mode 100644 index 0000000..c91ca95 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScDepartmentController.java @@ -0,0 +1,263 @@ +package com.sunyard.ssp.modules.user.controller; + + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.common.constant.ValidatorConstant; +import com.sunyard.ssp.modules.user.entity.ScDepartment; +import com.sunyard.ssp.modules.user.entity.ScDepartmentHeader; +import com.sunyard.ssp.modules.user.entity.ScRoleDepartment; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScDepartmentHeaderService; +import com.sunyard.ssp.modules.user.service.IScDepartmentService; +import com.sunyard.ssp.modules.user.service.IScRoleDepartmentService; +import com.sunyard.ssp.modules.user.service.IScUserService; +import com.sunyard.ssp.modules.user.utils.validator.DepartmentValidator; +import com.sunyard.ssp.redis.RedisObjectOperation; +import com.sunyard.ssp.utils.ResultUtil; +import com.sunyard.ssp.utils.SecurityUtil; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.DataBinder; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + *

+ * 前端控制器 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@RestController +@Slf4j +@RequestMapping("/department") +@Transactional +public class ScDepartmentController { + + @Autowired + DepartmentValidator departmentValidator; + + @Autowired + private IScDepartmentService departmentService; + + @Autowired + private IScUserService userService; + + @Autowired + private IScRoleDepartmentService roleDepartmentService; + + @Autowired + private IScDepartmentHeaderService departmentHeaderService; + + /*@Autowired + private StringRedisTemplate redisTemplate;*/ + + @Autowired + private RedisObjectOperation redisObjectOperation; + + @Autowired + private SecurityUtil securityUtil; + + @InitBinder(value = ValidatorConstant.DEPARTMENT_BASE_NAME) + public void initBainder(DataBinder binder){ + binder.replaceValidators(departmentValidator); + } + + @RequestMapping(value = "/getByParentId/{parentId}",method = RequestMethod.GET) + @ApiOperation(value = "通过id获取") + public Result> getByParentId(@PathVariable Long parentId, + @ApiParam("是否开始数据权限过滤") @RequestParam(required = false, defaultValue = "false") Boolean openDataFilter){ + + List list = new ArrayList<>(); + ScUser u = securityUtil.getCurrUser(); + + list = departmentService.findByParentIdOrderBySortOrder(parentId, openDataFilter); + list = setInfo(list); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/add",method = RequestMethod.POST) + @ApiOperation(value = "添加") + public Result add(@ModelAttribute(ValidatorConstant.DEPARTMENT_BASE_NAME) @Validated ScDepartment department){ + + departmentService.save(department); + // 如果不是添加的一级 判断设置上级为父节点标识 + if(department.getParentId()!=null && !CommonConstant.PARENT_ID.equals(department.getParentId())){ + ScDepartment parent = departmentService.getById(department.getParentId()); + if(parent.getIsParent()==null||!parent.isParent()){ + parent.setIsParent(true); + departmentService.updateById(parent); + } + } + // 更新缓存 + Set keys = redisObjectOperation.keys("department::*"); + redisObjectOperation.delete(keys); + return new ResultUtil().setData(department,"添加成功"); + } + + @RequestMapping(value = "/edit",method = RequestMethod.POST) + @ApiOperation(value = "编辑") + public Result edit(@ModelAttribute(ValidatorConstant.DEPARTMENT_BASE_NAME) @Validated ScDepartment department, + @RequestParam(required = false) Long[] mainHeader, + @RequestParam(required = false) Long[] viceHeader){ + + ScDepartment originDepartment = departmentService.getById(department.getId()); + if(!originDepartment.getParentId().equals(department.getParentId())){ + return new ResultUtil().setErrorMsg("禁止编辑上级部门"); + } + + departmentService.updateById(department); + // 先删除原数据 + departmentHeaderService.remove(new QueryWrapper().lambda() + .eq(ScDepartmentHeader::getDepartmentId, department.getId())); + for(Long id:mainHeader){ + ScDepartmentHeader dh = new ScDepartmentHeader(); + dh.setUserId(id); + dh.setDepartmentId(department.getId()); + dh.setType(CommonConstant.HEADER_TYPE_MAIN); + departmentHeaderService.save(dh); + } + for(Long id:viceHeader){ + ScDepartmentHeader dh = new ScDepartmentHeader(); + dh.setUserId(id); + dh.setDepartmentId(department.getId()); + dh.setType(CommonConstant.HEADER_TYPE_VICE); + departmentHeaderService.save(dh); + } + // 手动删除所有部门缓存 + Set keys = redisObjectOperation.keys("department:" + "*"); + redisObjectOperation.delete(keys); + // 删除所有用户缓存 + Set keysUser = redisObjectOperation.keys("user:" + "*"); + redisObjectOperation.delete(keysUser); + return new ResultUtil().setData(department,"编辑成功"); + } + + @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE) + @ApiOperation(value = "批量通过id删除") + public Result delByIds(@PathVariable String[] ids){ + + for(String id:ids){ + List list = userService.list(new QueryWrapper().lambda().eq(ScUser::getOrganizationId, id)); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("删除失败,包含正被用户使用关联的部门"); + } + ScDepartment department = departmentService.getById(id); + List departments = departmentService.findByParentIdOrderBySortOrder(department.getId(), false); + if(departments!=null&&departments.size()>0){ + return new ResultUtil().setErrorMsg("删除失败,待删除部门下还有子部门"); + } + } + for(String id:ids){ + departmentService.removeById(id); + // 删除关联数据权限 + roleDepartmentService.remove(new QueryWrapper().lambda() + .eq(ScRoleDepartment::getDepartmentId, id)); + // 删除关联部门负责人 + departmentHeaderService.remove(new QueryWrapper().lambda() + .eq(ScDepartmentHeader::getDepartmentId, id)); + } + // 手动删除所有部门缓存 + Set keys = redisObjectOperation.keys("department:" + "*"); + redisObjectOperation.delete(keys); + // 删除数据权限缓存 + Set keysUserRoleData = redisObjectOperation.keys("userRole::depIds:" + "*"); + redisObjectOperation.delete(keysUserRoleData); + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } + + @RequestMapping(value = "/search",method = RequestMethod.GET) + @ApiOperation(value = "部门名模糊搜索") + public Result> searchByTitle(@RequestParam String title, + @ApiParam("是否开始数据权限过滤") @RequestParam(required = false, defaultValue = "false") Boolean openDataFilter){ + + List list = departmentService.findByTitleLikeOrderBySortOrder("%"+title+"%", openDataFilter); + list = setInfo(list); + return new ResultUtil>().setData(list); + } + + public List setInfo(List list){ + + // lambda表达式 + list.forEach(item -> { + if(!CommonConstant.PARENT_ID.equals(item.getParentId())){ + ScDepartment parent = departmentService.getById(item.getParentId()); + if(parent != null){ + item.setParentTitle(parent.getTitle()); + }else{ + item.setParentTitle(""); + } + }else{ + item.setParentTitle("一级部门"); + } + // 设置负责人 + List mainHeaderList = departmentHeaderService.list(new QueryWrapper().lambda() + .eq(ScDepartmentHeader::getDepartmentId, item.getId()) + .eq(ScDepartmentHeader::getType, CommonConstant.HEADER_TYPE_MAIN)); + List viceHeaderList = departmentHeaderService.list(new QueryWrapper().lambda() + .eq(ScDepartmentHeader::getDepartmentId, item.getId()) + .eq(ScDepartmentHeader::getType, CommonConstant.HEADER_TYPE_VICE)); + + if(CollectionUtils.isNotEmpty(mainHeaderList)){ + item.setMainHeader(mainHeaderList.stream().map(scDepartmentHeader -> scDepartmentHeader.getUserId()).collect(Collectors.toList())); + } + + if(CollectionUtils.isNotEmpty(viceHeaderList)){ + item.setViceHeader(viceHeaderList.stream().map(scDepartmentHeader -> scDepartmentHeader.getUserId()).collect(Collectors.toList())); + } + + }); + return list; + } + @RequestMapping(value = "/getAllJSON",method = RequestMethod.GET) + @ApiOperation(value = "获取全部部门的json格式数据") + public Result getAllJSON(@ApiParam("是否开始数据权限过滤") @RequestParam(required = false, defaultValue = "true") Boolean openDataFilter){ + JSONArray res = getByPid(CommonConstant.DEPARTMENT_ROOT_ID,openDataFilter); + + return new ResultUtil().setData(res); + + } + + @RequestMapping(value = "/getAllList", method = RequestMethod.GET) + public Result> getAllList(){ + return new ResultUtil().setData(departmentService.list()); + } + + private JSONArray getByPid(Long pId, Boolean openDataFilter){ + JSONArray res = new JSONArray(); + List list = departmentService.findByParentIdOrderBySortOrder(pId, openDataFilter); + if (CollectionUtils.isEmpty(list)){ + return null; + } + + for (int i = 0; i < list.size(); i++) { + JSONObject departmentJSON = new JSONObject(); + departmentJSON.put("title",list.get(i).getTitle()); + departmentJSON.put("id",list.get(i).getId()); + departmentJSON.put("childern",getByPid(list.get(i).getId(),openDataFilter)); + res.add(departmentJSON); + } + + return res; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScDepartmentHeaderController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScDepartmentHeaderController.java new file mode 100644 index 0000000..76a0c39 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScDepartmentHeaderController.java @@ -0,0 +1,96 @@ +package com.sunyard.ssp.modules.user.controller; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.modules.user.entity.ScDepartmentHeader; +import com.sunyard.ssp.modules.user.service.IScDepartmentHeaderService; +import com.sunyard.ssp.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@RestController +@Slf4j +@RequestMapping("/departmentHeader") +@Transactional +public class ScDepartmentHeaderController { + + @Autowired + IScDepartmentHeaderService iScDepartmentHeaderService; + + @RequestMapping(value = "/getById",method = RequestMethod.GET) + @ResponseBody + public Result get(@RequestParam String id){ + + ScDepartmentHeader entity = iScDepartmentHeaderService.getById(id); + return new ResultUtil().setData(entity); + } + + @RequestMapping(value = "/getAll",method = RequestMethod.GET) + @ResponseBody + public Result> getAll(){ + + List list = iScDepartmentHeaderService.list(); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/page",method = RequestMethod.GET) + @ResponseBody + public Result> getByPage(@ModelAttribute PageVo page){ + Page data = new Page<>( page.getPageNumber(),page.getPageSize()); + IPage iPage = iScDepartmentHeaderService.page(data); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/save",method = RequestMethod.POST) + @ResponseBody + public Result save(@ModelAttribute ScDepartmentHeader entity){ + + boolean e = iScDepartmentHeaderService.save(entity); + if ( !e ){ + return new ResultUtil().setErrorMsg("添加失败"); + } + return new ResultUtil().setSuccessMsg("添加成功"); + } + + @RequestMapping(value = "/update",method = RequestMethod.PUT) + @ResponseBody + public Result> update(@ModelAttribute ScDepartmentHeader entity){ + + boolean e = iScDepartmentHeaderService.updateById(entity); + if ( !e ){ + return new ResultUtil>().setErrorMsg("更新失败"); + } + return new ResultUtil>().setSuccessMsg("更新成功"); + } + + @RequestMapping(value = "/deleteByIds",method = RequestMethod.DELETE) + @ResponseBody + public Result delAllByIds(@RequestParam String[] ids){ + + for(String id:ids){ + iScDepartmentHeaderService.removeById(id); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScPermissionController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScPermissionController.java new file mode 100644 index 0000000..5435028 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScPermissionController.java @@ -0,0 +1,421 @@ +package com.sunyard.ssp.modules.user.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.sunyard.config.security.permission.MyAccessDecisionManager; +import com.sunyard.config.security.permission.MyFilterSecurityInterceptor; +import com.sunyard.config.security.permission.MySecurityMetadataSource; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.common.constant.ValidatorConstant; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import com.sunyard.ssp.modules.user.entity.ScRolePermission; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScPermissionService; +import com.sunyard.ssp.modules.user.service.IScRolePermissionService; +import com.sunyard.ssp.modules.user.utils.validator.PermissionValidator; +import com.sunyard.ssp.utils.ResultUtil; +import com.sunyard.ssp.utils.SecurityUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator; +import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.DataBinder; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static com.sunyard.ssp.common.constant.CommonConstant.STATUS_DISABLE; + +/** + *

+ * 前端控制器 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@RestController +@Slf4j +@RequestMapping("/permission") +@Transactional +public class ScPermissionController { + + @Autowired + PermissionValidator permissionValidator; + + @Autowired + WebInvocationPrivilegeEvaluator privilegeEvaluator; + + @Autowired + HttpServletRequest request; + + @Autowired + HttpServletResponse response; + + @Autowired + SecurityUtil securityUtil; + + @Autowired + private StringRedisTemplate redisTemplate; + + @Autowired + MyFilterSecurityInterceptor myFilterSecurityInterceptor; + + @Autowired + MySecurityMetadataSource mySecurityMetadataSource; + + @Autowired + MyAccessDecisionManager myAccessDecisionManager; + + @Autowired + IScPermissionService permissionService; + + @Autowired + IScRolePermissionService rolePermissionService; + + @InitBinder(ValidatorConstant.PERMISSION_BASE_NAME) + public void initBainder(DataBinder binder){ + binder.addValidators(permissionValidator); + } + + @RequestMapping(value = "/getById",method = RequestMethod.GET) + @ResponseBody + public Result get(@RequestParam String id){ + + ScPermission entity = permissionService.getById(id); + return new ResultUtil().setData(entity); + } + + @RequestMapping(value = "/getAll",method = RequestMethod.GET) + @ResponseBody + public Result> getAll(){ + + List list = permissionService.list(); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/page",method = RequestMethod.GET) + @ResponseBody + public Result> getByPage(@ModelAttribute PageVo page){ + Page data = new Page<>( page.getPageNumber(),page.getPageSize()); + IPage iPage = permissionService.page(data); + return new ResultUtil>().setData(iPage); + } + + /*@RequestMapping(value = "/save",method = RequestMethod.POST) + @ResponseBody + public Result save(@ModelAttribute ScPermission entity){ + + boolean e = permissionService.save(entity); + + if ( !e ){ + return new ResultUtil().setErrorMsg("添加失败"); + } + return new ResultUtil().setSuccessMsg("添加成功"); + }*/ + + /*@RequestMapping(value = "/update",method = RequestMethod.PUT) + @ResponseBody + public Result> update(@ModelAttribute ScPermission entity){ + + boolean e = permissionService.updateById(entity); + if ( !e ){ + return new ResultUtil>().setErrorMsg("更新失败"); + } + return new ResultUtil>().setSuccessMsg("更新成功"); + }*/ + + @RequestMapping(value = "/deleteByIds",method = RequestMethod.DELETE) + @ResponseBody + public Result delAllByIds(@RequestParam String[] ids){ + + for(String id:ids){ + permissionService.removeById(id); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } + + @RequestMapping(value = "/getMenuList",method = RequestMethod.GET) + public Result> getAllMenuList(){ + + List list = new ArrayList<>(); + // 读取缓存 + ScUser u = securityUtil.getCurrUser(); + /*String key = "permission::userMenuList:" + u.getId(); + String v = redisTemplate.opsForValue().get(key); + if(StrUtil.isNotBlank(v)){ + list = new Gson().fromJson(v, new TypeToken>(){}.getType()); + if(CollectionUtils.isNotEmpty(list)){ + return new ResultUtil>().setData(list); + } + + }*/ + + // 用户所有权限 已排序去重 + list = permissionService.findByUserId(u.getId()); + + List menuList = new ArrayList<>(); + // 筛选一级页面 + for(ScPermission p : list){ + if(CommonConstant.PERMISSION_PAGE.equals(p.getPType())&&CommonConstant.LEVEL_ONE.equals(p.getPLevel())){ + menuList.add(p); + } + } + // 筛选二级页面 + List secondMenuList = new ArrayList<>(); + for(ScPermission p : list){ + if(CommonConstant.PERMISSION_PAGE.equals(p.getPType())&&CommonConstant.LEVEL_TWO.equals(p.getPLevel())){ + secondMenuList.add(p); + } + } + // 筛选三级页面 + List thirdMenuList = new ArrayList<>(); + for(ScPermission p : list){ + if(CommonConstant.PERMISSION_PAGE.equals(p.getPType())&&CommonConstant.LEVEL_THREE.equals(p.getPLevel())){ + thirdMenuList.add(p); + } + } + // 筛选二级页面拥有的按钮权限 + /*List buttonPermissions = new ArrayList<>(); + for(ScPermission p : list){ + if(CommonConstant.PERMISSION_OPERATION.equals(p.getType())){ + buttonPermissions.add(p); + } + }*/ + + // 匹配二级页面拥有权限 + /*for(ScPermission p : secondMenuList){ + List permTypes = new ArrayList<>(); + for(ScPermission pe : buttonPermissions){ + if(p.getId().equals(pe.getParentId())){ + permTypes.add(pe.getButtonType()); + } + } + p.setPermTypes(permTypes); + }*/ + // 匹配一级页面拥有二级页面 + for(ScPermission p : menuList){ + List secondMenu = new ArrayList<>(); + for(ScPermission pe : secondMenuList){ + if(p.getId().equals(pe.getParentId())){ + List thirdMenu = new ArrayList<>(); + for(ScPermission pt : thirdMenuList){ + if(pe.getId().equals(pt.getParentId())){ + thirdMenu.add(pt); + } + } + pe.setChildren(thirdMenu); + secondMenu.add(pe); + } + } + p.setChildren(secondMenu); + } + + // 缓存 + //redisTemplate.opsForValue().set(key, new Gson().toJson(menuList)); + return new ResultUtil>().setData(menuList); + } + + + @RequestMapping(value = "/getAllList",method = RequestMethod.GET) + public Result> getAllList(){ + + + // 一级 + List list = permissionService.findByLevelOrderBySortOrder(CommonConstant.LEVEL_ONE); + // 二级 + for(ScPermission p1 : list){ + List children1 = permissionService.findByParentIdOrderBySortOrder(p1.getId()); + p1.setChildren(children1); + // 三级 + for(ScPermission p2 : children1){ + List children2 = permissionService.findByParentIdOrderBySortOrder(p2.getId()); + p2.setChildren(children2); + //四级 + for(ScPermission p3 : children2){ + List children3 = permissionService.findByParentIdOrderBySortOrder(p3.getId()); + p3.setChildren(children3); + } + } + } + Result> res = new ResultUtil>().setData(list); + return res; + } + + @RequestMapping(value = "/tree",method = RequestMethod.GET) + public Result> getByTree(@RequestParam(required = false)Long parentId){ + + List list; + + if(parentId != null){ + list = permissionService.findByLevelOrderBySortOrder(CommonConstant.LEVEL_ONE); + }else{ + list = permissionService.findByParentIdOrderBySortOrder(parentId); + } + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/add",method = RequestMethod.POST) + /*@CacheEvict(key = "'menuList'")*/ + public Result add(@ModelAttribute(ValidatorConstant.PERMISSION_BASE_NAME) @Validated ScPermission permission){ + + // 判断拦截请求的操作权限按钮名是否已存在 + if(CommonConstant.PERMISSION_OPERATION.equals(permission.getPType())){ + List list = permissionService.list(new QueryWrapper().lambda() + .eq(ScPermission::getTitle,permission.getTitle()) + .orderByAsc(ScPermission::getSortOrder)); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("名称已存在"); + } + } + permissionService.save(permission); + //重新加载权限 + mySecurityMetadataSource.loadResourceDefine(); + //手动删除缓存 + Set redisLeys = redisTemplate.keys("permission:*"); + redisTemplate.delete(redisLeys); + return new ResultUtil().setData(permission); + } + + @RequestMapping(value = "/edit",method = RequestMethod.POST) + public Result edit(@ModelAttribute(ValidatorConstant.PERMISSION_BASE_NAME) @Validated ScPermission permission){ + + // 判断拦截请求的操作权限按钮名是否已存在 + if(CommonConstant.PERMISSION_OPERATION.equals(permission.getPType())){ + // 若名称修改 + ScPermission p = permissionService.getById(permission.getId()); + if(!p.getTitle().equals(permission.getTitle())){ + List list = permissionService.list(new QueryWrapper().lambda() + .eq(ScPermission::getTitle,permission.getTitle()) + .orderByAsc(ScPermission::getSortOrder)); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("名称已存在"); + } + } + } + permissionService.updateById(permission); + //重新加载权限 + mySecurityMetadataSource.loadResourceDefine(); + //手动批量删除缓存 + Set keys = redisTemplate.keys("userPermission:" + "*"); + redisTemplate.delete(keys); + Set keysUser = redisTemplate.keys("user:" + "*"); + redisTemplate.delete(keysUser); + Set keysUserMenu = redisTemplate.keys("permission::userMenuList:*"); + redisTemplate.delete(keysUserMenu); + redisTemplate.delete("permission::allList"); + return new ResultUtil().setData(permission); + } + + @RequestMapping(value = "/delByIds/{ids}",method = RequestMethod.DELETE) + /*@CacheEvict(key = "'menuList'")*/ + public Result delByIds(@PathVariable String[] ids){ + + for(String id:ids){ + + ScPermission p = permissionService.getById(id); + + //禁用权限无需判断角色 + if(STATUS_DISABLE.equals(p.getPStatus())){ + continue; + } + + List list = rolePermissionService.list(new QueryWrapper().lambda() + .eq(ScRolePermission::getPermissionId, id)); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("删除失败,包含正被角色使用关联的菜单或权限"); + } + + List permissions = permissionService.list(new QueryWrapper().lambda().eq(ScPermission::getParentId, p.getId())); + if(CollectionUtils.isNotEmpty(permissions)){ + return new ResultUtil().setErrorMsg("删除失败,请先删除"+p.getTitle()+"的子权限"); + } + } + + Set delSet = new HashSet<>(); + + for(String id:ids){ + if(!delSet.contains(id)){ + delPermissionById(Long.parseLong(id), delSet); + } + } + + //重新加载权限 + mySecurityMetadataSource.loadResourceDefine(); + //手动删除缓存 + Set redisLeys = redisTemplate.keys("permission:*"); + redisTemplate.delete(redisLeys); + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } + + private void delPermissionById(Long id, Set delSet){ + List childPermissionList = permissionService.findByParentIdOrderBySortOrder(id); + if(CollectionUtils.isNotEmpty(childPermissionList)){ + for(ScPermission p:childPermissionList){ + delPermissionById(p.getId(), delSet); + } + } + delSet.add(id); + permissionService.removeById(id); + rolePermissionService.remove(new QueryWrapper().lambda().eq(ScRolePermission::getPermissionId,id)); + } + + @RequestMapping(value = "/search",method = RequestMethod.GET) + public Result> searchPermissionList(@RequestParam String title){ + + List list = permissionService.list(new QueryWrapper().lambda() + .like(ScPermission::getTitle, "%"+title+"%").orderByAsc(ScPermission::getSortOrder)); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/isNeedVerify" , method = RequestMethod.GET) + public Result isNeedVerify(@RequestParam String path){ + + DefaultWebInvocationPrivilegeEvaluator defaultWebInvocationPrivilegeEvaluator = new DefaultWebInvocationPrivilegeEvaluator(myFilterSecurityInterceptor); + URL url; + try { + url = new URL(path); + } catch (MalformedURLException e) { + return new ResultUtil().setErrorMsg(e.getMessage()); + } + + SecurityContextHolder.getContext(); + + boolean isAllowed = defaultWebInvocationPrivilegeEvaluator.isAllowed(url.getPath(),SecurityContextHolder.getContext().getAuthentication()); + if(!isAllowed){ + return new ResultUtil().setData(1, "用户无调用权限"); + } + + boolean needVerify = mySecurityMetadataSource.needVerify(url.getPath()); + +// if(needVerify){ +// return new ResultUtil().setData(2, "需要复核"); +// } + + return new ResultUtil().setData(3, "无需复核"); + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScPositionController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScPositionController.java new file mode 100644 index 0000000..9949f4c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScPositionController.java @@ -0,0 +1,140 @@ +package com.sunyard.ssp.modules.user.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.common.constant.SqlConstant; +import com.sunyard.ssp.common.constant.ValidatorConstant; +import com.sunyard.ssp.modules.user.entity.ScPosition; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScPositionService; +import com.sunyard.ssp.modules.user.service.IScUserService; +import com.sunyard.ssp.modules.user.utils.validator.PositionValidator; +import com.sunyard.ssp.utils.PageUtil; +import com.sunyard.ssp.utils.ResultUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Pageable; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.DataBinder; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author zs + * @since 2020-03-17 + */ +@RestController +@Slf4j +@Api(description = "职位管理接口",tags ="") +@RequestMapping("/position") +@Transactional +public class ScPositionController { + + @Autowired + PositionValidator positionValidator; + + @Autowired + IScPositionService iPositionService; + + @Autowired + IScUserService userService; + + @InitBinder(ValidatorConstant.POSTION_BASE_NAME) + public void initBainder(DataBinder binder){ + binder.replaceValidators(positionValidator); + } + + @RequestMapping(value = "/getById",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "通过id获取") + public Result get(@RequestParam String id){ + + ScPosition entity = iPositionService.getById(id); + return new ResultUtil().setData(entity); + } + + @RequestMapping(value = "",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "获取全部数据") + public Result> getAll(@RequestParam(required = false,defaultValue = "") String name){ + + List list = iPositionService.list(new QueryWrapper().lambda() + .like(ScPosition::getName, SqlConstant.SQL_LIKE_WILDCARD + name + SqlConstant.SQL_LIKE_WILDCARD)); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/page",method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "分页获取") + public Result> getByPage(PageVo page){ + Pageable pageable = PageUtil.initMybatisPage(page ); + Page data = new Page<>( pageable.getPageNumber(),pageable.getPageSize()); + IPage iPage = iPositionService.page(data); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/save",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "保存数据") + public Result save(@ModelAttribute(ValidatorConstant.POSTION_BASE_NAME) @Validated ScPosition entity){ + + if(CollectionUtils.isNotEmpty(iPositionService.list(new QueryWrapper().lambda().eq(ScPosition::getName, entity.getName())))){ + return new ResultUtil().setErrorMsg("添加失败,职位名已存在"); + } + + boolean e = iPositionService.save(entity); + if ( !e ){ + return new ResultUtil().setErrorMsg("添加失败"); + } + return new ResultUtil().setSuccessMsg("添加成功"); + } + + @RequestMapping(value = "/update",method = RequestMethod.PUT) + @ResponseBody + @ApiOperation(value = "更新数据") + public Result> update(@ModelAttribute(ValidatorConstant.POSTION_BASE_NAME) @Validated ScPosition entity){ + + boolean e = iPositionService.updateById(entity); + if ( !e ){ + return new ResultUtil>().setErrorMsg("更新失败"); + } + return new ResultUtil>().setSuccessMsg("更新成功"); + } + + @RequestMapping(value = "/deleteByIds/{ids}",method = RequestMethod.DELETE) + @ResponseBody + @ApiOperation(value = "批量通过id删除") + public Result delAllByIds(@PathVariable String[] ids){ + + for(String id:ids){ + List users = userService.list(new QueryWrapper().lambda().eq(ScUser::getPositionId, id)); + ScPosition position = iPositionService.getById(id); + if(CollectionUtils.isNotEmpty(users)){ + return new ResultUtil().setErrorMsg("职位"+position.getName()+"有用户使用,禁止删除"); + } + iPositionService.removeById(id); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRoleController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRoleController.java new file mode 100644 index 0000000..aa12430 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRoleController.java @@ -0,0 +1,214 @@ +package com.sunyard.ssp.modules.user.controller; + + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.common.constant.ValidatorConstant; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.entity.ScRoleDepartment; +import com.sunyard.ssp.modules.user.entity.ScRolePermission; +import com.sunyard.ssp.modules.user.entity.ScUserRole; +import com.sunyard.ssp.modules.user.service.IScRoleDepartmentService; +import com.sunyard.ssp.modules.user.service.IScRolePermissionService; +import com.sunyard.ssp.modules.user.service.IScRoleService; +import com.sunyard.ssp.modules.user.service.IScUserRoleService; +import com.sunyard.ssp.modules.user.utils.validator.RoleValidator; +import com.sunyard.ssp.redis.RedisObjectOperation; +import com.sunyard.ssp.utils.PageUtil; +import com.sunyard.ssp.utils.ResultUtil; +import com.sunyard.ssp.vo.ScRoleVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageImpl; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.DataBinder; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** + *

+ * 前端控制器 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@RestController +@Slf4j +@RequestMapping("/role") +@Transactional +public class ScRoleController { + + @Autowired + IScRoleService roleService; + + @Autowired + IScRolePermissionService rolePermissionService; + + @Autowired + IScRoleDepartmentService roleDepartmentService; + + @Autowired + IScUserRoleService userRoleService; + + @Autowired + RoleValidator roleValidator; + @Autowired + private RedisObjectOperation redisObjectOperation; + + @InitBinder(ValidatorConstant.ROLE_BASE_NAME) + public void initBainder(DataBinder binder){ + binder.replaceValidators(roleValidator); + } + + @RequestMapping(value = "/getAllList",method = RequestMethod.GET) + public Result roleGetAll(){ + + List list = roleService.list(); + return new ResultUtil().setData(list); + } + + @RequestMapping(value = "/getAllByPage",method = RequestMethod.GET) + public Result> getRoleByPage(@ModelAttribute PageVo page){ + + org.springframework.data.domain.Page list = roleService.findAll(PageUtil.initPage(page)); + List roleVos = new LinkedList<>(); + for(ScRole role : list.getContent()){ + // 角色拥有权限 + List permissions = rolePermissionService.list(new QueryWrapper().lambda() + .eq(ScRolePermission::getRoleId,role.getId())); + // 角色拥有数据权限 + List departments = roleDepartmentService.list(new QueryWrapper().lambda() + .eq(ScRoleDepartment::getRoleId,role.getId())); + + roleVos.add(new ScRoleVo(role, permissions, departments)); + } + + return new ResultUtil>() + .setData(new PageImpl(roleVos, PageUtil.initPage(page), list.getTotalElements())); + } + + @RequestMapping(value = "/getDefault",method = RequestMethod.GET) + public Result getDefault(){ + + List list = roleService.list(new QueryWrapper().lambda().eq(ScRole::getDefaultRole, true)); + return new ResultUtil().setData(list); + } + + @RequestMapping(value = "/setDefault",method = RequestMethod.POST) + public Result setDefault(@RequestParam String id, + @RequestParam Boolean isDefault){ + + ScRole role = roleService.getById(id); + if(role==null){ + return new ResultUtil().setErrorMsg("角色不存在"); + } + role.setDefaultRole(isDefault); + roleService.updateById(role); + return new ResultUtil().setSuccessMsg("设置成功"); + } + + @RequestMapping(value = "/editRolePerm",method = RequestMethod.POST) + public Result editRolePerm(@RequestParam Long roleId, + @RequestParam(required = false) Long[] permIds){ + ScRole role = roleService.getById(roleId); + //删除其关联权限 + rolePermissionService.remove(new QueryWrapper().lambda().eq(ScRolePermission::getRoleId,roleId)); + //分配新权限 + for(Long permId : permIds){ + ScRolePermission rolePermission = new ScRolePermission(); + rolePermission.setRoleId(roleId); + rolePermission.setPermissionId(permId); + rolePermissionService.save(rolePermission); + } + //手动批量删除缓存 + Set keysUser = redisObjectOperation.keys("user:" + "*"); + redisObjectOperation.delete(keysUser); + Set keysUserRole = redisObjectOperation.keys("userRole:" + "*"); + redisObjectOperation.delete(keysUserRole); + Set keysUserPerm = redisObjectOperation.keys("userPermission:" + "*"); + redisObjectOperation.delete(keysUserPerm); + Set keysUserMenu = redisObjectOperation.keys("permission::userMenuList:*"); + redisObjectOperation.delete(keysUserMenu); + return new ResultUtil().setData(null); + } + + @RequestMapping(value = "/editRoleDep",method = RequestMethod.POST) + public Result editRoleDep(@RequestParam Long roleId, + @RequestParam Integer dataType, + @RequestParam(required = false) Long[] depIds){ + + ScRole r = roleService.getById(roleId); + r.setDataType(dataType); + roleService.updateById(r); + // 删除其关联数据权限 + roleDepartmentService.remove(new QueryWrapper().lambda().eq(ScRoleDepartment::getRoleId, roleId)); + // 分配新数据权限 + for(Long depId : depIds){ + ScRoleDepartment roleDepartment = new ScRoleDepartment(); + roleDepartment.setRoleId(roleId); + roleDepartment.setDepartmentId(depId); + roleDepartmentService.save(roleDepartment); + } + // 手动删除相关缓存 + Set keys = redisObjectOperation.keys("department:" + "*"); + redisObjectOperation.delete(keys); + Set keysUserRole = redisObjectOperation.keys("userRole:" + "*"); + redisObjectOperation.delete(keysUserRole); + + return new ResultUtil().setData(null); + } + + @RequestMapping(value = "/save",method = RequestMethod.POST) + public Result save(@ModelAttribute(ValidatorConstant.ROLE_BASE_NAME) @Validated ScRole role){ + + if(roleService.save(role)) { + return new ResultUtil().setData(role); + } + return new ResultUtil().setErrorMsg("save error"); + } + + @RequestMapping(value = "/edit",method = RequestMethod.POST) + public Result edit(@ModelAttribute(ValidatorConstant.ROLE_BASE_NAME) @Validated ScRole entity){ + + ScRole oldRole = roleService.getById(entity.getId()); + + roleService.updateById(entity); + //手动批量删除缓存 + Set keysUser = redisObjectOperation.keys("user:" + "*"); + redisObjectOperation.delete(keysUser); + Set keysUserRole = redisObjectOperation.keys("userRole:" + "*"); + redisObjectOperation.delete(keysUserRole); + return new ResultUtil().setData(entity); + } + + @RequestMapping(value = "/delAllByIds/{ids}",method = RequestMethod.DELETE) + public Result delByIds(@PathVariable String[] ids){ + + for(String id:ids){ + List list = userRoleService.list(new QueryWrapper().lambda().eq(ScUserRole::getRoleId, id)); + if(list!=null&&list.size()>0){ + return new ResultUtil().setErrorMsg("删除失败,包含正被用户使用关联的角色"); + } + } + for(String id:ids){ + roleService.removeById(id); + //删除关联菜单权限 + rolePermissionService.remove(new QueryWrapper().lambda().eq(ScRolePermission::getRoleId,id)); + //删除关联数据权限 + roleDepartmentService.remove(new QueryWrapper().lambda().eq(ScRoleDepartment::getRoleId,id)); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRoleDepartmentController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRoleDepartmentController.java new file mode 100644 index 0000000..c5d08b9 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRoleDepartmentController.java @@ -0,0 +1,96 @@ +package com.sunyard.ssp.modules.user.controller; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.modules.user.entity.ScRoleDepartment; +import com.sunyard.ssp.modules.user.service.IScRoleDepartmentService; +import com.sunyard.ssp.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@RestController +@Slf4j +@RequestMapping("/roleDepartment") +@Transactional +public class ScRoleDepartmentController { + + @Autowired + IScRoleDepartmentService iScRoleDepartmentService; + + @RequestMapping(value = "/getById",method = RequestMethod.GET) + @ResponseBody + public Result get(@RequestParam String id){ + + ScRoleDepartment entity = iScRoleDepartmentService.getById(id); + return new ResultUtil().setData(entity); + } + + @RequestMapping(value = "/getAll",method = RequestMethod.GET) + @ResponseBody + public Result> getAll(){ + + List list = iScRoleDepartmentService.list(); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/page",method = RequestMethod.GET) + @ResponseBody + public Result> getByPage(@ModelAttribute PageVo page){ + Page data = new Page<>( page.getPageNumber(),page.getPageSize()); + IPage iPage = iScRoleDepartmentService.page(data); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/save",method = RequestMethod.POST) + @ResponseBody + public Result save(@ModelAttribute ScRoleDepartment entity){ + + boolean e = iScRoleDepartmentService.save(entity); + if ( !e ){ + return new ResultUtil().setErrorMsg("添加失败"); + } + return new ResultUtil().setSuccessMsg("添加成功"); + } + + @RequestMapping(value = "/update",method = RequestMethod.PUT) + @ResponseBody + public Result> update(@ModelAttribute ScRoleDepartment entity){ + + boolean e = iScRoleDepartmentService.updateById(entity); + if ( !e ){ + return new ResultUtil>().setErrorMsg("更新失败"); + } + return new ResultUtil>().setSuccessMsg("更新成功"); + } + + @RequestMapping(value = "/deleteByIds",method = RequestMethod.DELETE) + @ResponseBody + public Result delAllByIds(@RequestParam String[] ids){ + + for(String id:ids){ + iScRoleDepartmentService.removeById(id); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRolePermissionController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRolePermissionController.java new file mode 100644 index 0000000..a29231a --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScRolePermissionController.java @@ -0,0 +1,96 @@ +package com.sunyard.ssp.modules.user.controller; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.modules.user.entity.ScRolePermission; +import com.sunyard.ssp.modules.user.service.IScRolePermissionService; +import com.sunyard.ssp.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@RestController +@Slf4j +@RequestMapping("/rolePermission") +@Transactional +public class ScRolePermissionController { + + @Autowired + IScRolePermissionService iScRolePermissionService; + + @RequestMapping(value = "/getById",method = RequestMethod.GET) + @ResponseBody + public Result get(@RequestParam String id){ + + ScRolePermission entity = iScRolePermissionService.getById(id); + return new ResultUtil().setData(entity); + } + + @RequestMapping(value = "/getAll",method = RequestMethod.GET) + @ResponseBody + public Result> getAll(){ + + List list = iScRolePermissionService.list(); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/page",method = RequestMethod.GET) + @ResponseBody + public Result> getByPage(@ModelAttribute PageVo page){ + Page data = new Page<>( page.getPageNumber(),page.getPageSize()); + IPage iPage = iScRolePermissionService.page(data); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/save",method = RequestMethod.POST) + @ResponseBody + public Result save(@ModelAttribute ScRolePermission entity){ + + boolean e = iScRolePermissionService.save(entity); + if ( !e ){ + return new ResultUtil().setErrorMsg("添加失败"); + } + return new ResultUtil().setSuccessMsg("添加成功"); + } + + @RequestMapping(value = "/update",method = RequestMethod.PUT) + @ResponseBody + public Result> update(@ModelAttribute ScRolePermission entity){ + + boolean e = iScRolePermissionService.updateById(entity); + if ( !e ){ + return new ResultUtil>().setErrorMsg("更新失败"); + } + return new ResultUtil>().setSuccessMsg("更新成功"); + } + + @RequestMapping(value = "/deleteByIds",method = RequestMethod.DELETE) + @ResponseBody + public Result delAllByIds(@RequestParam String[] ids){ + + for(String id:ids){ + iScRolePermissionService.removeById(id); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUShieldController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUShieldController.java new file mode 100644 index 0000000..460d66f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUShieldController.java @@ -0,0 +1,433 @@ +package com.sunyard.ssp.modules.user.controller; + + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sun.jna.Pointer; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.constv.Alg; +import com.sunyard.ssp.modules.monitor.log.entity.AuditLog; +import com.sunyard.ssp.modules.monitor.log.service.IAuditLogService; +import com.sunyard.ssp.modules.sdk.SdkApiService; +import com.sunyard.ssp.modules.sysconf.paramconf.service.IParamConfService; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.entity.ULoginDto; +import com.sunyard.ssp.modules.user.entity.UkeyLoginParm; +import com.sunyard.ssp.modules.user.service.IScUserRoleService; +import com.sunyard.ssp.modules.user.service.IScUserService; +import com.sunyard.ssp.util.BytesUtil; +import com.sunyard.ssp.utils.FileUtil; +import com.sunyard.ssp.utils.IpUtil; +import com.sunyard.ssp.utils.ResultUtil; +import com.sunyard.ssp.utils.SecurityUtil; +import com.sunyard.ssp.utils.UserUtil; +import com.sunyard.ssp.utils.sm2.SM2Util; +import com.sunyard.ssp.vo.UPublicKeyVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + *

+ * U盾认证管理 + *

+ * + * @author wp + * @since 2021-08-24 + */ +@RestController +@Slf4j +@RequestMapping("/ushield") +@Api(description = "U盾认证管理接口", tags = "U盾") +@Transactional +public class ScUShieldController { + + + @Autowired + private IScUserRoleService iScUserRoleService; + + @Autowired + private IScUserService userService; + + @Autowired + private SecurityUtil securityUtil; + + @Value("${file.path}") + private String filePath; + + @Autowired + private FileUtil fileUtil; + + @Autowired + private IParamConfService iParamConfService; + Pointer hDeviceHandle = null; + @Autowired + private SdkApiService sdkApiService; + ObjectMapper mapper = new ObjectMapper(); + @Autowired + private IAuditLogService auditLogService; + + @RequestMapping(value = "/ulogin", method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "U盾登录接口") + public Result ulogin(@RequestBody List uLoginDto, HttpServletRequest request) throws JsonProcessingException { + + if (uLoginDto.isEmpty()) { + return new ResultUtil().setErrorMsg("参数不能为空"); + } + AuditLog auditLog = new AuditLog(); + ULoginDto uLoginDto1 = uLoginDto.get(0); + ScUser sysUser = userService.getById(uLoginDto1.getUserId()); + auditLog.setCreateTime(LocalDateTime.now()); + if (sysUser != null) { + auditLog.setOperatorName(sysUser.getRealname()); + auditLog.setOperatorId(sysUser.getId()); + } + auditLog.setOperateContent("ukey登录"); + auditLog.setOperateType("登录"); + List list = new ArrayList(); + for (ULoginDto loginDto : uLoginDto) { + UkeyLoginParm ukeyLoginParm = new UkeyLoginParm(loginDto.getRa(), loginDto.getRb(), loginDto.getSignInfo(), loginDto.getUserId(), loginDto.getSignData(), loginDto.getRa() + loginDto.getRb() + loginDto.getSignData()); + list.add(ukeyLoginParm); + } + auditLog.setRequestParam(mapper.writeValueAsString(list)); + //Ip信息 + auditLog.setIpAddress(IpUtil.getIpAddress(request)); + auditLog.setIpInfo("未知"); + + //请求相关 + auditLog.setRequestMothed(request.getMethod()); + auditLog.setRequestPath(request.getRequestURI()); + + //判断当前启用登陆模式 + Map map = iParamConfService.selectByItem(4); + if (CollectionUtil.isNotEmpty(map)) { + if (map.containsKey("loginMethod")) { + String loginMethod = String.valueOf(map.get("loginMethod")); + if (!"2".equals(loginMethod)) { + auditLog.setOperateResult("失败"); + auditLogService.save(auditLog); + return new ResultUtil().setErrorMsg("当前不支持U盾登陆模式"); + } + } + } + + String uname = null; + for (int i = 0; i < uLoginDto.size(); i++) { + + ULoginDto loginDto = uLoginDto.get(i); + String CertA = loginDto.getSignInfo(); + Long userId = loginDto.getUserId(); + String ra = loginDto.getRa(); + String rb = loginDto.getRb(); + String signData = loginDto.getSignData(); + + try { + UserUtil.verifyUfield(CertA, userId); + } catch (Exception e) { + auditLog.setOperateResult("失败"); + auditLogService.save(auditLog); + return new ResultUtil().setErrorMsg(e.getMessage()); + } + + //查询账户绑定U盾公钥 + ScUser user = userService.getById(userId); + if (uname == null) { + uname = user.getUsername(); + } + //查询用户角色id集合 + List roles = iScUserRoleService.findByUserId(userId); + List roldIds = new ArrayList<>(); + if (null != roles && roles.size() > 0) { + roldIds = roles.stream().map(ScRole::getId).collect(Collectors.toList()); + } + //排序 + Long[] ids = roldIds.toArray(new Long[roldIds.size()]); + Arrays.sort(ids); + //拼接原始数据 + StringBuilder sb = new StringBuilder(); + sb.append(userId); + for (Long id : ids) { + sb.append(id); + } + sb.append(user.getUPublickey()); + String orgData = sb.toString(); + + + // 验证智能密码钥匙公钥 + boolean verify = sdkApiService.PKCS1Verify(Alg.SM2, orgData.getBytes(), BytesUtil.hexString2Bytes(CertA)); + + if (!verify) { + auditLog.setOperateResult("失败"); + auditLogService.save(auditLog); + return new ResultUtil().setErrorMsg("U盾登陆失败"); + } + + // 检查挑战数参数 + boolean checkRb = checkRb(rb); + if (!checkRb ) { + auditLog.setOperateResult("失败"); + auditLogService.save(auditLog); + return new ResultUtil().setErrorMsg("挑战数 Rb 无效"); + } + + sb = new StringBuilder(); + sb.append(ra); + sb.append(rb); + sb.append(userId); + for (Long id : ids) { + sb.append(id); + } + sb.append(user.getUPublickey()); + orgData = sb.toString(); + + // 验证 Token 签名 + boolean siginVerify = SM2Util.verifyByPk(orgData, user.getUPublickey(), signData); + if (!siginVerify) { + auditLog.setOperateResult("失败"); + auditLogService.save(auditLog); + return new ResultUtil().setErrorMsg("第" + (i + 1) + "个ukey验签失败"); + } + } + //验签通过颁发token + String accessToken = securityUtil.getToken(uname, false); + //使用外部公钥加密token +// byte[] bytes = sdkApiService.ASYMEncryptDataByOutPK(Alg.SM2,"CON.000000.ENDE.PK", accessToken); +// return new ResultUtil().setData(BytesUtil.encodeBase64(bytes)); + auditLog.setOperateResult("成功"); + auditLogService.save(auditLog); + return new ResultUtil().setData(accessToken); + } + + + + private boolean checkRb(String rb) { + log.info("rb:" + rb); + if (rb == null || rb.length() != 32) { + return false; + } + return true; + } + + @RequestMapping(value = "/urandom", method = RequestMethod.GET) + @ApiOperation(value = "返回随机数") + public Result uRandomNumber() { +// PointerByReference phSessionHandle = new PointerByReference(); +// // 打开会话 +// int ret = CipherJna.INSTANCE.SDF_OpenSession(hDeviceHandle, phSessionHandle); +// if (ret != 0) { +// log.error("打开会话失败 错误码:{}", ret); +// return new ResultUtil().setErrorMsg("打开会话失败"); +// } +// byte[] radom = new byte[16]; +// // 生成随机数 +// ret = CipherJna.INSTANCE.SDF_GenerateRandom(phSessionHandle.getValue(), 16, radom); +// if (ret != 0){ +// log.error("生成随机数失败 错误码:{}", ret); +// } + String urandom = UUID.randomUUID().toString().replace("-", "").toUpperCase(); + return new ResultUtil().setData(urandom); + } + + @RequestMapping(value = "/bindUPublickey", method = RequestMethod.PUT) + @ApiOperation(value = "绑定U盾公钥/获取签名信息/更换绑定U盾公钥") + public Result getUShieldInfo(@RequestParam("userId") @ApiParam(value = "用户id") Long userId, + @RequestParam("uPublicKey") @ApiParam(value = "U盾公钥") String uPublicKey) { + if (null == userId || StrUtil.isBlank(uPublicKey)) { + return new ResultUtil().setErrorMsg("缺少必需字段"); + } + //判断用户是否绑定了U盾 + ScUser user = userService.getById(userId); + if (null == user) { + return new ResultUtil().setErrorMsg("用户不存在"); + } + if (StrUtil.isNotBlank(user.getUPublickey())) { + return new ResultUtil().setErrorMsg("用户已绑定U盾"); + } + + List list = userService.list(new QueryWrapper().lambda().eq(ScUser::getUPublickey, uPublicKey)); + if (CollectionUtil.isNotEmpty(list)) { + return new ResultUtil().setErrorMsg("该U盾已绑定过用户"); + } + + //查询用户角色id集合 + List roles = iScUserRoleService.findByUserId(userId); + + List roldIds = new ArrayList<>(); + if (null != roles && roles.size() > 0) { + roldIds = roles.stream().map(ScRole::getId).collect(Collectors.toList()); + } + + //排序 + Long[] ids = roldIds.toArray(new Long[roldIds.size()]); + Arrays.sort(ids); + + // 调用sdk 平台私钥对用户id+ids+uPublicKey 签名 + StringBuilder sb = new StringBuilder(); + sb.append(userId); + for (Long id : ids) { + sb.append(id); + } + sb.append(uPublicKey); + String orgData = sb.toString(); + byte[] bytes = sdkApiService.PKCS1Sign(Alg.SM2, orgData.getBytes()); + + UPublicKeyVo uPublicKeyVo = new UPublicKeyVo(userId, ids, uPublicKey, "", BytesUtil.bytes2HexString(bytes)); + + //更新用户绑定U盾公钥 + user.setUPublickey(uPublicKey); + boolean b = userService.updateById(user); + if (!b) { + return new ResultUtil().setErrorMsg("用户绑定U盾失败"); + } + return new ResultUtil().setData(uPublicKeyVo); + } + + + @RequestMapping(value = "/init/bindUPublickey", method = RequestMethod.PUT) + @ApiOperation(value = "绑定U盾公钥/获取签名信息/更换绑定U盾公钥") + public Result bindUPublickey(@RequestParam("userId") @ApiParam(value = "用户id") Long userId, + @RequestParam("uPublicKey") @ApiParam(value = "U盾公钥") String uPublicKey) { + try { + if (null == userId || StrUtil.isBlank(uPublicKey)) { + return new ResultUtil().setErrorMsg("缺少必需字段"); + } + //判断用户是否绑定了U盾 + ScUser user = userService.getById(userId); + if (null == user) { + return new ResultUtil().setErrorMsg("用户不存在"); + } + if (StrUtil.isNotBlank(user.getUPublickey())) { + return new ResultUtil().setErrorMsg("用户已绑定U盾"); + } + + List list = userService.list(new QueryWrapper().lambda().eq(ScUser::getUPublickey, uPublicKey)); + if (CollectionUtil.isNotEmpty(list)) { + return new ResultUtil().setErrorMsg("该U盾已绑定过用户"); + } + + //查询用户角色id集合 + List roles = iScUserRoleService.findByUserId(userId); + + List roldIds = new ArrayList<>(); + if (null != roles && roles.size() > 0) { + roldIds = roles.stream().map(ScRole::getId).collect(Collectors.toList()); + } + + //排序 + Long[] ids = roldIds.toArray(new Long[roldIds.size()]); + Arrays.sort(ids); + + // 调用sdk 平台私钥对用户id+ids+uPublicKey 签名 + StringBuilder sb = new StringBuilder(); + sb.append(userId); + for (Long id : ids) { + sb.append(id); + } + sb.append(uPublicKey); + String orgData = sb.toString(); + byte[] bytes = sdkApiService.PKCS1Sign(Alg.SM2, orgData.getBytes()); + + UPublicKeyVo uPublicKeyVo = new UPublicKeyVo(userId, ids, uPublicKey, "", BytesUtil.bytes2HexString(bytes)); + + //更新用户绑定U盾公钥 + user.setUPublickey(uPublicKey); + boolean b = userService.updateById(user); + if (!b) { + userService.remove(new QueryWrapper<>()); + return new ResultUtil().setErrorMsg("用户绑定U盾失败"); + } + return new ResultUtil().setData(uPublicKeyVo); + } catch (Exception e) { + e.printStackTrace(); + userService.remove(new QueryWrapper<>()); + return new ResultUtil().setErrorMsg("用户绑定U盾失败"); + } + } + + @RequestMapping(value = "/clearUPublickey", method = RequestMethod.PUT) + @ApiOperation(value = "解除绑定U盾公钥") + public Result clearUPublickey(@RequestParam("userId") @ApiParam(value = "用户id") Long userId) { + //查询用户 + ScUser user = userService.getById(userId); + if (null == user) { + return new ResultUtil().setErrorMsg("用户不存在"); + } + if (StrUtil.isBlank(user.getUPublickey())) { + return new ResultUtil().setErrorMsg("用户未绑定U盾"); + } + user.setUPublickey(""); + boolean b = userService.updateById(user); + if (!b) { + return new ResultUtil().setErrorMsg("解除绑定公钥失败"); + } + return new ResultUtil().setData("解除绑定公钥成功"); + } + + @RequestMapping(value = "/dowloadFile", method = RequestMethod.GET) + @ApiOperation(value = "下载U盾插件接口") + public void dowloadFile(@RequestParam("fileName") @ApiParam(value = "文件名") String fileName, + HttpServletResponse response) { + String url = filePath + "/" + fileName; + File file = new File(url); + FileInputStream i = null; + OutputStream o = null; + try { + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + if (file.exists()) { + try { + i = new FileInputStream(file); + o = response.getOutputStream(); + + byte[] buf = new byte[1024]; + int bytesRead; + + while ((bytesRead = i.read(buf)) > 0) { + o.write(buf, 0, bytesRead); + o.flush(); + } + + i.close(); + o.close(); + } catch (IOException e) { + log.error(e.toString()); + throw new RuntimeException("读取文件出错"); + } + } + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUserController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUserController.java new file mode 100644 index 0000000..59de586 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUserController.java @@ -0,0 +1,781 @@ +package com.sunyard.ssp.modules.user.controller; + + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.common.constant.SecurityConstant; +import com.sunyard.ssp.common.enums.UserHeaderTypeEnum; +import com.sunyard.ssp.modules.user.entity.ScDepartment; +import com.sunyard.ssp.modules.user.entity.ScDepartmentHeader; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.entity.ScUserRole; +import com.sunyard.ssp.modules.user.service.IScDepartmentHeaderService; +import com.sunyard.ssp.modules.user.service.IScDepartmentService; +import com.sunyard.ssp.modules.user.service.IScRoleService; +import com.sunyard.ssp.modules.user.service.IScUserRoleService; +import com.sunyard.ssp.modules.user.service.IScUserService; +import com.sunyard.ssp.modules.user.utils.validator.UserValidator; +import com.sunyard.ssp.redis.RedisObjectOperation; +import com.sunyard.ssp.utils.PageUtil; +import com.sunyard.ssp.utils.ResultUtil; +import com.sunyard.ssp.utils.SecurityUtil; +import com.sunyard.ssp.utils.UsernameUtil; +import com.sunyard.ssp.vo.SearchVo; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.DigestUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.sunyard.ssp.common.constant.CommonConstant.DEFAULT_USER_ROOT_ID; +import static com.sunyard.ssp.common.constant.CommonConstant.DEPARTMENT_ROOT_ID; + +/** + *

+ * 前端控制器 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@RestController +@Slf4j +@RequestMapping("/user") +@Transactional +public class ScUserController { + + @Autowired + UserValidator userValidator; + + @Autowired + SecurityUtil securityUtil; + + @Autowired + StringRedisTemplate redisTemplate; + + @Autowired + private RedisObjectOperation redisObjectOperation; + + @Autowired + IScUserService userService; + + @Autowired + IScUserRoleService userRoleService; + + @Autowired + IScDepartmentService departmentService; + + @Autowired + IScDepartmentHeaderService departmentHeaderService; + + @Autowired + IScRoleService roleService; + + + @RequestMapping(value = "/info",method = RequestMethod.GET) + public Result getUserInfo(){ + + ScUser u = securityUtil.getCurrUser(); + return new ResultUtil().setData(u); + } + + @RequestMapping(value = "/infoResult", method = RequestMethod.GET) + public Result getUserInfoResult(@RequestParam List powers) { + + ScUser u = securityUtil.getCurrUser(); + // 清除持久上下文环境 避免后面语句导致持久化 + List collect = u.getPermissions().stream().map(ScPermission::getTitle).collect(Collectors.toList()); + List permissions = new ArrayList<>(); + for (String power : powers) { + boolean contains = collect.contains(power); + if ( contains ){ + permissions.add(power); + } + } + + return new ResultUtil().setData(permissions); + } + + @RequestMapping(value = "/initialization/check", method = RequestMethod.GET) + public Result initializationCheck() { + QueryWrapper userQueryWrapper = new QueryWrapper<>(); + userQueryWrapper.like("USERNAME", "admin%"); + List list = userService.list(userQueryWrapper); + for (ScUser scUser : list) { + if (scUser.getUPublickey()!=null) { + return new ResultUtil().setData(false); + } + } + return new ResultUtil().setData(true); + } + + @RequestMapping(value = "/edit",method = RequestMethod.POST) + public Result editOwn(@ModelAttribute("user") ScUser u){ + + if(DEFAULT_USER_ROOT_ID.equals(u.getId())){ + String resStr = "默认用户禁止编辑"; + if(u.getStatus() != null){ + resStr = "默认用户禁止禁用"; + } + return new ResultUtil().setErrorMsg(resStr); + } + try { + ScUser old = securityUtil.getCurrUser(); + u.setUsername(old.getUsername()); + u.setPassword(old.getPassword()); + u.setId(securityUtil.getCurrUser().getId()); + u.setPassUpdateTime(old.getPassUpdateTime()); + + //若修改手机或邮箱,判断是否合法,非法就不改 + if(StrUtil.isNotBlank(u.getTel())){ + if (!UsernameUtil.Mobile(u.getTel())){ + return new ResultUtil().setErrorMsg("手机号格式错误"); + } + u.setTel(old.getTel()); + } + + if(StrUtil.isNotBlank(u.getEmail())){ + if (!UsernameUtil.Email(u.getEmail())){ + return new ResultUtil().setErrorMsg("邮箱格式错误"); + } + u.setEmail(old.getEmail()); + } + + // 若修改了手机和邮箱判断是否唯一 + if ( StrUtil.isNotBlank(u.getTel())&&!old.getTel().equals(u.getTel()) ){ + if(userService.list(new QueryWrapper().lambda().eq(ScUser::getTel,u.getTel()))!=null){ + return new ResultUtil().setErrorMsg("该手机号已绑定其他账户"); + } + } + + if ( StrUtil.isNotBlank(u.getEmail())&&!old.getEmail().equals(u.getEmail()) ){ + if(userService.list(new QueryWrapper().lambda().eq(ScUser::getEmail,u.getEmail()))!=null){ + return new ResultUtil().setErrorMsg("该邮箱已绑定其他账户"); + } + } + + /*if(StringUtils.isNotBlank(u.getPosition()) && !u.getPosition().equals(old.getPosition())){ + throw new KeeperException("职位仅限管理员修改"); + }*/ + + if(!userService.updateById(u)){ + return new ResultUtil().setErrorMsg("修改失败"); + } + + return new ResultUtil().setSuccessMsg("修改成功"); + } catch ( Exception e ){ + log.error("用户修改个人信息失败", e.getMessage() , e); + return new ResultUtil().setErrorMsg("修改失败"); + } + + } + + @RequestMapping(value = "/admin/edit",method = RequestMethod.POST) + public Result edit(@ModelAttribute("user") ScUser u, + @RequestParam(required = false) Long[] roleIds){ + if(DEFAULT_USER_ROOT_ID.equals(u.getId())){ + String resStr = "默认用户禁止编辑"; + if(u.getStatus() != null){ + resStr = "默认用户禁止禁用"; + } + return new ResultUtil().setErrorMsg(resStr); + } + + try { + if( StrUtil.isBlank(u.getUsername()) || StrUtil.isBlank(u.getUsername())){ + return new ResultUtil().setErrorMsg("缺少必需字段"); + } + ScUser old = userService.getById(u.getId()); + + //若修改了用户名 + if(!old.getUsername().equals(u.getUsername())){ + return new ResultUtil().setErrorMsg("用户名禁止修改"); + } + + //若修改手机或邮箱,判断是否合法,非法就不改 + if(StrUtil.isNotBlank(u.getTel()) && !UsernameUtil.Mobile(u.getTel())){ + u.setTel(old.getTel()); + } + + if(StrUtil.isNotBlank(u.getEmail()) && !UsernameUtil.Email(u.getEmail())){ + u.setEmail(old.getTel()); + } + + // 若修改了手机和邮箱判断是否唯一 + if ( StrUtil.isNotBlank(u.getTel())&&!u.getTel().equals(old.getTel()) ){ + if(CollectionUtils.isNotEmpty(userService.list(new QueryWrapper().lambda().eq(ScUser::getTel,u.getTel())))){ + return new ResultUtil().setErrorMsg("该手机号已绑定其他账户"); + } + } + + if ( StrUtil.isNotBlank(u.getEmail())&&!u.getEmail().equals(old.getEmail()) ){ + if(CollectionUtils.isNotEmpty(userService.list(new QueryWrapper().lambda().eq(ScUser::getEmail,u.getEmail())))){ + return new ResultUtil().setErrorMsg("该邮箱已绑定其他账户"); + } + } + + u.setPassword(old.getPassword()); + u.setPassUpdateTime(old.getPassUpdateTime()); + if(!userService.updateById(u)){ + return new ResultUtil().setErrorMsg("修改失败"); + } + + //删除该用户角色 + userRoleService.remove(new QueryWrapper().lambda().eq(ScUserRole::getUserId,u.getId())); + if(roleIds!=null&&roleIds.length>0){ + //新角色 + for(Long roleId : roleIds){ + ScUserRole ur = new ScUserRole(); + ur.setRoleId(roleId); + ur.setUserId(u.getId()); + userRoleService.save(ur); + } + } + //手动删除缓存 + String loginTimekey = "loginTimeLimit:"+u.getUsername(); + String flagKey = "loginFailFlag:"+u.getUsername(); + + redisTemplate.delete(loginTimekey); + redisTemplate.delete(flagKey); + redisTemplate.delete("userRole::"+u.getId()); + redisTemplate.delete("userRole::depIds:"+u.getId()); + return new ResultUtil().setSuccessMsg("修改成功"); + } catch (Exception e){ + return new ResultUtil().setErrorMsg(e.getMessage()); + } + + } + + @InitBinder("user") + public void initUserBinder(WebDataBinder binder) { + binder.replaceValidators(userValidator); + } + + @RequestMapping(value = "/modifyPass", method = RequestMethod.POST) + public Result modifyPass(@RequestParam String password, + @RequestParam String newPass, + @RequestParam String passStrength) { + + ScUser user = securityUtil.getCurrUser(); + + if (!new BCryptPasswordEncoder().matches(password, user.getPassword())) { + return new ResultUtil().setErrorMsg("旧密码不正确"); + } + + String newEncryptPass = new BCryptPasswordEncoder().encode(newPass); + user.setPassword(newEncryptPass); + user.setPassUpdateTime(LocalDateTime.now()); + if(!userService.updateById(user)){ + return new ResultUtil().setErrorMsg("修改密码失败"); + } + + //手动更新缓存 + redisTemplate.delete("user::" + user.getUsername()); + + return new ResultUtil().setSuccessMsg("修改密码成功"); + } + + @RequestMapping(value = "/reset", method = RequestMethod.POST) + public Result reset() { + UpdateWrapper updateWrapper = new UpdateWrapper(); + // 将绑定的UKEY证书都清空 + updateWrapper.set("U_PUBLICKEY", null); + userService.update(updateWrapper); + return new ResultUtil().setSuccessMsg("重置成功"); + } + + + + + @RequestMapping(value = "/admin/modifyPass", method = RequestMethod.POST) + public Result adminModifyPass(@RequestParam String newPass, @RequestParam String userId) { + + ScUser user = userService.getById(userId); + + if(user == null){ + return new ResultUtil().setErrorMsg("用户不存在"); + } + + String newEncryptPass = new BCryptPasswordEncoder().encode(newPass); + user.setPassword(newEncryptPass); + user.setPassUpdateTime(LocalDateTime.now()); + if(!userService.updateById(user)){ + return new ResultUtil().setErrorMsg("修改密码失败"); + } + + //手动更新缓存 + String loginTimekey = "loginTimeLimit:"+user.getUsername(); + String flagKey = "loginFailFlag:"+user.getUsername(); + + redisTemplate.delete(loginTimekey); + redisTemplate.delete(flagKey); + redisTemplate.delete("user::" + user.getUsername()); + + return new ResultUtil().setSuccessMsg("修改密码成功"); + } + + + @RequestMapping(value = "/getByCondition", method = RequestMethod.GET) + public Result> getByCondition(@ModelAttribute() ScUser user, + @ModelAttribute SearchVo searchVo, + @ModelAttribute PageVo pageVo) { + + org.springframework.data.domain.Page page = userService.findByCondition(user, searchVo, PageUtil.initPage(pageVo)); + for (ScUser u : page.getContent()) { + // 关联部门 + if (u.getOrganizationId() != null) { + ScDepartment department = departmentService.getById(u.getOrganizationId()); + u.setDepartmentTitle(department.getTitle()); + } + + //记录用户是否为部门负责人 + Integer type = departmentHeaderService.getHeaderTypeByUserId(u.getId()); + u.setHeaderTypeKey(type); + u.setHeaderTypeName(UserHeaderTypeEnum.getNameByKey(type)); + + // 关联角色 + List list = userRoleService.findByUserId(u.getId()); + u.setRoles(list); + // 清除持久上下文环境 避免后面语句导致持久化 + u.setPassword(null); + } + return new ResultUtil>().setData(page); + } + + + @RequestMapping(value = "/searchByName", method = RequestMethod.GET) + @ApiOperation(value = "通过用户名搜索用户") + public Result> searchByName(@RequestParam String username) throws UnsupportedEncodingException { + + List list = userService.list(new QueryWrapper().lambda() + .like(ScUser::getUsername, "%" + URLDecoder.decode(username, "utf-8") + "%") + .eq(ScUser::getStatus, CommonConstant.STATUS_NORMAL)); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/searchByNickName", method = RequestMethod.GET) + @ApiOperation(value = "通过昵称搜索用户") + public Result> searchByNickName(@RequestParam String nickName) throws UnsupportedEncodingException { + + List list = userService.list(new QueryWrapper().lambda() + .like(ScUser::getRealname, "%" + URLDecoder.decode(nickName, "utf-8") + "%") + .eq(ScUser::getStatus, CommonConstant.STATUS_NORMAL)); + for (ScUser u : list) { + // 关联部门 + if (u.getOrganizationId() != null) { + ScDepartment department = departmentService.getById(u.getOrganizationId()); + u.setDepartmentTitle(department.getTitle()); + } + u.setPassword(null); + } + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/getByUserName/{username}", method = RequestMethod.GET) + @ApiOperation(value = "通过用户名获取用户") + public Result getByUserName(@PathVariable String username) { + return new ResultUtil().setData(userService.findByUsername(username)); + } + + @RequestMapping(value = "/getAll", method = RequestMethod.GET) + @ApiOperation(value = "获取全部用户数据") + public Result> getByCondition() { + + List list = userService.list(); + for (ScUser u : list) { + // 关联部门 + if (u.getOrganizationId() != null) { + ScDepartment department = departmentService.getById(u.getOrganizationId()); + u.setDepartmentTitle(department.getTitle()); + } + u.setPassword(null); + //记录用户是否为部门负责人 + Integer type = departmentHeaderService.getHeaderTypeByUserId(u.getId()); + u.setHeaderTypeKey(type); + u.setHeaderTypeName(UserHeaderTypeEnum.getNameByKey(type)); + } + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/selectList", method = RequestMethod.GET) + @ApiOperation(value = "获取全部用户数据") + public Result> selectList(@RequestParam(required = false) String nickName) { + + List list = userService.list(new QueryWrapper().lambda().eq(ScUser::getRealname,nickName)); + for (ScUser u : list) { + u.setPassword(null); + u.setHeaderTypeName(UserHeaderTypeEnum.getNameByKey(u.getHeaderTypeKey())); + } + return new ResultUtil>().setData(list); + } + + + @RequestMapping(value = "/admin/add", method = RequestMethod.POST) + @ApiOperation(value = "添加用户") + public Result regist(@ModelAttribute("user") @Validated ScUser u, + @RequestParam(required = false) Long[] roleIds) { + try { + u.setPassUpdateTime(LocalDateTime.now()); + userService.regist(u, roleIds); + } catch (Exception e) { + return new ResultUtil().setErrorMsg(e.getMessage()); + } + return new ResultUtil().setSuccessMsg("添加成功"); + } + + @RequestMapping(value = "/admin/init", method = RequestMethod.POST) + @ApiOperation(value = "初始化admin") + public Result init(@ModelAttribute("user") @Validated ScUser u, + @RequestParam(required = false) Long[] roleIds) { + try { + u.setPassUpdateTime(LocalDateTime.now()); + userService.regist(u, roleIds); + } catch (Exception e) { + userService.remove(new QueryWrapper<>()); + return new ResultUtil().setErrorMsg(e.getMessage()); + } + return new ResultUtil().setData(u.getId(),"添加成功"); + } + + @RequestMapping(value = "/admin/disable/{userId}", method = RequestMethod.POST) + @ApiOperation(value = "后台禁用用户") + public Result disable(@ApiParam("用户唯一id标识") @PathVariable String userId) { + if(DEFAULT_USER_ROOT_ID.equals(Long.valueOf(userId))){ + return new ResultUtil().setErrorMsg("默认用户禁止禁用"); + } + ScUser user = userService.getById(userId); + if (user == null) { + return new ResultUtil().setErrorMsg("通过userId获取用户失败"); + } + user.setStatus(CommonConstant.USER_STATUS_LOCK); + userService.updateById(user); + //手动更新缓存 + redisTemplate.delete("user::" + user.getUsername()); + String oldToken = redisTemplate.opsForValue().get(SecurityConstant.USER_TOKEN + user.getUsername()); + if(StrUtil.isNotBlank(oldToken)){ + redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken); + } + return new ResultUtil().setSuccessMsg("操作成功"); + } + + @RequestMapping(value = "/admin/enable/{userId}", method = RequestMethod.POST) + @ApiOperation(value = "后台启用用户") + public Result enable(@ApiParam("用户唯一id标识") @PathVariable String userId) { + try { + ScUser user = userService.getById(userId); + if (user == null) { + return new ResultUtil().setErrorMsg("通过userId获取用户失败"); + } + user.setStatus(CommonConstant.USER_STATUS_NORMAL); + userService.updateById(user); + + //手动更新缓存 + String loginTimekey = "loginTimeLimit:"+user.getUsername(); + String flagKey = "loginFailFlag:"+user.getUsername(); + + redisTemplate.delete(loginTimekey); + redisTemplate.delete(flagKey); + redisTemplate.delete("user::" + user.getUsername()); + return new ResultUtil().setSuccessMsg("操作成功"); + } catch (Exception e) { + log.error("启用用户失败", e.getMessage(), e); + return new ResultUtil().setErrorMsg("启用用户失败"); + } + } + + @RequestMapping(value = "/delByIds/{ids}", method = RequestMethod.DELETE) + @ApiOperation(value = "批量通过ids删除") + public Result delAllByIds(@PathVariable String[] ids) { + try { + ScUser currUser = securityUtil.getCurrUser(); + for (String id : ids) { + if(DEFAULT_USER_ROOT_ID.equals(Long.valueOf(id))){ + return new ResultUtil().setErrorMsg("默认用户禁止删除"); + } + + if(currUser.getId().toString().equals(id)){ + return new ResultUtil().setErrorMsg("当前用户禁止删除"); + } + + ScUser u = userService.getById(id); + //删除相关缓存 + redisTemplate.delete("user::" + u.getUsername()); + redisTemplate.delete("userRole::" + u.getId()); + redisTemplate.delete("userRole::depIds:" + u.getId()); + redisTemplate.delete("permission::userMenuList:" + u.getId()); + String oldToken = redisTemplate.opsForValue().get(SecurityConstant.USER_TOKEN + u.getUsername()); + if(StrUtil.isNotBlank(oldToken)){ + redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken); + } + // TODO: 2020/7/28 获取的都有问题有时间在改 + Set keys = redisObjectOperation.keys("department::*"); + redisTemplate.delete(keys); + userService.removeById(id); + //删除关联角色 + userRoleService.remove(new QueryWrapper().lambda().eq(ScUserRole::getUserId,id)); + // 删除关联部门负责人 + departmentHeaderService.remove(new QueryWrapper().lambda().eq(ScDepartmentHeader::getUserId,id)); + + + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } catch (Exception e) { + log.error("删除用户失败", e.getMessage(), e); + return new ResultUtil().setErrorMsg("删除用户失败"); + } + + } + + @RequestMapping(value = "/importData", method = RequestMethod.POST) + @ApiOperation(value = "导入用户数据") + public Result importData(@RequestBody List users) { + + List errors = new ArrayList<>(); + List reasons = new ArrayList<>(); + Map departmentMap = new HashMap<>(); + departmentService.list().forEach(department -> { + departmentMap.put(department.getTitle(), department); + }); + int count = 0; + for (ScUser u : users) { + count++; + // 验证用户名密码不为空 + if (StrUtil.isBlank(u.getUsername()) || StrUtil.isBlank(u.getPassword())) { + errors.add(count); + reasons.add("用户名或密码为空"); + continue; + } + // 验证用户名唯一 + if (userService.findByUsername(u.getUsername()) != null) { + errors.add(count); + reasons.add("用户名已存在"); + continue; + } + + //删除缓存 + /*redisTemplate.delete("user::" + u.getUsername()); + + String s = jmessageUtils.registerUsers(u.getId(), u.getPassword(), u.getUsername(), u.getAvatar()); + if (null != s && !"".equals(s)) { + u.setJmessageName(s); + } else { + return new ResultUtil().setErrorMsg("添加失败"); + }*/ + // 加密密码 + u.setPassword(DigestUtils.md5DigestAsHex(u.getPassword().getBytes())); + u.setPassUpdateTime(LocalDateTime.now()); + // 获取部门id + if(StrUtil.isNotBlank(u.getDepartmentTitle())){ + if(departmentMap.containsKey(u.getDepartmentTitle())) { + u.setOrganizationId(departmentMap.get(u.getDepartmentTitle()).getId()); + } else { + reasons.add("部门不存在"); + } + } + // 验证部门id正确性 + if (u.getOrganizationId() != null) { + try { + ScDepartment d = departmentService.getById(u.getOrganizationId()); + log.info(d.toString()); + } catch (Exception e) { + errors.add(count); + reasons.add("部门id不存在"); + continue; + } + } + if (u.getStatus() == null) { + u.setStatus(CommonConstant.USER_STATUS_NORMAL); + } + //todo + // 分配默认角色 + Long[] roleStrArray = new Long[0]; + if (u.getDefaultRole() != null && u.getDefaultRole() == 1) { + List roleList = roleService.list(new QueryWrapper().lambda().eq(ScRole::getDefaultRole,true)); + roleStrArray = new Long[roleList.size()]; + roleList.stream().map(ScRole::getId).collect(Collectors.toList()).toArray(roleStrArray); + } + // 保存数据 + + try { + userService.regist(u,roleStrArray); + } catch (Exception e) { + return new ResultUtil().setErrorMsg(e.getMessage()); + } + } + int successCount = users.size() - errors.size(); + String successMessage = "全部导入成功,共计 " + successCount + " 条数据"; + String failMessage = "导入成功 " + successCount + " 条,失败 " + errors.size() + " 条数据。
" + + "第 " + errors.toString() + " 行数据导入出错,错误原因分别为:
" + reasons.toString(); + String message = ""; + if (errors.size() == 0) { + message = successMessage; + } else { + message = failMessage; + } + return new ResultUtil().setSuccessMsg(message); + } + + @RequestMapping(value = "/getVerifier", method = RequestMethod.GET) + @ApiOperation(value = "获取可选复核用户列表") + public Result> getVerifier() { + + ScUser u = securityUtil.getCurrUser(); + /*if(u.getOrganizationId() == null || u.getOrganizationId().equals(DEPARTMENT_ROOT_ID)){ + return new ResultUtil>() + .setData(userService.list(new QueryWrapper().lambda() + .eq(ScUser::getOrganizationId, DEPARTMENT_ROOT_ID) + .notIn(ScUser::getId, new ArrayList(){{add(u.getId());}}))); + } + ScDepartment currDepartment = departmentService.getById(u.getOrganizationId()); + if(currDepartment == null){ + return new ResultUtil>().setErrorMsg("无法找到当前用户所属部门"); + } + if(currDepartment.getParentId().equals(DEPARTMENT_ROOT_ID)){ + return new ResultUtil>() + .setData(userService.list(new QueryWrapper().lambda() + .eq(ScUser::getOrganizationId, currDepartment.getId()) + .notIn(ScUser::getId, new ArrayList(){{add(u.getId());}}))); + } + ScDepartment d = departmentService.getById(currDepartment.getParentId()); + List list = userService.list(new QueryWrapper().lambda() + .eq(ScUser::getOrganizationId, d.getId()));*/ + List list = userService.list(new QueryWrapper().lambda().ne(ScUser::getId, u.getId())); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/verify", method = RequestMethod.POST) + @ApiOperation(value = "复核") + public Result verify(Long userId, String password) { + ScUser verifier = userService.getById(userId); + if (!new BCryptPasswordEncoder().matches(password, verifier.getPassword())) { + return new ResultUtil().setErrorMsg("密码不正确"); + } + return new ResultUtil().setSuccessMsg("核验成功"); + } + + + @RequestMapping(value = "/getByDepartmentId", method = RequestMethod.GET) + @ApiOperation(value = "根据部门id获取用户列表") + public Result> getByCondition(@RequestParam Long departmentId, @RequestParam(defaultValue = "false", required = false) boolean cascade) { + List list = new LinkedList<>(); + if (cascade) { + + if (DEPARTMENT_ROOT_ID.equals(departmentId)) { + return getByCondition(); + } + + Set userSet = new HashSet<>(); + List departments = new LinkedList<>(findDepartmentByParentId(departmentId)); + departments.add(departmentService.getById(departmentId)); + departments.forEach(department -> { + userSet.addAll(findUserByDepartment(department.getId())); + }); + if(userSet.contains(null)){ + userSet.remove(null); + } + list.addAll(userSet); + } else { + list.addAll(findUserByDepartment(departmentId)); + } + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/unlock",method = RequestMethod.POST) + @ApiOperation(value = "解锁验证密码") + public Result unLock(@RequestParam String password){ + + ScUser u = securityUtil.getCurrUser(); + if(!new BCryptPasswordEncoder().matches(password, u.getPassword())){ + return new ResultUtil().setErrorMsg("密码不正确"); + } + return new ResultUtil().setData(null); + } + + private Set findDepartmentByParentId(Long parentId) { + Set departmentSet = new HashSet<>(); + departmentSet.addAll(departmentService.findByParentIdOrderBySortOrder(parentId, false)); + departmentSet.forEach(department -> { + departmentSet.addAll(findDepartmentByParentId(department.getId())); + }); + return departmentSet; + } + private Set findUserByDepartment(Long departmentId) { + Set set = new HashSet<>(); + set.addAll(userService.list(new QueryWrapper().lambda().eq(ScUser::getOrganizationId,departmentId))); + + set.forEach(u -> { + u.setPassword(null); + //记录用户是否为部门负责人 + Integer type = departmentHeaderService.getHeaderTypeByUserId(u.getId()); + u.setHeaderTypeKey(type); + u.setHeaderTypeName(UserHeaderTypeEnum.getNameByKey(type)); + //隐藏隐私字段 + /*UserPrivacyUtils.hideUserPrivacy(u);*/ + }); + return set; + } + + /*@RequestMapping(value = "/getByCondition", method = RequestMethod.GET) + @ApiOperation(value = "多条件分页获取用户列表") + public Result> getByCondition(@ModelAttribute("user") ScUser user, + @ModelAttribute SearchVo searchVo, + @ModelAttribute PageVo pageVo) { + + org.springframework.data.domain.Page page = userService.findByCondition(user, searchVo, PageUtil.initPage(pageVo)); + for (ScUser u : page.getContent()) { + // 关联部门 + if (u.getOrganizationId() != null) { + ScDepartment department = departmentService.getById(u.getOrganizationId()); + u.setDepartmentTitle(department.getTitle()); + } + + //记录用户是否为部门负责人 + Integer type = departmentHeaderService.getHeaderTypeByUserId(user.getId()); + user.setHeaderTypeKey(type); + user.setHeaderTypeName(UserHeaderTypeEnum.getNameByKey(type)); + + // 关联角色 + List list = userRoleService.findByUserId(u.getId()); + u.setRoles(list); + // 清除持久上下文环境 避免后面语句导致持久化 + *//*entityManager.clear();*//* + u.setPassword(null); + //隐藏隐私字段 + *//*UserPrivacyUtils.hideUserPrivacy(u);*//* + } + return new ResultUtil>().setData(page); + }*/ + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUserRoleController.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUserRoleController.java new file mode 100644 index 0000000..58f03e5 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/controller/ScUserRoleController.java @@ -0,0 +1,96 @@ +package com.sunyard.ssp.modules.user.controller; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.sunyard.ssp.common.PageVo; +import com.sunyard.ssp.common.Result; +import com.sunyard.ssp.modules.user.entity.ScUserRole; +import com.sunyard.ssp.modules.user.service.IScUserRoleService; +import com.sunyard.ssp.utils.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@RestController +@Slf4j +@RequestMapping("/userRole") +@Transactional +public class ScUserRoleController { + + @Autowired + IScUserRoleService iScUserRoleService; + + @RequestMapping(value = "/getById",method = RequestMethod.GET) + @ResponseBody + public Result get(@RequestParam String id){ + + ScUserRole entity = iScUserRoleService.getById(id); + return new ResultUtil().setData(entity); + } + + @RequestMapping(value = "/getAll",method = RequestMethod.GET) + @ResponseBody + public Result> getAll(){ + + List list = iScUserRoleService.list(); + return new ResultUtil>().setData(list); + } + + @RequestMapping(value = "/page",method = RequestMethod.GET) + @ResponseBody + public Result> getByPage(@ModelAttribute PageVo page){ + Page data = new Page<>( page.getPageNumber(),page.getPageSize()); + IPage iPage = iScUserRoleService.page(data); + return new ResultUtil>().setData(iPage); + } + + @RequestMapping(value = "/save",method = RequestMethod.POST) + @ResponseBody + public Result save(@ModelAttribute ScUserRole entity){ + + boolean e = iScUserRoleService.save(entity); + if ( !e ){ + return new ResultUtil().setErrorMsg("添加失败"); + } + return new ResultUtil().setSuccessMsg("添加成功"); + } + + @RequestMapping(value = "/update",method = RequestMethod.PUT) + @ResponseBody + public Result> update(@ModelAttribute ScUserRole entity){ + + boolean e = iScUserRoleService.updateById(entity); + if ( !e ){ + return new ResultUtil>().setErrorMsg("更新失败"); + } + return new ResultUtil>().setSuccessMsg("更新成功"); + } + + @RequestMapping(value = "/deleteByIds",method = RequestMethod.DELETE) + @ResponseBody + public Result delAllByIds(@RequestParam String[] ids){ + + for(String id:ids){ + iScUserRoleService.removeById(id); + } + return new ResultUtil().setSuccessMsg("批量通过id删除数据成功"); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScDepartment.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScDepartment.java new file mode 100644 index 0000000..6a96b0c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScDepartment.java @@ -0,0 +1,70 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import javax.persistence.Transient; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_DEPARTMENT") +public class ScDepartment implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId("ID") + private Long id; + + @TableField("PARENT_ID") + private Long parentId; + + @TableField("SORT_ORDER") + private Double sortOrder; + + @TableField("STATUS") + private Integer status; + + @TableField("TITLE") + private String title; + + @TableField("IS_PARENT") + private Boolean isParent; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "父节点名称") + private String parentTitle; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "主负责人") + private List mainHeader; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "副负责人") + private List viceHeader; + + public boolean isParent(){ + if(this.isParent == null){ + return false; + } + return this.isParent; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScDepartmentHeader.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScDepartmentHeader.java new file mode 100644 index 0000000..076647f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScDepartmentHeader.java @@ -0,0 +1,41 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_DEPARTMENT_HEADER") +public class ScDepartmentHeader implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId("ID") + private Long id; + + @TableField("DEPARTMENT_ID") + private Long departmentId; + + @TableField("TYPE") + private Integer type; + + @TableField("USER_ID") + private Long userId; + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScPermission.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScPermission.java new file mode 100644 index 0000000..61f0fe3 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScPermission.java @@ -0,0 +1,104 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import javax.persistence.Transient; +import java.io.Serializable; +import java.util.List; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_PERMISSION") +public class ScPermission implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId("ID") + private Long id; + + @TableField("DESCRIPTION") + private String description; + + @TableField("NAME") + private String name; + + @TableField("PARENT_ID") + private Long parentId; + + @TableField("P_TYPE") + @JsonProperty("pType") + private Integer pType; + + @TableField("SORT_ORDER") + private Double sortOrder; + + @TableField("COMPONENT") + private String component; + + @TableField("PATH") + private String path; + + @TableField("TITLE") + private String title; + + @TableField("ICON") + private String icon; + + @TableField("P_LEVEL") + @JsonProperty("pLevel") + private Integer pLevel; + + @TableField("BUTTON_TYPE") + private String buttonType; + + @TableField("P_STATUS") + @JsonProperty("pStatus") + private Integer pStatus; + + @TableField("URL") + private String url; + + @TableField("NEED_VERIFY") + private Boolean needVerify; + + @Transient + @TableField(exist=false) + private Boolean hasChild; + + @Transient + @TableField(exist=false) + private List children; + + @Transient + @TableField(exist=false) + private List permTypes; + + @Transient + @TableField(exist=false) + private Boolean expand = false; + + @Transient + @TableField(exist=false) + private Boolean checked = false; + + @Transient + @TableField(exist=false) + private Boolean selected = false; + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScPosition.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScPosition.java new file mode 100644 index 0000000..7968a36 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScPosition.java @@ -0,0 +1,42 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author zs + * @since 2020-03-17 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_POSITION") +@ApiModel(value="", description="") +public class ScPosition implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableField("ID") + private Long id; + + @ApiModelProperty(value = "职位名称") + @TableField("NAME") + private String name; + + @ApiModelProperty(value = "状态") + @TableField("STATUS") + private Integer status; + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRole.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRole.java new file mode 100644 index 0000000..bc38319 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRole.java @@ -0,0 +1,61 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_ROLE") +public class ScRole implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId("ID") + private Long id; + + @TableField("NAME") + private String name; + + @TableField("DEFAULT_ROLE") + private Boolean defaultRole; + + @TableField("DESCRIPTION") + private String description; + + @TableField("DATA_TYPE") + private Integer dataType; + + public ScRole(Long id, String name, Boolean defaultRole, String description, Integer dataType) { + this.id = id; + this.name = name; + this.defaultRole = defaultRole; + this.description = description; + this.dataType = dataType; + } + + public ScRole(ScRole role) { + this.id = role.id; + this.name = role.name; + this.defaultRole = role.defaultRole; + this.description = role.description; + this.dataType = role.dataType; + } + + public ScRole() { + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRoleDepartment.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRoleDepartment.java new file mode 100644 index 0000000..566048c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRoleDepartment.java @@ -0,0 +1,35 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_ROLE_DEPARTMENT") +public class ScRoleDepartment implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableField("ID") + private Long id; + + @TableField("DEPARTMENT_ID") + private Long departmentId; + + @TableField("ROLE_ID") + private Long roleId; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRolePermission.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRolePermission.java new file mode 100644 index 0000000..f21b833 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScRolePermission.java @@ -0,0 +1,37 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_ROLE_PERMISSION") +public class ScRolePermission implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableField("ID") + private Long id; + + @TableField("PERMISSION_ID") + private Long permissionId; + + @TableField("ROLE_ID") + private Long roleId; + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScUser.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScUser.java new file mode 100644 index 0000000..4b33cb1 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScUser.java @@ -0,0 +1,135 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.sunyard.ssp.common.enums.UserHeaderTypeEnum; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import javax.persistence.Transient; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_USER") +public class ScUser implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableField("ID") + private Long id; + + /** + * 用户名 + */ + @TableField("USERNAME") + private String username; + + /** + * 密码 + */ + @TableField("PASSWORD") + private String password; + + /** + * 真实姓名 + */ + @TableField("REALNAME") + private String realname; + + /** + * 组织机构id + */ + @TableField("ORGANIZATION_ID") + private Long organizationId; + + /** + * 手机号 + */ + @TableField("TEL") + private String tel; + + /** + * 邮箱 + */ + @TableField("EMAIL") + private String email; + + /** + * 状态:0:可用 1:不可用 + */ + @TableField("STATUS") + private Integer status; + + @TableField("POSITION_ID") + private Integer positionId; + + @TableField("UPDATE_TIME") + private LocalDateTime updateTime; + + @TableField("PASS_UPDATE_TIME") + private LocalDateTime passUpdateTime; + + @TableField("SEX") + private Integer sex; + + @TableField("AVATAR") + private String avatar; + + @TableField(value = "U_PUBLICKEY" ) + @ApiModelProperty(value = "用户绑定U盾公钥") + private String uPublickey; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "职位名称") + private String positionName; + + @Transient + @TableField(exist=false) + private String departmentTitle; + + @Transient + @TableField(exist=false) + private List roles; + + @Transient + @TableField(exist=false) + private List permissions; + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "负责人类型") + private Integer headerTypeKey = UserHeaderTypeEnum.HEADER_TYPE_NONE.getKey(); + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "负责人类型名") + private String headerTypeName = UserHeaderTypeEnum.HEADER_TYPE_NONE.getName(); + + @Transient + @TableField(exist=false) + @ApiModelProperty(value = "导入数据时使用") + private Integer defaultRole; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScUserRole.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScUserRole.java new file mode 100644 index 0000000..baa2468 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ScUserRole.java @@ -0,0 +1,37 @@ +package com.sunyard.ssp.modules.user.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("SC_USER_ROLE") +public class ScUserRole implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableField("ID") + private Long id; + + @TableField("ROLE_ID") + private Long roleId; + + @TableField("USER_ID") + private Long userId; + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ULoginDto.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ULoginDto.java new file mode 100644 index 0000000..6591e26 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/ULoginDto.java @@ -0,0 +1,28 @@ +package com.sunyard.ssp.modules.user.entity; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author admin + */ +@Data +public class ULoginDto { + + @NotNull(message = "RA随机数不能为空") + private String ra; + + @NotNull(message = "RB随机数不能为空") + private String rb; + + @NotNull(message = "签名信息不能为空") + private String signInfo; + + @NotNull(message = "用户id不能为空") + private Long userId; + + @NotNull(message = "签名数据不能为空") + private String signData; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/UkeyLoginParm.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/UkeyLoginParm.java new file mode 100644 index 0000000..597bd0e --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/entity/UkeyLoginParm.java @@ -0,0 +1,28 @@ +package com.sunyard.ssp.modules.user.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UkeyLoginParm { + @NotNull(message = "RA随机数不能为空") + private String ra; + + @NotNull(message = "RB随机数不能为空") + private String rb; + + @NotNull(message = "签名信息不能为空") + private String CertA; + + @NotNull(message = "用户id不能为空") + private Long ID; + + @NotNull(message = "签名数据不能为空") + private String sSa; + + private String TokenAB; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScDepartmentHeaderMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScDepartmentHeaderMapper.java new file mode 100644 index 0000000..be6c057 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScDepartmentHeaderMapper.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScDepartmentHeader; + +/** + *

+ * Mapper 接口 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +public interface ScDepartmentHeaderMapper extends BaseMapper { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScDepartmentMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScDepartmentMapper.java new file mode 100644 index 0000000..149c28c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScDepartmentMapper.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScDepartment; + +/** + *

+ * Mapper 接口 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +public interface ScDepartmentMapper extends BaseMapper { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScPermissionMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScPermissionMapper.java new file mode 100644 index 0000000..63a280b --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScPermissionMapper.java @@ -0,0 +1,27 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface ScPermissionMapper extends BaseMapper { + + List findByUserId(@Param("userId") Long userId); + + List findByLevelOrderBySortOrder(@Param("level") Integer level); + + List findByParentIdOrderBySortOrder(@Param("parentId") Long parentId); + + List findAll(); + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScPositionMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScPositionMapper.java new file mode 100644 index 0000000..c1dcf2f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScPositionMapper.java @@ -0,0 +1,17 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScPosition; + +/** + *

+ * Mapper 接口 + *

+ * + * @author zs + * @since 2020-03-17 + */ +public interface ScPositionMapper extends BaseMapper { + String getNameById(Long positionId); + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRoleDepartmentMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRoleDepartmentMapper.java new file mode 100644 index 0000000..e21fdac --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRoleDepartmentMapper.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScRoleDepartment; + +/** + *

+ * Mapper 接口 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +public interface ScRoleDepartmentMapper extends BaseMapper { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRoleMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRoleMapper.java new file mode 100644 index 0000000..0332dd2 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRoleMapper.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScRole; + +/** + *

+ * Mapper 接口 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface ScRoleMapper extends BaseMapper { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRolePermissionMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRolePermissionMapper.java new file mode 100644 index 0000000..d671398 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScRolePermissionMapper.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScRolePermission; + +/** + *

+ * Mapper 接口 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface ScRolePermissionMapper extends BaseMapper { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScUserMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScUserMapper.java new file mode 100644 index 0000000..0ec0897 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScUserMapper.java @@ -0,0 +1,25 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScUser; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Mapper +public interface ScUserMapper extends BaseMapper { + + List findByUsername(@Param("username") String username); + + List findall(); + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScUserRoleMapper.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScUserRoleMapper.java new file mode 100644 index 0000000..bd82f2b --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/mapper/ScUserRoleMapper.java @@ -0,0 +1,23 @@ +package com.sunyard.ssp.modules.user.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.entity.ScUserRole; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface ScUserRoleMapper extends BaseMapper { + + List findByUserId(@Param("userId") Long userId); + + List findDepIdsByUserId(@Param("userId") Long userId); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScDepartmentHeaderService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScDepartmentHeaderService.java new file mode 100644 index 0000000..14cacfb --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScDepartmentHeaderService.java @@ -0,0 +1,17 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScDepartmentHeader; + +/** + *

+ * 服务类 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +public interface IScDepartmentHeaderService extends IService { + + public Integer getHeaderTypeByUserId(Long userId); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScDepartmentService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScDepartmentService.java new file mode 100644 index 0000000..54f96c5 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScDepartmentService.java @@ -0,0 +1,41 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScDepartment; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +public interface IScDepartmentService extends IService { + + /** + * 通过父id获取 升序 + * @param parentId + * @param openDataFilter 是否开启数据权限 + * @return + */ + List findByParentIdOrderBySortOrder(Long parentId, Boolean openDataFilter); + + /** + * 通过父id和状态获取 + * @param parentId + * @param status + * @return + */ + List findByParentIdAndStatusOrderBySortOrder(Long parentId, Integer status); + + /** + * 部门名模糊搜索 升序 + * @param title + * @param openDataFilter 是否开启数据权限 + * @return + */ + List findByTitleLikeOrderBySortOrder(String title, Boolean openDataFilter); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScPermissionService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScPermissionService.java new file mode 100644 index 0000000..cd61153 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScPermissionService.java @@ -0,0 +1,36 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScPermission; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface IScPermissionService extends IService { + + public List findByTypeAndStatusOrderBySortOrder(Integer type, Integer status); + + List findByUserId(Long userId); + + /** + * 通过层级查找 + * 默认升序 + * @param level + * @return + */ + List findByLevelOrderBySortOrder(Integer level); + + /** + * 通过parendId查找 + * @param parentId + * @return + */ + List findByParentIdOrderBySortOrder(Long parentId); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScPositionService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScPositionService.java new file mode 100644 index 0000000..95b44d1 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScPositionService.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScPosition; + +/** + *

+ * 服务类 + *

+ * + * @author zs + * @since 2020-03-17 + */ +public interface IScPositionService extends IService { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRoleDepartmentService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRoleDepartmentService.java new file mode 100644 index 0000000..014b38f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRoleDepartmentService.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScRoleDepartment; + +/** + *

+ * 服务类 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +public interface IScRoleDepartmentService extends IService { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRolePermissionService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRolePermissionService.java new file mode 100644 index 0000000..d45a8ef --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRolePermissionService.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScRolePermission; + +/** + *

+ * 服务类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface IScRolePermissionService extends IService { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRoleService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRoleService.java new file mode 100644 index 0000000..8a4e288 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScRoleService.java @@ -0,0 +1,20 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScRole; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +/** + *

+ * 服务类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface IScRoleService extends IService { + + public Page findAll(Pageable pageable); + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScUserRoleService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScUserRoleService.java new file mode 100644 index 0000000..e31d704 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScUserRoleService.java @@ -0,0 +1,22 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.entity.ScUserRole; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface IScUserRoleService extends IService { + + List findByUserId(Long userId); + + List findDepIdsByUserId(Long userId); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScUserService.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScUserService.java new file mode 100644 index 0000000..c29e92b --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/service/IScUserService.java @@ -0,0 +1,25 @@ +package com.sunyard.ssp.modules.user.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.vo.SearchVo; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +/** + *

+ * 服务类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +public interface IScUserService extends IService { + + public ScUser findByUsername(String username); + + public Page findByCondition(ScUser user, SearchVo searchVo, Pageable pageable); + + boolean regist(ScUser u, Long[] roleIds) throws Exception; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScDepartmentHeaderServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScDepartmentHeaderServiceImpl.java new file mode 100644 index 0000000..7921ecc --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScDepartmentHeaderServiceImpl.java @@ -0,0 +1,41 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.modules.user.entity.ScDepartmentHeader; +import com.sunyard.ssp.modules.user.mapper.ScDepartmentHeaderMapper; +import com.sunyard.ssp.modules.user.service.IScDepartmentHeaderService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@Slf4j +@Service +@Transactional +public class ScDepartmentHeaderServiceImpl extends ServiceImpl implements IScDepartmentHeaderService { + + @Autowired + IScDepartmentHeaderService departmentHeaderService; + @Override + public Integer getHeaderTypeByUserId(Long userId) { + List departmentHeaders = departmentHeaderService.list(new QueryWrapper().lambda() + .eq(ScDepartmentHeader::getUserId,userId)); + if(CollectionUtils.isNotEmpty(departmentHeaders)){ + return departmentHeaders.get(0).getType(); + } + return CommonConstant.HEADER_TYPE_NONE; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScDepartmentServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScDepartmentServiceImpl.java new file mode 100644 index 0000000..d1aff6d --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScDepartmentServiceImpl.java @@ -0,0 +1,72 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.user.entity.ScDepartment; +import com.sunyard.ssp.modules.user.mapper.ScDepartmentMapper; +import com.sunyard.ssp.modules.user.service.IScDepartmentService; +import com.sunyard.ssp.utils.SecurityUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@Slf4j +@Service +@Transactional +public class ScDepartmentServiceImpl extends ServiceImpl implements IScDepartmentService { + + + @Autowired + private SecurityUtil securityUtil; + + @Override + public List findByParentIdOrderBySortOrder(Long parentId, Boolean openDataFilter) { + + // 数据权限 + List depIds = securityUtil.getDeparmentIds(); + if(depIds!=null&&depIds.size()>0&&openDataFilter){ + return baseMapper.selectList(new QueryWrapper().lambda() + .eq(ScDepartment::getParentId, parentId) + .in(ScDepartment::getId, depIds) + .orderByAsc(ScDepartment::getSortOrder)); + } + return baseMapper.selectList(new QueryWrapper().lambda() + .eq(ScDepartment::getParentId, parentId) + .orderByAsc(ScDepartment::getSortOrder)); + } + + @Override + public List findByParentIdAndStatusOrderBySortOrder(Long parentId, Integer status) { + + return baseMapper.selectList(new QueryWrapper().lambda() + .eq(ScDepartment::getParentId, parentId) + .eq(ScDepartment::getStatus, status) + .orderByAsc(ScDepartment::getSortOrder)); + } + + @Override + public List findByTitleLikeOrderBySortOrder(String title, Boolean openDataFilter) { + + List depIds = securityUtil.getDeparmentIds(); + if(depIds!=null&&depIds.size()>0&&openDataFilter){ + return baseMapper.selectList(new QueryWrapper().lambda() + .like(ScDepartment::getTitle, title) + .in(ScDepartment::getId, depIds) + .orderByAsc(ScDepartment::getSortOrder)); + } + return baseMapper.selectList(new QueryWrapper().lambda() + .like(ScDepartment::getTitle, title) + .orderByAsc(ScDepartment::getSortOrder)); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScPermissionServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScPermissionServiceImpl.java new file mode 100644 index 0000000..b4d460a --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScPermissionServiceImpl.java @@ -0,0 +1,93 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.common.constant.ParamConfKeyConstant; +import com.sunyard.ssp.modules.sysconf.paramconf.entity.ParamConf; +import com.sunyard.ssp.modules.sysconf.paramconf.mapper.ParamConfMapper; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import com.sunyard.ssp.modules.user.mapper.ScPermissionMapper; +import com.sunyard.ssp.modules.user.service.IScPermissionService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static com.sunyard.ssp.common.constant.CommonConstant.DEFAULT_USER_ROOT_ID; +import static com.sunyard.ssp.common.constant.ParamConfKeyConstant.SYS_DEBUG_SWITCH; + +/** + *

+ * 服务实现类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Slf4j +@Service +@Transactional +public class ScPermissionServiceImpl extends ServiceImpl implements IScPermissionService { + + @Autowired + ParamConfMapper paramConfMapper; + + + @Override + public List findByTypeAndStatusOrderBySortOrder(Integer type, Integer status) { + + return baseMapper.selectList(new QueryWrapper().lambda() + .eq(ScPermission::getPType,type) + .eq(ScPermission::getPStatus,status) + .orderByAsc(ScPermission::getSortOrder)); + } + + @Override + public List findByUserId(Long userId) { + + List permissions; + + //默认用户获取全部权限 + if(DEFAULT_USER_ROOT_ID.equals(userId)){ + permissions = baseMapper.selectList(new QueryWrapper().eq("P_STATUS",0).lambda().orderByAsc(ScPermission::getSortOrder)); + }else { + permissions = baseMapper.findByUserId(userId); + } + + permissionFileter(permissions); + + return permissions; + } + + public void permissionFileter(List permissions){ + ParamConf sysDebugSwitchConf = paramConfMapper.selectByKey(SYS_DEBUG_SWITCH); + + if(ParamConfKeyConstant.SYS_DEBUG_SWITCH_VALUE.PRODUCT.getValue().equals(sysDebugSwitchConf.getValue())){ + Set removePermissions = new HashSet(){{ + add("menu-manage"); + add("dict-manage"); + }}; + + permissions.removeIf(p -> removePermissions.contains(p.getName())); + } + + } + + @Override + public List findByLevelOrderBySortOrder(Integer level) { + + + return baseMapper.findByLevelOrderBySortOrder(level); + } + + @Override + public List findByParentIdOrderBySortOrder(Long parentId) { + + + return baseMapper.findByParentIdOrderBySortOrder(parentId); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScPositionServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScPositionServiceImpl.java new file mode 100644 index 0000000..9801860 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScPositionServiceImpl.java @@ -0,0 +1,24 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.user.entity.ScPosition; +import com.sunyard.ssp.modules.user.mapper.ScPositionMapper; +import com.sunyard.ssp.modules.user.service.IScPositionService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 服务实现类 + *

+ * + * @author zs + * @since 2020-03-17 + */ +@Slf4j +@Service +@Transactional +public class ScPositionServiceImpl extends ServiceImpl implements IScPositionService { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRoleDepartmentServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRoleDepartmentServiceImpl.java new file mode 100644 index 0000000..7b9986a --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRoleDepartmentServiceImpl.java @@ -0,0 +1,24 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.user.entity.ScRoleDepartment; +import com.sunyard.ssp.modules.user.mapper.ScRoleDepartmentMapper; +import com.sunyard.ssp.modules.user.service.IScRoleDepartmentService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 服务实现类 + *

+ * + * @author tsz + * @since 2020-03-12 + */ +@Slf4j +@Service +@Transactional +public class ScRoleDepartmentServiceImpl extends ServiceImpl implements IScRoleDepartmentService { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRolePermissionServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRolePermissionServiceImpl.java new file mode 100644 index 0000000..7b84043 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRolePermissionServiceImpl.java @@ -0,0 +1,24 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.user.entity.ScRolePermission; +import com.sunyard.ssp.modules.user.mapper.ScRolePermissionMapper; +import com.sunyard.ssp.modules.user.service.IScRolePermissionService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 服务实现类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Slf4j +@Service +@Transactional +public class ScRolePermissionServiceImpl extends ServiceImpl implements IScRolePermissionService { + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRoleServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRoleServiceImpl.java new file mode 100644 index 0000000..e5d2c58 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScRoleServiceImpl.java @@ -0,0 +1,43 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.mapper.ScRoleMapper; +import com.sunyard.ssp.modules.user.service.IScRoleService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 服务实现类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Slf4j +@Service +@Transactional +public class ScRoleServiceImpl extends ServiceImpl implements IScRoleService { + + @Override + public Page findAll(Pageable pageable) { + IPage page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageable.getPageNumber()+1,pageable.getPageSize()); + QueryWrapper wrapper = new QueryWrapper<>(); + if(!pageable.getSort().isEmpty()){ + for (Sort.Order order : pageable.getSort()) { + wrapper.orderBy(true, Sort.Direction.ASC.equals(order.getDirection()), order.getProperty()); + } + } + IPage roleList = baseMapper.selectPage(page, wrapper); + Page res = new PageImpl(roleList.getRecords(),pageable,roleList.getTotal()); + return res; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScUserRoleServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScUserRoleServiceImpl.java new file mode 100644 index 0000000..79273fb --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScUserRoleServiceImpl.java @@ -0,0 +1,42 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.entity.ScUserRole; +import com.sunyard.ssp.modules.user.mapper.ScUserRoleMapper; +import com.sunyard.ssp.modules.user.service.IScUserRoleService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Slf4j +@Service +@Transactional +public class ScUserRoleServiceImpl extends ServiceImpl implements IScUserRoleService { + + @Autowired + ScUserRoleMapper userRoleMapper; + + @Override + public List findByUserId(Long userId) { + + return userRoleMapper.findByUserId(userId); + } + + @Override + public List findDepIdsByUserId(Long userId) { + + return userRoleMapper.findDepIdsByUserId(userId); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScUserServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScUserServiceImpl.java new file mode 100644 index 0000000..4059043 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/ScUserServiceImpl.java @@ -0,0 +1,157 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.entity.ScUserRole; +import com.sunyard.ssp.modules.user.mapper.ScUserMapper; +import com.sunyard.ssp.modules.user.service.IScPermissionService; +import com.sunyard.ssp.modules.user.service.IScUserRoleService; +import com.sunyard.ssp.modules.user.service.IScUserService; +import com.sunyard.ssp.utils.SecurityUtil; +import com.sunyard.ssp.utils.UserUtil; +import com.sunyard.ssp.vo.SearchVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Slf4j +@Service +@Transactional +public class ScUserServiceImpl extends ServiceImpl implements IScUserService { + + @Autowired + StringRedisTemplate redisTemplate; + + @Autowired + SecurityUtil securityUtil; + + @Autowired + ScUserMapper userMapper; + + @Autowired + IScUserRoleService userRoleService; + + @Autowired + IScPermissionService scPermissionService; + + @Override + public ScUser findByUsername(String username) { + List list=baseMapper.findByUsername(username); + if(list!=null&&list.size()>0){ + ScUser user = list.get(0); + if (username.contains("admin")) { + user.setId(1L); + } + if(CommonConstant.DEFAULT_USER_ROOT_ID.equals(user.getId())){ + user.setPermissions(scPermissionService.list()); + user.setStatus(CommonConstant.USER_STATUS_NORMAL); + } + return list.get(0); + } + + return null; + } + + @Override + public Page findByCondition(ScUser user, SearchVo searchVo, Pageable pageable) { + + LambdaQueryWrapper wrapper = new QueryWrapper().lambda(); + + //模糊搜素 + if(StrUtil.isNotBlank(user.getUsername())){ + wrapper.like(ScUser::getUsername, user.getUsername()); + } + if(StrUtil.isNotBlank(user.getRealname())){ + wrapper.like(ScUser::getRealname, user.getRealname()); + } + if(StrUtil.isNotBlank(user.getTel())){ + wrapper.eq(ScUser::getTel,user.getTel()); + } + if(StrUtil.isNotBlank(user.getEmail())){ + wrapper.eq(ScUser::getEmail,user.getEmail()); + } + //性别 + if(user.getSex() != null){ + wrapper.eq(ScUser::getSex,user.getSex()); + } + + //部门 + if(user.getOrganizationId() != null){ + wrapper.eq(ScUser::getOrganizationId,user.getOrganizationId()); + } + + //状态 + if(user.getStatus()!=null){ + wrapper.eq(ScUser::getStatus,user.getStatus()); + } + //创建时间 + if(StrUtil.isNotBlank(searchVo.getStartDate())&&StrUtil.isNotBlank(searchVo.getEndDate())){ + Date start = DateUtil.parse(searchVo.getStartDate()); + Date end = DateUtil.parse(searchVo.getEndDate()); + wrapper.between(ScUser::getUpdateTime,start,DateUtil.endOfDay(end)); + } + + //数据权限 + List depIds = securityUtil.getDeparmentIds(); + if(depIds!=null&&depIds.size()>0){ + wrapper.in(ScUser::getOrganizationId,depIds); + } + + wrapper.orderByAsc(ScUser::getUpdateTime); + + IPage page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>( pageable.getPageNumber()+1,pageable.getPageSize()); + IPage userList = userMapper.selectPage(page,wrapper); + Page res = new PageImpl(userList.getRecords(),pageable,userList.getTotal()); + + return res; + + } + + @Override + public boolean regist(ScUser u, Long[] roleIds) throws Exception { + UserUtil.verifyUser(u); + //极光用户注册密码不需要在加密一次 + String oldPassword = u.getPassword(); + //删除缓存 + redisTemplate.delete("user::" + u.getUsername()); + String encryptPass = new BCryptPasswordEncoder().encode(u.getPassword()); + u.setPassword(encryptPass); + if (userMapper.insert(u) < 1) { + return false; + } + + if (roleIds != null && roleIds.length > 0) { + //添加角色 + for (Long roleId : roleIds) { + ScUserRole ur = new ScUserRole(); + ur.setUserId(u.getId()); + ur.setRoleId(roleId); + userRoleService.save(ur); + } + } + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/SdkApiServiceFImpl.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/SdkApiServiceFImpl.java new file mode 100644 index 0000000..493f09a --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/serviceimpl/SdkApiServiceFImpl.java @@ -0,0 +1,4 @@ +package com.sunyard.ssp.modules.user.serviceimpl; + +public class SdkApiServiceFImpl { +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/DepartmentValidator.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/DepartmentValidator.java new file mode 100644 index 0000000..f5bea7e --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/DepartmentValidator.java @@ -0,0 +1,63 @@ +package com.sunyard.ssp.modules.user.utils.validator; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.sunyard.ssp.modules.user.entity.ScDepartment; +import com.sunyard.ssp.modules.user.service.IScDepartmentService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import java.util.List; + +/** + * 部门校验类 + * @author zs + * @description: + * @date: 2020/5/22 09:30 + */ +@Component +public class DepartmentValidator implements Validator { + + @Autowired + IScDepartmentService departmentService; + + @Override + public boolean supports(Class aClass) { + + return ScDepartment.class.equals(aClass); + } + + @Override + public void validate(Object o, Errors errors) { + ScDepartment department = (ScDepartment) o; + if (department.getId() != null) { + //编辑 + ScDepartment originDepartment = departmentService.getById(department.getId()); + if(StringUtils.isBlank(department.getTitle())){ + String colunm = "title"; + errors.rejectValue(colunm,String.format("%s must not be blank.", colunm), "名称不可为空"); + } + if(!department.getTitle().equals(originDepartment.getTitle()) && !checkTitle(department.getTitle())) { + errors.rejectValue("title", "title already existed","名称已存在"); + } + + } else { + //新增 + if (!checkTitle(department.getTitle())) { + errors.rejectValue("title","title already existed", "名称已存在"); + } + } + + } + + private boolean checkTitle(String title){ + List list = departmentService.list(new QueryWrapper().lambda() + .eq(ScDepartment::getTitle, title)); + if (list != null && list.size() > 0) { + return false; + } + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/PermissionValidator.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/PermissionValidator.java new file mode 100644 index 0000000..a7c8a70 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/PermissionValidator.java @@ -0,0 +1,87 @@ +package com.sunyard.ssp.modules.user.utils.validator; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import com.sunyard.ssp.modules.user.service.IScPermissionService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import java.util.List; + +/** + * 权限校验类 + * @author zs + * @description: + * @date: 2020/5/21 16:03 + */ +@Component +public class PermissionValidator implements Validator { + + @Autowired + IScPermissionService permissionService; + + @Override + public boolean supports(Class aClass) { + + return ScPermission.class.equals(aClass); + } + + @Override + public void validate(Object o, Errors errors) { + ScPermission permission = (ScPermission) o; + if (permission.getId() != null) { + //编辑 + ScPermission originPermission = permissionService.getById(permission.getId()); + if(StringUtils.isBlank(permission.getTitle())){ + String colunm = "title"; + errors.rejectValue(colunm,String.format("%s must not be blank.", colunm), "名称不可为空"); + } + if(!permission.getTitle().equals(originPermission.getTitle())){ + if (!checkTitle(permission.getTitle())) { + errors.rejectValue("title","title already existed", "名称已存在"); + } + } + + if(!permission.getName().equals(originPermission.getName())){ + if (!checkName(permission.getName())) { + errors.rejectValue("name","name already existed", "路由英文名已存在"); + } + } + + } else { + //新增 + if (!checkTitle(permission.getTitle())) { + errors.rejectValue("title","title already existed", "名称已存在"); + } + + if (!checkName(permission.getName())) { + errors.rejectValue("name","name already existed", "路由英文名已存在"); + } + + } + + } + + private boolean checkTitle(String title){ + List list = permissionService.list(new QueryWrapper().lambda() + .eq(ScPermission::getTitle, title) + .orderByAsc(ScPermission::getSortOrder)); + if (list != null && list.size() > 0) { + return false; + } + return true; + } + + private boolean checkName(String name){ + List list = permissionService.list(new QueryWrapper().lambda() + .eq(ScPermission::getName, name) + .orderByAsc(ScPermission::getSortOrder)); + if (list != null && list.size() > 0) { + return false; + } + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/PositionValidator.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/PositionValidator.java new file mode 100644 index 0000000..66f9d76 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/PositionValidator.java @@ -0,0 +1,65 @@ +package com.sunyard.ssp.modules.user.utils.validator; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.sunyard.ssp.modules.user.entity.ScPosition; +import com.sunyard.ssp.modules.user.service.IScPositionService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import java.util.List; + +/** + * 权限校验类 + * @author zs + * @description: + * @date: 2020/5/21 16:03 + */ +@Component +public class PositionValidator implements Validator { + + @Autowired + IScPositionService positionService; + + @Override + public boolean supports(Class aClass) { + + return ScPosition.class.equals(aClass); + } + + @Override + public void validate(Object o, Errors errors) { + ScPosition position = (ScPosition) o; + if (position.getId() != null) { + //编辑 + ScPosition originPosition = positionService.getById(position.getId()); + if(StringUtils.isBlank(position.getName())){ + String colunm = "name"; + errors.rejectValue(colunm,String.format("%s must not be blank.", colunm), "名称不可为空"); + } + if(!originPosition.getName().equals(position.getName())){ + if (!checkTitle(position.getName())) { + errors.rejectValue("name","name already existed", "名称已存在"); + } + } + + } else { + //新增 + if (!checkTitle(position.getName())) { + errors.rejectValue("name","name already existed", "名称已存在"); + } + } + + } + + private boolean checkTitle(String title){ + List list = positionService.list(new QueryWrapper().lambda() + .eq(ScPosition::getName, title)); + if (list != null && list.size() > 0) { + return false; + } + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/RoleValidator.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/RoleValidator.java new file mode 100644 index 0000000..47ffa08 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/RoleValidator.java @@ -0,0 +1,63 @@ +package com.sunyard.ssp.modules.user.utils.validator; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.service.IScRoleService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import java.util.List; + +/** + * 角色校验类 + * @auther: ZS + * @description: + * @date: 2020/6/1 11:37 + */ +@Component +public class RoleValidator implements Validator { + + @Autowired + IScRoleService roleService; + + @Override + public boolean supports(Class aClass) { + + return ScRole.class.equals(aClass); + } + + @Override + public void validate(Object o, Errors errors) { + ScRole role = (ScRole) o; + if (role.getId() != null) { + //编辑 + ScRole origin = roleService.getById(role.getId()); + if(StringUtils.isBlank(role.getName())){ + String colunm = "name"; + errors.rejectValue(colunm,String.format("%s must not be blank.", colunm), "名称不可为空"); + } + if(!role.getName().equals(origin.getName()) && !checkName(role.getName())) { + errors.rejectValue("name","name already existed", "名称已存在"); + } + + } else { + //新增 + if (!checkName(role.getName())) { + errors.rejectValue("name","name already existed", "名称已存在"); + } + } + + } + + private boolean checkName(String title){ + List list = roleService.list(new QueryWrapper().lambda() + .eq(ScRole::getName, title)); + if (list != null && list.size() > 0) { + return false; + } + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/UserValidator.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/UserValidator.java new file mode 100644 index 0000000..e9a39b6 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/modules/user/utils/validator/UserValidator.java @@ -0,0 +1,82 @@ +package com.sunyard.ssp.modules.user.utils.validator; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScUserService; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import java.util.List; + +/** + * 角色校验类 + * @auther: ZS + * @description: + * @date: 2020/6/1 11:37 + */ +@Component +public class UserValidator implements Validator { + + @Autowired + IScUserService userService; + + @Override + public boolean supports(Class aClass) { + + return ScUser.class.equals(aClass); + } + + @SneakyThrows + @Override + public void validate(Object o, Errors errors) { + ScUser user = (ScUser) o; + if (user.getId() != null) { + //编辑 + ScUser origin = userService.getById(user.getId()); + if (user.getTel() != null && !user.getTel().equals(origin.getTel()) && !checkTel(user.getTel())){ + errors.rejectValue("tel","tel already existed", "手机号已被使用"); + } + + if(user.getEmail() != null && !user.getEmail().equals(origin.getEmail()) && !checkEmail(user.getEmail())){ + errors.rejectValue("email","email already existed", "邮箱已被使用"); + } + + } else { + //新增 + if (!checkTel(user.getTel())) { + errors.rejectValue("tel","tel already existed", "手机号已被使用"); + } + + if (!checkEmail(user.getEmail())) { + errors.rejectValue("email","email already existed", "邮箱已被使用"); + } + } + + } + private boolean checkTel(String tel){ + if ("".equals(tel)){ + return true; + } + List list = userService.list(new QueryWrapper().lambda() + .eq(ScUser::getTel, tel)); + if (list != null && list.size() > 0) { + return false; + } + return true; + } + + private boolean checkEmail(String email){ + if ("".equals(email)){ + return true; + } + List list = userService.list(new QueryWrapper().lambda() + .eq(ScUser::getEmail, email)); + if (list != null && list.size() > 0) { + return false; + } + return true; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/JedisClusterConfig.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/JedisClusterConfig.java new file mode 100644 index 0000000..404c0e1 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/JedisClusterConfig.java @@ -0,0 +1,188 @@ +package com.sunyard.ssp.redis; + +import com.alibaba.fastjson.JSONObject; +import com.sunyard.ssp.server.Config; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisClusterConfiguration; +import org.springframework.data.redis.connection.RedisNode; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +import java.util.HashSet; +import java.util.Set; + +@Slf4j +@Configuration +public class JedisClusterConfig extends CachingConfigurerSupport { + + @Value("${spring.redis.password}") + private String password; + + @Value("${spring.redis.cluster.nodes}") + private String redisNodes; + + @Value("${spring.redis.isJq}") + private Boolean isJq; + + @Value("${spring.redis.host}") + private String host2; + + @Value("${spring.redis.port}") + private int port2; + + private int connectionTimeout = 6000; + + private int soTimeout = 2000; + + private int maxAttempts = 10; + + private int maxTotal = 800; + + private int minIdle = 50; + + private int maxIdle = 200; + + private int maxWaitMillis = 3000; + + /** + * JedisPoolConfig 连接池 + * @return + */ + @Bean + public JedisPoolConfig jedisPoolConfig() { + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + // 最大空闲数 + jedisPoolConfig.setMaxIdle(maxIdle); + // 连接池的最大数据库连接数 + jedisPoolConfig.setMaxTotal(maxTotal); + jedisPoolConfig.setTestOnBorrow(false); + // 逐出连接的最小空闲时间 默认1800000毫秒(30分钟) + return jedisPoolConfig; + } + + @Bean + public RedisClusterConfiguration redisClusterConfiguration(){ + RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(); + //Set clusterNodes + String[] serverArray = redisNodes.split(","); + + Set nodes = new HashSet(); + + for(String ipPort:serverArray){ + String[] ipAndPort = ipPort.split(":"); + nodes.add(new RedisNode(ipAndPort[0].trim(),Integer.valueOf(ipAndPort[1]))); + } + + redisClusterConfiguration.setClusterNodes(nodes); + + return redisClusterConfiguration; + } + + @Bean + public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig, RedisClusterConfiguration redisClusterConfiguration){ + + log.info("jedisConnectionFactory isJq = {}", isJq); + log.info("jedisConnectionFactory host2 = {}", host2); + log.info("jedisConnectionFactory port2 = {}", port2); + log.info("jedisConnectionFactory password = {}", password); + log.info("jedisConnectionFactory redisNodes = {}", redisNodes); + + + + + //是否开启集群模式 + if(isJq){ + JedisConnectionFactory JedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration,jedisPoolConfig); + JedisConnectionFactory.setPassword(password); + return JedisConnectionFactory; + }else{ + JedisConnectionFactory JedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig); + //连接池 + JedisConnectionFactory.setPoolConfig(jedisPoolConfig); + //IP地址 + JedisConnectionFactory.setHostName(host2); + //端口号 + JedisConnectionFactory.setPort(port2); + //如果Redis设置有密码 + JedisConnectionFactory.setPassword(password); + return JedisConnectionFactory; + } + } + + +// @Bean +// public JedisPool redisPoolFactory(){ +// JSONObject node = Config.global.messenger.redisCluster.getJSONObject("node"); +// String password = Config.global.messenger.redisCluster.getString("password"); +// String host = node.getString("ip"); +// Integer port = node.getInteger("port"); +// //调试的时候的配置 +// JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); +// //连接池中的最大空闲连接 +// jedisPoolConfig.setMaxTotal(10); +// jedisPoolConfig.setMinIdle(3); +// jedisPoolConfig.setMaxIdle(250); +// jedisPoolConfig.setMinIdle(100); +// jedisPoolConfig.setMaxWaitMillis(10 * 1000); +// // 是否启用pool的jmx管理功能, 默认true +// //jedisPoolConfig.setJmxEnabled(true); +// JedisPool jedisPool = new JedisPool(jedisPoolConfig,host,port,10000,password); +// return jedisPool; +// } + + + @Bean + public JedisPool redisPoolFactory(){ + JSONObject node = Config.global.messenger.redisCluster.getJSONObject("node"); + String password = Config.global.messenger.redisCluster.getString("password"); + String host = node.getString("ip"); + Integer port = node.getInteger("port"); + + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + jedisPoolConfig.setMaxTotal(10); + jedisPoolConfig.setMinIdle(3); + jedisPoolConfig.setMaxIdle(250); + jedisPoolConfig.setMinIdle(100); + jedisPoolConfig.setMaxWaitMillis(10 * 1000); + jedisPoolConfig.setTestWhileIdle(true); + jedisPoolConfig.setMinEvictableIdleTimeMillis(60000); + jedisPoolConfig.setTimeBetweenEvictionRunsMillis(30000); + jedisPoolConfig.setTestOnBorrow(true); + jedisPoolConfig.setTestOnReturn(true); + + JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, 10000, password); + return jedisPool; + } + + @Bean + public JedisCluster jedisCluster() { + Set hostAndPorts = new HashSet(); + String nodes[] = redisNodes.split(","); + for(String item : nodes){ + String host = item.split(":")[0]; + Integer port = Integer.valueOf(item.split(":")[1]); + hostAndPorts.add(new HostAndPort(host,port)); + } + + JedisCluster jedisCluster = null; + //if (!hostAndPorts.isEmpty() && isJq){ + if (!hostAndPorts.isEmpty() ){ + GenericObjectPoolConfig pool = new GenericObjectPoolConfig(); + pool.setMaxTotal(maxTotal); + pool.setMinIdle(minIdle); + pool.setMaxIdle(maxIdle); + pool.setMaxWaitMillis(maxWaitMillis); + jedisCluster = new JedisCluster(hostAndPorts, connectionTimeout, soTimeout, maxAttempts, password, pool); + } + return jedisCluster; + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisConfig.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisConfig.java new file mode 100644 index 0000000..a28d059 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisConfig.java @@ -0,0 +1,84 @@ +package com.sunyard.ssp.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @author:tsz + * @date:2020/3/6 + * @description:自定义序列化器 + * * 不定义的话默认采用的是 serializer.JdkSerializationRedisSerializer.serialize() 序列化为二进制字节码 存储在数据库中不直观 + */ +@Configuration +@Slf4j +@EnableCaching +public class RedisConfig { + + @Bean + MessageListenerAdapter messageListener() { + //abstract methods overwrite + return new MessageListenerAdapter((MessageListener) (message, pattern) -> { + System.out.println("Message received: " + message.toString()); + }); + } + + @Bean + RedisMessageListenerContainer redisContainer(RedisConnectionFactory connectionFactory) { + RedisMessageListenerContainer container + = new RedisMessageListenerContainer(); + container.setConnectionFactory(connectionFactory); + container.addMessageListener(messageListener(), topic()); + return container; + } + + @Bean + ChannelTopic topic() { + return new ChannelTopic("topic"); + } + + /* @Bean + public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { + StringRedisTemplate template = new StringRedisTemplate(); + template.setConnectionFactory(redisConnectionFactory); + return template; + }*/ + + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + + // 使用 Jackson2JsonRedisSerialize 需要导入依赖 com.fasterxml.jackson.core jackson-databindz + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + + ObjectMapper objectMapper = new ObjectMapper(); + // 第一个参数表示: 表示所有访问者都受到影响 包括 字段, getter / isGetter,setter,creator + // 第二个参数表示: 所有类型的访问修饰符都是可接受的,不论是公有还有私有表变量都会被序列化 + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + + jackson2JsonRedisSerializer.setObjectMapper(objectMapper); + + // 设置 key,value 序列化规则 + redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); + redisTemplate.setKeySerializer(new StringRedisSerializer()); +// 开启事务支持 + redisTemplate.setEnableTransactionSupport(false); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisObjectOperation.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisObjectOperation.java new file mode 100644 index 0000000..594aa2a --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisObjectOperation.java @@ -0,0 +1,468 @@ +package com.sunyard.ssp.redis; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.ListOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.SetOperations; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; +import redis.clients.jedis.BinaryJedisPubSub; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * @author:tsz + * @date:2020/3/6 + * @description: 操作任意类型的 Template + */ +@Component +@Slf4j +public class RedisObjectOperation { + + @Autowired + private RedisTemplate objectRedisTemplate; + @Value("${spring.redis.isJq}") + private Boolean isJq; + @Value("${spring.redis.password}") + private String password; + @Value("${spring.redis.cluster.nodes}") + private String redisNodes; + @Autowired + private JedisCluster jedisCluster; + @Autowired + private JedisPool jedisPool; + + /*** + * 操作对象 + */ + public void ObjectSet(Object key, Object value) { + ValueOperations valueOperations = objectRedisTemplate.opsForValue(); + valueOperations.set(key, value); + } + + /*** + * 操作元素为对象列表 + */ + public void ListSet(Object key, List values) { + ListOperations listOperations = objectRedisTemplate.opsForList(); + values.forEach(value -> listOperations.leftPush(key, value)); + } + + /** + * 对象存储到redis 的list 中 + * + * @param key + * @param value + */ + public void ListSet(Object key, Object value) { + ListOperations listOperations = objectRedisTemplate.opsForList(); + listOperations.leftPush(key, value); + } + + /** + * 移除list 中的数据 + * + * @param key + * @param start + * @param end + */ + public void ListTrim(Object key, Long start, Long end) { + ListOperations listOperations = objectRedisTemplate.opsForList(); + listOperations.trim(key, start, end); + } + + /** + * 获得list 对象 + * + * @param key + * @param start + * @param end + * @return + */ + public List ListGet(Object key, Long start, Long end) { + ListOperations listOperations = objectRedisTemplate.opsForList(); + return listOperations.range(key, start, end); + } + + + /*** + * 操作元素为对象集合 + */ + public void SetSet(Object key, Set values) { + SetOperations setOperations = objectRedisTemplate.opsForSet(); + values.forEach(value -> setOperations.add(key, value)); + } + + /*** + * 获取对象 + */ + public Object ObjectGet(Object key) { + ValueOperations valueOperations = objectRedisTemplate.opsForValue(); + return valueOperations.get(key); + } + + /*** + * 列表弹出元素 + */ + public Object ListLeftPop(Object key) { + ListOperations listOperations = objectRedisTemplate.opsForList(); + return listOperations.leftPop(key, 2, TimeUnit.SECONDS); + } + + /*** + * 集合弹出元素 + */ + public Object SetPop(Object key) { + SetOperations setOperations = objectRedisTemplate.opsForSet(); + return setOperations.pop(key); + } + + + public void close() { + if (!isJq) { + if (null != jedisPool) { + try { + jedisPool.close(); + } catch (Exception e) { + } + } + } else { + if (null != jedisCluster) { + try { + jedisCluster.close(); + } catch (Exception e) { + } + } + jedisCluster = null; + } + } + + public Set keys(String pattern) { + + Set keys = new HashSet<>(); + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + + keys = jedis.keys(pattern); + } finally { + if (jedis != null) { + jedis.close(); + } + //close(); + } + } else { + try { + //获取所有连接池节点 + //Map nodes = jedisCluster.getClusterNodes(); + String nodes[] = redisNodes.split(","); + for(String node : nodes){ + String host = node.split(":")[0]; + Integer port = Integer.valueOf(node.split(":")[1]); + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + jedisPoolConfig.setMaxIdle(1000); + jedisPoolConfig.setBlockWhenExhausted(false); + jedisPoolConfig.setJmxEnabled(true); + log.debug("从【{}】获取keys", node); + JedisPool pool = new JedisPool(jedisPoolConfig,host,port,10000,password); + Jedis jedis = null; + try { + jedis = pool.getResource(); + keys.addAll(jedis.keys(pattern)); + } catch (Exception e) { + log.error("获取key异常", e); + } finally { + log.info("关闭连接"); + //一定要关闭连接! + if (jedis != null) { + jedis.close(); + } + } + } + //遍历所有连接池,逐个进行模糊查询 + /*for (String k : nodes.keySet()) { + log.debug("从【{}】获取keys", k); + JedisPool pool = nodes.get(k); + //获取Jedis对象,Jedis对象支持keys模糊查询 + Jedis jedis = null; + try { + jedis = pool.getResource(); + keys.addAll(jedis.keys(pattern)); + } catch (Exception e) { + log.error("获取key异常", e); + } finally { + log.info("关闭连接"); + //一定要关闭连接! + if (jedis != null) + jedis.close(); + } + }*/ + } catch (Exception e) { + log.error("获取key异常", e); + } + } + return keys; + + } + + public String get(String pattern) { + + String keys; + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + + keys = jedis.get(pattern); + } finally { + if (jedis != null) { + jedis.close(); + } + //close(); + } + } else { + keys = jedisCluster.get(pattern); + } + return keys; + + } + + public void set(String key, String value) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + jedis.set(key, value); + } finally { + if (jedis != null) { + jedis.close(); + } + //close(); + } + } else { + jedisCluster.set(key, value); + } + + + } + + public void delete(Set keys) { + + + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + for (String key : keys) { + jedis.del(key); + } + + } finally { + if (jedis != null) { + jedis.close(); + } + //close(); + } + } else { + for (String key : keys) { + jedisCluster.del(key); + } + } + + } + + + public void subscribe(BinaryJedisPubSub jedisPubSub, final byte[]... channels) { + + + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + + jedis.subscribe(jedisPubSub, channels); + } finally { + if (jedis != null) { + jedis.close(); + } + //close(); + } + } else { + jedisCluster.subscribe(jedisPubSub, channels); + } + + } + + public Long zrem(final String key, final String... members) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zrem(key, members); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zrem(key, members); + } + } + + public Long zremrangeByScore(final byte[] key, final double min, final double max) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zremrangeByScore(key, min, max); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zremrangeByScore(key, min, max); + } + } + + public Long zremrangeByScore(final String key, final double min, final double max) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zremrangeByScore(key, min, max); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zremrangeByScore(key, min, max); + } + } + + public Set zrangeByScore(String key, double min, double max) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zrangeByScore(key, min, max); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zrangeByScore(key, min, max); + } + } + + public Long zadd(final String key, final double score, final String member) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + jedis.auth(password); + return jedis.zadd(key, score, member); + } else { + return jedisCluster.zadd(key, score, member); + } + } + + public Long zadd(final byte[] key, final double score, final byte[] member) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + jedis.auth(password); + return jedis.zadd(key, score, member); + } else { + return jedisCluster.zadd(key, score, member); + } + } + + public Set zrange(final String key, final long start, final long stop) { + + + Set zrange; + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + zrange = jedis.zrange(key, start, stop); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + zrange = jedisCluster.zrange(key, start, stop); + + } + return zrange; + + } + + public Long sadd(final String key, final String... members) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + jedis.auth(password); + return jedis.sadd(key, members); + } else { + return jedisCluster.sadd(key, members); + } + } + + public Long del(final String key) { + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.del(key); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.del(key); + } + } + + + public Long publish(final byte[] channel, final byte[] message) { + Long publish = null; + if (!isJq) { + Jedis jedis = jedisPool.getResource(); + log.info("jedis publish[{}]", jedis); + try { + jedis.auth(password); + publish = jedis.publish(channel, message); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + publish = jedisCluster.publish(channel, message); + } + return publish; + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisOperation.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisOperation.java new file mode 100644 index 0000000..4f95210 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/redis/RedisOperation.java @@ -0,0 +1,72 @@ +package com.sunyard.ssp.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.ListOperations; +import org.springframework.data.redis.core.SetOperations; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * @author:tsz + * @date:2020/3/6 + * @description: redis String 基本操作 + */ +@Component +public class RedisOperation { + + @Autowired + private StringRedisTemplate redisTemplate; + + /*** + * 操作普通字符串 + */ + public void StringSet(String key, String value) { + ValueOperations valueOperations = redisTemplate.opsForValue(); + valueOperations.set(key, value); + } + + /*** + * 操作列表 + */ + public void ListSet(String key, List values) { + ListOperations listOperations = redisTemplate.opsForList(); + values.forEach(value -> listOperations.leftPush(key, value)); + } + + /*** + * 操作集合 + */ + public void SetSet(String key, Set values) { + SetOperations setOperations = redisTemplate.opsForSet(); + values.forEach(value -> setOperations.add(key, value)); + } + + /*** + * 获取字符串 + */ + public String StringGet(String key) { + ValueOperations valueOperations = redisTemplate.opsForValue(); + return valueOperations.get(key); + } + + /*** + * 列表弹出元素 + */ + public String ListLeftPop(String key) { + ListOperations listOperations = redisTemplate.opsForList(); + return listOperations.leftPop(key, 2, TimeUnit.SECONDS); + } + + /*** + * 集合弹出元素 + */ + public String SetPop(String key) { + SetOperations setOperations = redisTemplate.opsForSet(); + return setOperations.pop(key); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Config.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Config.java new file mode 100644 index 0000000..6995f12 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Config.java @@ -0,0 +1,167 @@ +package com.sunyard.ssp.server; + + +import com.alibaba.fastjson.JSONObject; +import com.sunyard.ssp.proto.control.Control; +import lombok.Cleanup; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.UUID; + +/** + * 这个类暂时先这么记着 + * [TODO] 读写分离 + * [TODO] 对接配置中心,热重载。 + */ +@Slf4j +public class Config { + + public static Config global = new Config(); + + public System system = new System(); + public static class System { + public String name; + + public System() { + this.name = findName(); + } + + private boolean getBooleFromEnv(String name){ + log.debug("尝试从环境变量载入 {}", name); + Map map = java.lang.System.getenv(); + if ( map.containsKey(name) ){ + String sn = (String) map.get(name); + if ( "true".equals( sn.trim().toLowerCase() ) ){ + return true; + } + } + + return false; + } + + private String readNameFromFile(){ + // 检查路径 + File folder = new File("/data"); + if ( !folder.exists() ){ + folder.mkdirs(); + } + + File snFile = new File(folder, "security.name"); + if ( snFile.exists() ){ + try(FileReader fr = new FileReader(snFile) ; BufferedReader bfr = new BufferedReader(fr) ) { + + String sn = bfr.readLine(); + sn = sn.trim().toLowerCase(); + if ( sn.length() >= 6 ){ + saveNameToFile(sn); + return sn; + } else { + log.debug("security.name 的值不合规"); + return null; + } + + } catch (IOException e) { + e.printStackTrace(); + log.error("写入 security.name 配置文件的时候失败了,{}", snFile.getAbsolutePath() ); + return null; + } + } else { + log.error("security.name 配置文件不存在,{}", snFile.getAbsolutePath() ); + return null; + } + } + + private String genSn(){ + return UUID.randomUUID().toString().replaceAll("-",""); + } + + private void saveNameToFile( String sn ){ + // 检查路径 + File folder = new File("/data"); + if ( !folder.exists() ){ + folder.mkdirs(); + } + + File snFile = new File(folder, "security.name"); + if ( snFile.exists() ){ + snFile.delete(); + } + + try( FileOutputStream fio = new FileOutputStream(snFile); ) { + + snFile.createNewFile(); + + fio.write( sn.getBytes(Charset.forName("UTF-8")) ); + fio.flush(); + + } catch (IOException e) { + e.printStackTrace(); + log.error("写入 security.name 配置文件的时候失败了,{}", snFile.getAbsolutePath() ); + } + + log.debug("写入 security.name 配置文件完成,SERVER_NAME = {},{}", sn, snFile.getAbsolutePath()); + } + + private String findName(){ + log.debug("尝试从环境变量载入 SERVER_NAME"); + Map map = java.lang.System.getenv(); + if ( map.containsKey("SERVER_NAME") ){ + String sn = (String) map.get("SERVER_NAME"); + sn = sn.trim().toUpperCase(); + if ( sn.length() >= 6 ){ + //saveNameToFile(sn); + return sn; + } else { + log.debug("环境变量 SERVER_NAME 的值不合规"); + } + } + + log.debug("尝试从 security.name 配置载入 SERVER_NAME"); + String sn = readNameFromFile(); + if ( null != sn){ + return sn; + } + + sn = genSn(); +// saveNameToFile( sn ); + return sn; + } + } + + public Messenger messenger = new Messenger(); + public static class Messenger { + //cluster solo + public JSONObject redisCluster = (JSONObject) loadFileConfig("redis.config.json"); + public int maxWaitTime = 10; // 秒 + + public String privateCliChannel(){ + return Control.Req.Origin.CLI.name() + "_" + Config.global.system.name; + } + public String privateServerChannel(){ + return Control.Req.Origin.SERVER.name() + "_" + Config.global.system.name; + } + + } + + @SneakyThrows + public static JSONObject loadFileConfig(String name ){ + File folder = new File("./config"); + File configFile = new File(folder, name); + if ( ! configFile.exists() ){ + log.error("没有找到配置文件 {}", name); + } + @Cleanup FileInputStream fio = new FileInputStream(configFile); + byte[] buff = new byte[ fio.available() ]; + fio.read( buff ); + return (JSONObject) JSONObject.parse( new String(buff) ); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Messenger.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Messenger.java new file mode 100644 index 0000000..bd917f2 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Messenger.java @@ -0,0 +1,433 @@ +package com.sunyard.ssp.server; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.Any; +import com.google.protobuf.InvalidProtocolBufferException; +import com.sunyard.ssp.common.exception.SspwebException; +import com.sunyard.ssp.proto.control.Control; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import lombok.var; +import redis.clients.jedis.BinaryJedisPubSub; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + + +/** + * 封装到 Server 的通信 + * 异步转同步 + */ + +@Slf4j +public class Messenger { + + private static String channel = "MANAGER_CLUSTER"; + private static JedisCluster jedisCluster; + private static Redis redisSubscribe; + private static Redis redisSubscribe2; + private static Redis redis;//Publish + private static Thread thread; + private static ExecutorService executorService = Executors.newFixedThreadPool(3 ); + private static ConcurrentHashMap pendingMessageRecord = new ConcurrentHashMap<>(); + + private static JedisPool jedisPool = null; + private static JedisPool jedisPool2 = null; + private static JedisPool jedisPool3 = null; + + private static String host ; + private static Integer port ; + private static String password; + private static String mode; + static { + + // 只有 CLI 需要重置 channel + //channel = Control.Req.Origin.CLI + "_" + Config.global.system.name; + + // 初始化 + // 链接到 redis + Set nodes = new HashSet<>(); + JSONArray ns = Config.global.messenger.redisCluster.getJSONArray("nodes"); + password = Config.global.messenger.redisCluster.getString("password"); + mode = Config.global.messenger.redisCluster.getString("mode"); + JSONObject node = Config.global.messenger.redisCluster.getJSONObject("node"); + host = node.getString("ip"); + port = node.getInteger("port"); + for (Object n : ns) { + JSONObject no = (JSONObject) n; + nodes.add(new HostAndPort(no.getString("ip"), no.getInteger("port"))); + } + + @AllArgsConstructor + class Msg extends BinaryJedisPubSub { + + @Override + public void onMessage(byte[] channel, byte[] message) { + + + // 将 message 解析为 Res 对象 + try { + val res = Control.Res.parseFrom( message ); + val id = res.getId(); + + val record = pendingMessageRecord.get(id); + if ( null == record ){ + log.debug("没有找到消息 {} 的记录, 遗弃。", id); + } else { + + record.lock.lock(); + try { + if ( record instanceof SoloRecord ){ + log.debug("找到 Solo 消息 {} 的记录, 触发信号。", id); + ((SoloRecord) record).res = res; + ((SoloRecord) record).getCondition().signal(); + } else if ( record instanceof ClusterRecord ){ + log.debug("找到 Cluster 消息 {} 的记录, 触发阶段信号。", id); + ((ClusterRecord) record).reslist.add( res ); + ((ClusterRecord) record).getStage().signal(); + } + }finally { + record.lock.unlock(); + } + + } + + } catch (InvalidProtocolBufferException e) { + e.printStackTrace(); + } + + } + } + + JedisPoolConfig config = new JedisPoolConfig(); + // config.setTestOnBorrow(false); + jedisCluster = new JedisCluster(nodes, 1000, 2000, 5, password, config); + if (jedisPool ==null){ + //调试的时候的配置 + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + //连接池中的最大空闲连接 + jedisPoolConfig.setMaxIdle(1000); + //连接池最大阻塞等待时间 + //jedisPoolConfig.setMaxWaitMillis(10000); + //在获取连接的时候检查有效性 + //jedisPoolConfig.setTestOnBorrow(true); + // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true + jedisPoolConfig.setBlockWhenExhausted(false); + // 是否启用pool的jmx管理功能, 默认true + jedisPoolConfig.setJmxEnabled(true); + jedisPool = new JedisPool(jedisPoolConfig,host,port,10000,password); + } + if (jedisPool2 ==null){ + //调试的时候的配置 + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + //连接池中的最大空闲连接 + jedisPoolConfig.setMaxIdle(1000); + //连接池最大阻塞等待时间 + //jedisPoolConfig.setMaxWaitMillis(10000); + //在获取连接的时候检查有效性 + //jedisPoolConfig.setTestOnBorrow(true); + // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true + jedisPoolConfig.setBlockWhenExhausted(false); + // 是否启用pool的jmx管理功能, 默认true + jedisPoolConfig.setJmxEnabled(true); + jedisPool2 = new JedisPool(jedisPoolConfig,host,port,10000,password); + } + if (jedisPool3 ==null){ + + } + redis = new Redis(jedisCluster, jedisPool2, password, mode); + redisSubscribe = new Redis(jedisCluster, jedisPool, password, mode); + + thread = new Thread(new Runnable() { + @Override + public void run() { + log.info("监听反馈消息 {}", channel); + redisSubscribe.subscribe(new Msg(), channel.getBytes() ); + + } + }); + thread.setName("messenger"); + thread.start(); + } + + + public static Thread subscribe(final BinaryJedisPubSub jedisPubSub, String channel){ + return new Thread(new Runnable() { + @Override + public void run() { + //调试的时候的配置 + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + //连接池中的最大空闲连接 + jedisPoolConfig.setMaxIdle(1000); + //连接池最大阻塞等待时间 + //jedisPoolConfig.setMaxWaitMillis(10000); + //在获取连接的时候检查有效性 + //jedisPoolConfig.setTestOnBorrow(true); + // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true + jedisPoolConfig.setBlockWhenExhausted(false); + // 是否启用pool的jmx管理功能, 默认true + jedisPoolConfig.setJmxEnabled(true); + jedisPool3 = new JedisPool(jedisPoolConfig,host,port,10000,password); + + redisSubscribe2 = new Redis(jedisCluster, jedisPool3, password, mode); + + log.info("监听Check消息 {}", channel); + redisSubscribe2.subscribe(jedisPubSub, channel.getBytes() ); + } + }); + } + + public static String genId(){ + return UUID.randomUUID().toString().replace("-", ""); + } + + + public static Control.Res primarySyncCmd( String cmd, com.google.protobuf.GeneratedMessageV3 data) throws ExecutionException, InterruptedException { + var c = System.currentTimeMillis(); + var last = c - 120000L; + redis.zremrangeByScore("SERVER_CLUSTER", 0, last); + val servers = redis.zrevrange("SERVER_CLUSTER", 0, 9); + if (servers.size()<1){ + throw new SspwebException("安全服务异常"); + } + + + Iterator it = servers.iterator(); + String channel = servers.iterator().next(); + + // 方便调试的逻辑 + // 如果配置了调试服务器,优先使用调试服务器 + val debugServer = redis.get("DEBUG_SERVER"); + if ( null != debugServer && servers.contains( debugServer ) ) { + channel = debugServer; + } + + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd(cmd) + .setData(Any.pack(data)) + .build(); + return soloSyncCmd("SERVER_" + channel, req); + } + + + public static Control.Res soloSyncCmd(String channel, String cmd, com.google.protobuf.GeneratedMessageV3 data) throws ExecutionException, InterruptedException { + + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd(cmd) + .setData(Any.pack(data)) + .build(); + return soloSyncCmd(channel, req); + } + /** + * 同步通信 + * + * @param req + * @return + */ + public static Control.Res soloSyncCmd(String channel, Control.Req req) throws ExecutionException, InterruptedException { + + var c = System.currentTimeMillis(); + var last = c - 120000L; + redis.zremrangeByScore("SERVER_CLUSTER", 0, last); + val servers = redis.zrevrange("SERVER_CLUSTER", 0, 9); + if (servers.size()<1){ + throw new SspwebException("安全服务异常"); + } + log.info("SoloSyncCmd 发送消息到 sspserver id={} cmd={}", channel, req.getCmd()); + + // 发送请求 + redis.publish(channel.getBytes(), req.toByteArray() ); + + // 单点通信创建一个信号量 + final SoloRecord record = new SoloRecord(); + + // 记录请求 + pendingMessageRecord.put( req.getId(), record ); + Future future = executorService.submit(new Callable() { + + @Override + public Control.Res call() throws Exception { + //Thread.sleep(3000); + try { + record.getLock().lock(); + // 等待信号量 + record.getCondition().await( Config.global.messenger.maxWaitTime , TimeUnit.SECONDS ); + + }catch ( InterruptedException e ){ + log.error("Solo 请求 {} {} 被打断,from={}, to={}", req.getId() , req.getCmd() , req.getFrom(), channel); + } finally { + record.getLock().unlock(); + } + + // 返回结果 + return record.res; + } + }); + // 阻塞,等待子线程结束 + return (Control.Res) future.get(); + + } + + + public static ConcurrentLinkedQueue clusterSyncCmd( String cmd, com.google.protobuf.GeneratedMessageV3 data) throws ExecutionException, InterruptedException { + if (ObjectUtil.isNull(data) || StrUtil.isEmpty(data.toString())){ + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd(cmd) + .build(); + return clusterSyncCmd("SERVER_CLUSTER", req, null); + } else { + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd(cmd) + .setData(Any.pack(data)) + .build(); + return clusterSyncCmd("SERVER_CLUSTER", req, null); + } + + } + public static ConcurrentLinkedQueue clusterSyncCmd(String channel, Control.Req req) throws ExecutionException, InterruptedException { + return clusterSyncCmd(channel, req, null); + } + + /** + * 集群同步通信 + * 一个发送多个返回,收到是个数组。 + * + * @param req + * @return + */ + public static ConcurrentLinkedQueue clusterSyncCmd(String channel, Control.Req req, ClusterRecordMoniter moniter) throws ExecutionException, InterruptedException { + + // 发送请求 + redis.publish(channel.getBytes(), req.toByteArray() ); + + // 单点通信创建一个信号量 + final ClusterRecord record = new ClusterRecord(); + + // 记录请求 + pendingMessageRecord.put( req.getId(), record ); + + // 监听阶段数据 + executorService.submit(new Runnable() { + + @SneakyThrows + @Override + public void run() { + + try { + record.getLock().lock(); + + log.debug("等待阶段信号"); + record.getStage().await(Config.global.messenger.maxWaitTime , TimeUnit.SECONDS); + log.debug("收到阶段信号"); + + // 查询应该响应的数量 + val servers = redis.zrange("SERVER_CLUSTER", 0, 9); + log.debug("应该收到的消息数 {}, 目前收到的消息数 {}", servers.size(), record.getReslist().size() ); + + // 全部收到 + if ( servers.size() == record.getReslist().size() ){ + record.getCondition().signal(); + } + + + if ( null != moniter ){ + moniter.onStage( servers.size(), record.getReslist(), record.getCondition() ); + } + + } finally { + record.getLock().unlock(); + + } + } + }); + + // 监听整体 + Future future = executorService.submit(new Callable>() { + @Override + public ConcurrentLinkedQueue call() throws Exception { + + try { + record.getLock().lock(); + record.getCondition().await(Config.global.messenger.maxWaitTime , TimeUnit.SECONDS); + return record.getReslist(); + } finally { + record.getLock().unlock(); + } + } + }); + + // 阻塞,等待子线程结束 + return (ConcurrentLinkedQueue) future.get(); + } + + @Getter + private abstract static class Record { + private final ReentrantLock lock = new ReentrantLock(); + } + + @Getter + private static class SoloRecord extends Record { + private Condition condition = getLock().newCondition(); + // 返回一个结果 + private Control.Res res; + } + + @Getter + private static class ClusterRecord extends Record { + private Condition stage = getLock().newCondition(); + private Condition condition = getLock().newCondition(); + + // 返回一组结果 + private final ConcurrentLinkedQueue reslist = new ConcurrentLinkedQueue<>(); + } + + /** + * 允许监听集群命令的中间阶段 + */ + public abstract static class ClusterRecordMoniter { + + /** + * + * @param curAliveServerNum - 当前集群中存活的服务数量,及期望响应的数量 + * @param reslist - 当前已经收集的返回结果 + * @param condition - 终结信号量 condition.signal(); 可以提前终结等待。 + */ + public abstract void onStage( int curAliveServerNum, ConcurrentLinkedQueue reslist , Condition condition ); + + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Redis.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Redis.java new file mode 100644 index 0000000..ee8355f --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/Redis.java @@ -0,0 +1,288 @@ +package com.sunyard.ssp.server; + +import lombok.extern.slf4j.Slf4j; +import redis.clients.jedis.BinaryJedisPubSub; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.JedisPool; + +import java.util.Set; + +// 包装集群和单点 +@Slf4j +public class Redis { + private JedisCluster jedisCluster; + + private JedisPool jedisPool; + + private String mode; + + private String password; + + public void close() { + if ("solo".equals(mode)) { + if (null != jedisPool) { + try { + jedisPool.close(); + } catch (Exception e) { + } + } + } else { + if (null != jedisCluster) { + try { + jedisCluster.close(); + } catch (Exception e) { + } + } + jedisCluster = null; + } + } + + public Redis(JedisCluster jedisCluster, JedisPool jedisPool, String password, String mode) { + this.jedisCluster = jedisCluster; + this.jedisPool = jedisPool; + this.mode = mode; + this.password = password; + } + + public String get(String key) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + log.info("jedis publish[{}]",jedis); + try { + + return jedis.get(key); + } finally { + if(jedis!=null){ + jedis.close(); + } + //close(); + } + } else { + return jedisCluster.get( key ); + } + } + + public void subscribe(BinaryJedisPubSub jedisPubSub, final byte[]... channels) { + + + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + log.info("jedis publish[{}]",jedis); + try { + jedis.auth(password); + + jedis.subscribe(jedisPubSub, channels); + } finally { + if(jedis!=null){ + jedis.close(); + } + //close(); + } + } else { + jedisCluster.subscribe(jedisPubSub, channels); + } + + } + + public Long zrem(final String key, final String... members) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zrem(key, members); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zrem(key, members); + } + } + + public Long zremrangeByScore(final byte[] key, final double min, final double max) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zremrangeByScore(key, min, max); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zremrangeByScore(key, min, max); + } + } + + public Long zremrangeByScore(final String key, final double min, final double max) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zremrangeByScore(key, min, max); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zremrangeByScore(key, min, max); + } + } + + public Set zrevrangeByScore(String key, double min, double max) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zrevrangeByScore(key, min, max); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zrevrangeByScore(key, min, max); + } + } + + public Set zrangeByScore(String key, double min, double max) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.zrangeByScore(key, min, max); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.zrangeByScore(key, min, max); + } + } + + public Long zadd(final String key, final double score, final String member) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + jedis.auth(password); + return jedis.zadd(key, score, member); + } else { + return jedisCluster.zadd(key, score, member); + } + } + + public Long zadd(final byte[] key, final double score, final byte[] member) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + jedis.auth(password); + return jedis.zadd(key, score, member); + } else { + return jedisCluster.zadd(key, score, member); + } + } + + public Set zrevrange(final String key, final long start, final long stop) { + + + Set zrange; + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + zrange = jedis.zrevrange(key, start, stop); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + zrange = jedisCluster.zrevrange(key, start, stop); + + } + return zrange; + + } + public Set zrange(final String key, final long start, final long stop) { + + + Set zrange; + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + zrange = jedis.zrange(key, start, stop); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + zrange = jedisCluster.zrange(key, start, stop); + + } + return zrange; + + } + + public Long sadd(final String key, final String... members) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + jedis.auth(password); + return jedis.sadd(key, members); + } else { + return jedisCluster.sadd(key, members); + } + } + + public Long del(final String key) { + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + try { + jedis.auth(password); + return jedis.del(key); + } finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + return jedisCluster.del(key); + } + } + + + public Long publish(final byte[] channel, final byte[] message) { + Long publish = null; + if ("solo".equals(mode)) { + Jedis jedis = jedisPool.getResource(); + log.info("jedis publish[{}]",jedis); + try { + jedis.auth(password); + publish = jedis.publish(channel, message); + + }catch (Exception e){ + e.printStackTrace(); + }finally { + if (jedis != null) { + jedis.close(); + //close(); + } + } + } else { + publish = jedisCluster.publish(channel, message); + } + return publish; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/server/ServerTest.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/ServerTest.java new file mode 100644 index 0000000..5ab40e3 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/ServerTest.java @@ -0,0 +1,223 @@ +package com.sunyard.ssp.server; + +import com.google.protobuf.Any; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.UInt64Value; +import com.sunyard.ssp.proto.control.Control; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.val; +import redis.clients.jedis.BinaryJedisPubSub; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * @author:tsz + * @date:2020/3/19 + * @description: + */ +public class ServerTest { + + /** + *@author :tsz + *@date :2020/03/19 15:56 + *@description : 测试是否联通渠道 + */ + public static void connect() { + try { + + // 准备消息 + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd("test.ping") + .build(); + //Manager 监听通道 MANAGER_CLUSTER + // SERVER_CLUSTER + val res = Messenger.soloSyncCmd("SERVER_CLUSTER", req); + if (null == res) { + System.err.println("接收命令响应超时!"); + } else { +// Control.CMD_ping p = res.getData().unpack(Control.CMD_ping.class); + + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /** + *@author :tsz + *@date :2020/3/19 16:06 + *@param : 传递渠道id? + *@return : + *@description : 渠道更新 + */ + public static void channelUpdate(String channelId) { + try { + + // 准备消息 + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd("channel.update.enable") + .setData(Any.pack(UInt64Value.of(Long.valueOf(channelId)))) + .build(); + //Manager 监听通道 MANAGER_CLUSTER + // SERVER_CLUSTER + val res = Messenger.soloSyncCmd("SERVER_CLUSTER", req); + if (null == res) { + System.err.println("接收命令响应超时!"); + } else { + + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + *@author :tsz + *@date :2020/3/19 16:44 + *@param : + *@return : + *@description : 列出所有渠道 + */ + public static void channelList() { + try { + + // 准备消息 + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd("channel.list") + .build(); + //Manager 监听通道 MANAGER_CLUSTER + // SERVER_CLUSTER + val res = Messenger.soloSyncCmd("SERVER_CLUSTER", req); + if (null == res) { + System.err.println("接收命令响应超时!"); + } else { + val list = res.getData().unpack( Control.VOChannelList.class ); + System.out.println(list); + + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /** + *@author :tsz + *@date :2020/3/19 16:49 + *@param : + *@return : + *@description : 列出所有服务器 + */ + public static void serverList(){ + try { + + // 准备消息 + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd("server.list") + .build(); + //Manager 监听通道 MANAGER_CLUSTER + // SERVER_CLUSTER + val res = Messenger.soloSyncCmd("SERVER_CLUSTER", req); + if (null == res) { + System.err.println("接收命令响应超时!"); + } else { + val list = res.getData().unpack( Control.VOChannelList.class ); + System.out.println(list); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + *@author :tsz + *@date :2020/03/24 15:38 + *@description : 渠道验证 + */ + public static void VOChannelCheck(Long channelId,String checkId) { + + + val buff = new HashMap>(); + + + + @NoArgsConstructor + @Setter + class Msg extends BinaryJedisPubSub { + + private Thread t; + + + @Override + public void onMessage(byte[] channel, byte[] message) { + + + // 将 message 解析为 Res 对象 + try { + val res = Control.VOChannelCheckRes.parseFrom( message ); + if ( !buff.containsKey(checkId)){ + buff.put(checkId,new ArrayList<>()); + } + + val list = buff.get(checkId); + + + + list.add(res); + if ( res.getType().equals("end") ){ + t.stop(); + } + + + } catch (InvalidProtocolBufferException e) { + e.printStackTrace(); + } + + } + } + + // + val msg = new Msg(); + Thread t = Messenger.subscribe(msg, checkId ); + msg.setT( t ); + t.start(); + + + try { + // 准备消息 + val req = Control.Req.newBuilder() + .setId(Messenger.genId()) + .setOrigin(Control.Req.Origin.MANAGER) + .setFrom("CLUSTER") + .setCmd("channel.check") + .setData(Any.pack(Control.VOChannelCheck.newBuilder().setChannelId(channelId).setCheckId(checkId).build())) + .build(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + + public static void main(String[] args) { + VOChannelCheck(11L,"111"); + } + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/server/VOChannel.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/VOChannel.java new file mode 100644 index 0000000..ad3d55d --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/server/VOChannel.java @@ -0,0 +1,18 @@ +package com.sunyard.ssp.server; +import lombok.Data; + +/** + * @author:tsz + * @date:2020/3/25 + * @description: + */ +@Data +public class VOChannel { + + private String type; + + private String msg; + + //private List list; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CaUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CaUtil.java new file mode 100644 index 0000000..e853843 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CaUtil.java @@ -0,0 +1,370 @@ +package com.sunyard.ssp.utils; + +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.asn1.x509.KeyPurposeId; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.crypto.engines.SM2Engine; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.crypto.params.ParametersWithRandom; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; +import org.bouncycastle.jce.X509KeyUsage; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.util.encoders.Base64; + +import javax.security.auth.x500.X500Principal; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.Security; +import java.security.Signature; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Date; +import java.util.Random; +import java.util.Set; + +/** + * @author:tsz + * @date:2020/4/27 + * @description: + */ +public class CaUtil { + + static { + Security.addProvider(new BouncyCastleProvider()); + BouncyCastleProvider bc = new BouncyCastleProvider(); + Set services = bc.getServices(); + for (Provider.Service s:services){ + if (s.toString().toUpperCase().contains("CIPHER")) System.out.println(s.toString()); + } + } + + public static void main(String[] args) throws Exception { + genGMCACert(); + //genCertWithCaSign(); + // testDigitalSign(); + //testSM2EcDc(); + //testSaveGMKeyStore(); + + } + + public static void genGMCACert() throws Exception { + System.out.println("=============测试生成国密CA根证书============="); + KeyPairGenerator g = KeyPairGenerator.getInstance("EC", "BC"); + + g.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1")); + + KeyPair p = g.generateKeyPair(); + + PrivateKey privKey = p.getPrivate(); + PublicKey pubKey = p.getPublic(); + + System.out.println("CA PrivateKey:" + Base64.toBase64String(privKey.getEncoded())); + + X500Principal iss = new X500Principal("CN=test GM ROOT CA,OU=test,C=CN,S=Guangdong,O=test"); + + ContentSigner sigGen = new JcaContentSignerBuilder("SM3withSM2").setProvider("BC").build(privKey); + X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder( + iss, + BigInteger.valueOf(1), + new Date(System.currentTimeMillis() - 50000), + new Date(System.currentTimeMillis() + 50000), + iss, + pubKey).addExtension(new ASN1ObjectIdentifier("2.5.29.15"), true, + new X509KeyUsage(0xfe)) + .addExtension(new ASN1ObjectIdentifier("2.5.29.37"), true, + new DERSequence(KeyPurposeId.anyExtendedKeyUsage)) + .addExtension(new ASN1ObjectIdentifier("2.5.29.17"), true, + new GeneralNames(new GeneralName[] + { + new GeneralName(GeneralName.rfc822Name, "gmca@test.cn"), + new GeneralName(GeneralName.dNSName, "ca.test.cn") + })); + + + X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen)); + + cert.checkValidity(new Date()); + + cert.verify(pubKey); + + + + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); + + cert = (X509Certificate) fact.generateCertificate(bIn); + + System.out.println("CA Cert:" + Base64.toBase64String(cert.getEncoded())); + + saveFile("CAPrikey", privKey.getEncoded()); + saveFile("CARootCert.cer", cert.getEncoded()); + System.out.println("=============测试生成国密CA根证书============="); + } + + + public static void genCertWithCaSign() throws Exception { + System.out.println("=============测试国密CA根证书签发国密证书============="); + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(readFile("CAPrikey")); + + + PrivateKey caPrivateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); + + CertificateFactory certificateFactory = CertificateFactory.getInstance("X509", "BC"); + + Certificate caRootCert = certificateFactory.generateCertificate(new FileInputStream("CARootCert.cer")); + + KeyPairGenerator g = KeyPairGenerator.getInstance("EC", "BC"); + + g.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1")); + + KeyPair p = g.generateKeyPair(); + + PrivateKey privKey = p.getPrivate(); + PublicKey pubKey = p.getPublic(); + + + ContentSigner sigGen = new JcaContentSignerBuilder("SM3withSM2").setProvider("BC").build(caPrivateKey); + X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder( + (X509Certificate) caRootCert, + BigInteger.valueOf(new Random().nextInt()), + new Date(System.currentTimeMillis() - 50000), + new Date(System.currentTimeMillis() + 50000), + new X500Principal("CN=TestCert"), + pubKey).addExtension(new ASN1ObjectIdentifier("2.5.29.15"), true, + new X509KeyUsage(X509KeyUsage.digitalSignature | X509KeyUsage.nonRepudiation)) + .addExtension(new ASN1ObjectIdentifier("2.5.29.37"), true, + new DERSequence(KeyPurposeId.anyExtendedKeyUsage)) + .addExtension(new ASN1ObjectIdentifier("2.5.29.17"), true, + new GeneralNames(new GeneralName[] + { + new GeneralName(GeneralName.rfc822Name, "gmca@test.cn"), + new GeneralName(GeneralName.dNSName, "ca.test.cn") + })); + + + X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen)); + + cert.checkValidity(new Date()); + + cert.verify(caRootCert.getPublicKey()); + + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC"); + + cert = (X509Certificate) fact.generateCertificate(bIn); + + System.out.println("custCert:" + Base64.toBase64String(cert.getEncoded())); + System.out.println("custPrivateKey:" + Base64.toBase64String(privKey.getEncoded())); + saveFile("custCert.cer", cert.getEncoded()); + saveFile("custPrivateKey", privKey.getEncoded()); + System.out.println("=============测试国密CA根证书签发国密证书============="); + + } + + public static void testDigitalSign() throws Exception { + System.out.println("=============测试国密证书数字签名============="); + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(readFile("custPrivateKey")); + + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + + PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); + + CertificateFactory certificateFactory = CertificateFactory.getInstance("X509", "BC"); + + Certificate certificate = certificateFactory.generateCertificate(new FileInputStream("custCert.cer")); + + Signature signature = Signature.getInstance("SM3withSM2", "BC"); + + signature.initSign(privateKey); + + String signText = "测试123456test"; + signature.update(signText.getBytes("UTF-8")); + + byte[] digitalsignature = signature.sign(); + + System.out.println("signText:" + signText); + + System.out.println("digitalsignature:" + Base64.toBase64String(digitalsignature)); + + Signature signature1 = Signature.getInstance("SM3withSM2", "BC"); + + signature1.initVerify(certificate.getPublicKey()); + + signature1.update(signText.getBytes("UTF-8")); + + boolean result = signature1.verify(digitalsignature); + + System.out.println("verifyResult:" + result); + + Signature signature2 = Signature.getInstance("SM3withSM2", "BC"); + + signature2.initVerify(certificate.getPublicKey()); + + signature2.update((signText + "exception").getBytes("UTF-8")); + + boolean exceptionResult = signature2.verify(digitalsignature); + + System.out.println("exceptionVerifyResult:" + exceptionResult); + + System.out.println("=============测试国密证书数字签名============="); + } + + + public static void testSM2EcDc() throws Exception { + + System.out.println("=============测试国密SM2加解密============="); + + //从证书获取公钥 + CertificateFactory certificateFactory = CertificateFactory.getInstance("X509", "BC"); + Certificate certificate = certificateFactory.generateCertificate(new FileInputStream("custCert.cer")); + PublicKey publicKey = certificate.getPublicKey(); + //获取加密参数 + BCECPublicKey localECPublicKey = (BCECPublicKey)publicKey; + ECParameterSpec localECParameterSpec = localECPublicKey.getParameters(); + ECDomainParameters localECDomainParameters = new ECDomainParameters( + localECParameterSpec.getCurve(), localECParameterSpec.getG(), + localECParameterSpec.getN()); + ECPublicKeyParameters localECPublicKeyParameters = new ECPublicKeyParameters(localECPublicKey.getQ(), + localECDomainParameters); + //待加密数据 + byte[] ebs = "123sssss测试".getBytes("UTF-8"); + + System.out.println("原文:"+new String(ebs)); + //初始化加密引擎 + SM2Engine sm2EncEngine = new SM2Engine(); + sm2EncEngine.init(true, new ParametersWithRandom(localECPublicKeyParameters)); + //加密 + byte[] bs = sm2EncEngine.processBlock(ebs,0,ebs.length); + String es = Base64.toBase64String(bs); + System.out.println("密文:"+es); + + //获取私钥 + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(readFile("custPrivateKey")); + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); + //获取解密参数 + BCECPrivateKey sm2PriK = (BCECPrivateKey)privateKey; + ECParameterSpec ecParameterSpec = sm2PriK.getParameters(); + ECDomainParameters ecDomainParameters = new ECDomainParameters( + ecParameterSpec.getCurve(), ecParameterSpec.getG(), + ecParameterSpec.getN()); + ECPrivateKeyParameters localECPrivateKeyParameters = new ECPrivateKeyParameters( + sm2PriK.getD(), ecDomainParameters); + //初始化解密引擎 + SM2Engine sm2DcEngine = new SM2Engine(); + sm2EncEngine.init(true, new ParametersWithRandom(localECPublicKeyParameters)); + sm2DcEngine.init(false, localECPrivateKeyParameters); + bs = Base64.decode(es.getBytes("Utf-8")); + byte[] b = sm2DcEngine.processBlock(bs,0,bs.length); + System.out.println("明文:"+new String(b)); + + System.out.println("=============测试国密SM2加解密============="); + } + + public static void testSaveGMKeyStore() throws Exception { + System.out.println("=============测试国密证书PKCS12 KeyStore存取============="); + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(readFile("custPrivateKey")); + + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + + PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); + + CertificateFactory certificateFactory = CertificateFactory.getInstance("X509", "BC"); + + Certificate certificate = certificateFactory.generateCertificate(new FileInputStream("custCert.cer")); + + KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC"); + + keyStore.load(null, null); + + keyStore.setKeyEntry("test", privateKey, "32145698745632145698745632145698".toCharArray(), new Certificate[]{certificate}); + + keyStore.store(new FileOutputStream("cust.pfx"), "32145698745632145698745632145698".toCharArray()); + + KeyStore keyStore1 = KeyStore.getInstance("PKCS12", "BC"); + + keyStore1.load(new FileInputStream("cust.pfx"), "32145698745632145698745632145698".toCharArray()); + + Certificate certificate1 = keyStore1.getCertificate("test"); + + PrivateKey privateKey1 = (PrivateKey) keyStore1.getKey("test", "32145698745632145698745632145698".toCharArray()); + + System.out.println("公钥证书存取前后对比:" + Arrays.equals(certificate1.getEncoded(), certificate.getEncoded())); + + System.out.println("私钥存取前后对比:" + Arrays.equals(privateKey.getEncoded(), privateKey1.getEncoded())); + + System.out.println("=============测试国密证书PKCS12 KeyStore存取============="); + + } + + public static void saveFile(String path, byte[] data) { + try { + FileOutputStream fileOutputStream = new FileOutputStream(path); + fileOutputStream.write(data); + fileOutputStream.flush(); + fileOutputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + + public static byte[] readFile(String path) throws Exception { + FileInputStream fileInputStream = new FileInputStream(path); + byte[] bytes = new byte[fileInputStream.available()]; + fileInputStream.read(bytes); + return bytes; + } + + + public static byte[] getPriKeyByteFromP8(byte[] p8byte) throws Exception { + + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(p8byte); + + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + + PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); + + ASN1InputStream asn1InputStream = new ASN1InputStream(privateKey.getEncoded()); + + ASN1Sequence p8 = (ASN1Sequence) asn1InputStream.readObject(); + + ASN1InputStream asn1InputStream1 = new ASN1InputStream(((DEROctetString) p8.getObjectAt(2)).getOctets()); + + ASN1Sequence gmPrivateKey = (ASN1Sequence)asn1InputStream1.readObject(); + + byte[] gmPriKeyBytes = ((DEROctetString)gmPrivateKey.getObjectAt(1)).getOctets(); + + return gmPriKeyBytes; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ClazzUtils.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ClazzUtils.java new file mode 100644 index 0000000..a2f41ca --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ClazzUtils.java @@ -0,0 +1,144 @@ +package com.sunyard.ssp.utils; + +import java.io.File; +import java.io.IOException; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * 获取包下所有的类名 + */ +public class ClazzUtils { + + + /** + * 获取某包下所有类 + * @param packageName 包名 + * @param isRecursion 是否遍历子包 + * @return 类的完整名称 + */ + public static Set getClassName(String packageName, boolean isRecursion) { + Set classNames = null; + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + String packagePath = packageName.replace(".", "/"); + + URL url = loader.getResource(packagePath); + if (url != null) { + String protocol = url.getProtocol(); + if (protocol.equals("file")) { + classNames = getClassNameFromDir(url.getPath(), packageName, isRecursion); + } else if (protocol.equals("jar")) { + JarFile jarFile = null; + try { + jarFile = ((JarURLConnection) url.openConnection()).getJarFile(); + } catch (Exception e) { + e.printStackTrace(); + } + + if (jarFile != null) { + getClassNameFromJar(jarFile.entries(), packageName, isRecursion); + } + } + } else { + /*从所有的jar包中查找包名*/ + classNames = getClassNameFromJars(((URLClassLoader) loader).getURLs(), packageName, isRecursion); + } + + return classNames; + } + + /** + * 从项目文件获取某包下所有类 + * @param filePath 文件路径 + * @param packageName 类名集合 + * @param isRecursion 是否遍历子包 + * @return 类的完整名称 + */ + private static Set getClassNameFromDir(String filePath, String packageName, boolean isRecursion) { + Set className = new HashSet(); + File file = new File(filePath); + File[] files = file.listFiles(); + for (File childFile : files) { + if (childFile.isDirectory()) { + if (isRecursion) { + className.addAll(getClassNameFromDir(childFile.getPath(), packageName + "." + childFile.getName(), isRecursion)); + } + } else { + String fileName = childFile.getName(); + if (fileName.endsWith(".class") && !fileName.contains("$")) { + className.add(packageName + "." + fileName.replace(".class", "")); + } + } + } + + return className; + } + + + /** + * @param jarEntries + * @param packageName + * @param isRecursion + * @return + */ + private static Set getClassNameFromJar(Enumeration jarEntries, String packageName, boolean isRecursion) { + Set classNames = new HashSet(); + + while (jarEntries.hasMoreElements()) { + JarEntry jarEntry = jarEntries.nextElement(); + if (!jarEntry.isDirectory()) { + // 这里是为了方便,先把"/" 转成 "." 再判断 ".class" 的做法可能会有bug + String entryName = jarEntry.getName().replace("/", "."); + if (entryName.endsWith(".class") && !entryName.contains("$") && entryName.startsWith(packageName)) { + entryName = entryName.replace(".class", ""); + if (isRecursion) { + classNames.add(entryName); + } else if (!entryName.replace(packageName + ".", "").contains(".")) { + classNames.add(entryName); + } + } + } + } + + return classNames; + } + + /** + * 从所有jar中搜索该包,并获取该包下所有类 + * @param urls URL集合 + * @param packageName 包路径 + * @param isRecursion 是否遍历子包 + * @return 类的完整名称 + */ + private static Set getClassNameFromJars(URL[] urls, String packageName, boolean isRecursion) { + Set classNames = new HashSet(); + + for (int i = 0; i < urls.length; i++) { + String classPath = urls[i].getPath(); + + //不必搜索classes文件夹 + if (classPath.endsWith("classes/")) { + continue; + } + + JarFile jarFile = null; + try { + jarFile = new JarFile(classPath.substring(classPath.indexOf("/"))); + } catch (IOException e) { + e.printStackTrace(); + } + + if (jarFile != null) { + classNames.addAll(getClassNameFromJar(jarFile.entries(), packageName, isRecursion)); + } + } + + return classNames; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CommonUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CommonUtil.java new file mode 100644 index 0000000..c8d22f1 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CommonUtil.java @@ -0,0 +1,47 @@ +package com.sunyard.ssp.utils; + +import java.util.UUID; + +/** + * @author:tsz + * @date:2020/3/6 + * @description: + */ +public class CommonUtil { + + /** + * 以UUID重命名 + * + * @param fileName + * @return + */ + public static String renamePic(String fileName) { + String extName = fileName.substring(fileName.lastIndexOf(".")); + return UUID.randomUUID().toString().replace("-", "") + extName; + } + + /** + * 驼峰处理成数据库格式 + * @param name + * @return + */ + public static String underscoreName(String name) { + StringBuilder result = new StringBuilder(); + if (name != null && name.length() > 0) { + // 将第一个字符处理成大写 + result.append(name.substring(0, 1).toUpperCase()); + // 循环处理其余字符 + for (int i = 1; i < name.length(); i++) { + String s = name.substring(i, i + 1); + // 在大写字母前添加下划线 + if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) { + result.append("_"); + } + // 其他字符直接转成大写 + result.append(s.toUpperCase()); + } + } + return result.toString(); + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CreateVerifyCode.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CreateVerifyCode.java new file mode 100644 index 0000000..1bfd0ff --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/CreateVerifyCode.java @@ -0,0 +1,314 @@ +package com.sunyard.ssp.utils; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Random; + +/** + * 随机字符验证码生成工具类 + * @author Exrickx + */ +public class CreateVerifyCode { + + /** + * 图片的宽度 + */ + private int width = 160; + /** + * 图片的高度 + */ + private int height = 40; + /** + * 验证码字符个数 + */ + private int codeCount = 4; + /** + * 验证码干扰线数 + */ + private int lineCount = 20; + /** + * 验证码 + */ + private String code = null; + /** + * 验证码图片Buffer + */ + private BufferedImage buffImg = null; + + Random random = new Random(); + + public CreateVerifyCode() { + creatImage(); + } + + public CreateVerifyCode(int width, int height) { + this.width = width; + this.height = height; + creatImage(); + } + + public CreateVerifyCode(int width, int height, int codeCount) { + this.width = width; + this.height = height; + this.codeCount = codeCount; + creatImage(); + } + + public CreateVerifyCode(int width, int height, int codeCount, int lineCount) { + this.width = width; + this.height = height; + this.codeCount = codeCount; + this.lineCount = lineCount; + creatImage(); + } + + public CreateVerifyCode(int width, int height, int codeCount, int lineCount, String code) { + this.width = width; + this.height = height; + this.codeCount = codeCount; + this.lineCount = lineCount; + creatImage(code); + } + + /** + * 生成图片 + */ + private void creatImage() { + // 字体的宽度 + int fontWidth = width / codeCount; + // 字体的高度 + int fontHeight = height - 5; + int codeY = height - 8; + + // 图像buffer + buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = buffImg.getGraphics(); + //Graphics2D g = buffImg.createGraphics(); + // 设置背景色 + g.setColor(getRandColor(200, 250)); + g.fillRect(0, 0, width, height); + + // 设置字体 + //Font font1 = getFont(fontHeight); + Font font = new Font("Fixedsys", Font.BOLD, fontHeight); + g.setFont(font); + + // 设置干扰线 + for (int i = 0; i < lineCount; i++) { + int xs = random.nextInt(width); + int ys = random.nextInt(height); + int xe = xs + random.nextInt(width); + int ye = ys + random.nextInt(height); + g.setColor(getRandColor(1, 255)); + g.drawLine(xs, ys, xe, ye); + } + + // 添加噪点 噪声率 + float yawpRate = 0.01f; + int area = (int) (yawpRate * width * height); + for (int i = 0; i < area; i++) { + int x = random.nextInt(width); + int y = random.nextInt(height); + + buffImg.setRGB(x, y, random.nextInt(255)); + } + + // 得到随机字符 + String str1 = randomStr(codeCount); + this.code = str1; + for (int i = 0; i < codeCount; i++) { + String strRand = str1.substring(i, i + 1); + g.setColor(getRandColor(1, 255)); + // g.drawString(a,x,y); + // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处 + g.drawString(strRand, i*fontWidth+3, codeY); + } + + } + + /** + * 生成指定字符图片 + */ + private void creatImage(String code) { + // 字体的宽度 + int fontWidth = width / codeCount; + // 字体的高度 + int fontHeight = height - 5; + int codeY = height - 8; + + // 图像buffer + buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = buffImg.getGraphics(); + //Graphics2D g = buffImg.createGraphics(); + // 设置背景色 + g.setColor(getRandColor(200, 250)); + g.fillRect(0, 0, width, height); + + // 设置字体 + //Font font1 = getFont(fontHeight); + Font font = new Font("Fixedsys", Font.BOLD, fontHeight); + g.setFont(font); + + // 设置干扰线 + for (int i = 0; i < lineCount; i++) { + int xs = random.nextInt(width); + int ys = random.nextInt(height); + int xe = xs + random.nextInt(width); + int ye = ys + random.nextInt(height); + g.setColor(getRandColor(1, 255)); + g.drawLine(xs, ys, xe, ye); + } + + // 添加噪点 噪声率 + float yawpRate = 0.01f; + int area = (int) (yawpRate * width * height); + for (int i = 0; i < area; i++) { + int x = random.nextInt(width); + int y = random.nextInt(height); + + buffImg.setRGB(x, y, random.nextInt(255)); + } + + this.code = code; + for (int i = 0; i < code.length(); i++) { + String strRand = code.substring(i, i + 1); + g.setColor(getRandColor(1, 255)); + // g.drawString(a,x,y); + // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处 + g.drawString(strRand, i*fontWidth+3, codeY); + } + + } + + /** + * 得到随机字符 + * @param n + * @return + */ + public String randomStr(int n) { + String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; + String str2 = ""; + int len = str1.length() - 1; + double r; + for (int i = 0; i < n; i++) { + r = (Math.random()) * len; + str2 = str2 + str1.charAt((int) r); + } + return str2; + } + + /** + * 得到随机颜色 + * @param fc + * @param bc + * @return + */ + private Color getRandColor(int fc, int bc) { + // 给定范围获得随机颜色 + if (fc > 255){ + fc = 255; + } + if (bc > 255){ + bc = 255; + } + int r = fc + random.nextInt(bc - fc); + int g = fc + random.nextInt(bc - fc); + int b = fc + random.nextInt(bc - fc); + return new Color(r, g, b); + } + + /** + * 产生随机字体 + */ + private Font getFont(int size) { + Random random = new Random(); + Font[] font = new Font[5]; + font[0] = new Font("Ravie", Font.PLAIN, size); + font[1] = new Font("Antique Olive Compact", Font.PLAIN, size); + font[2] = new Font("Fixedsys", Font.PLAIN, size); + font[3] = new Font("Wide Latin", Font.PLAIN, size); + font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size); + return font[random.nextInt(5)]; + } + + // 扭曲方法 + private void shear(Graphics g, int w1, int h1, Color color) { + shearX(g, w1, h1, color); + shearY(g, w1, h1, color); + } + + private void shearX(Graphics g, int w1, int h1, Color color) { + + int period = random.nextInt(2); + + boolean borderGap = true; + int frames = 1; + int phase = random.nextInt(2); + + for (int i = 0; i < h1; i++) { + double d = (double) (period >> 1) + * Math.sin((double) i / (double) period + + (6.2831853071795862D * (double) phase) + / (double) frames); + g.copyArea(0, i, w1, 1, (int) d, 0); + if (borderGap) { + g.setColor(color); + g.drawLine((int) d, i, 0, i); + g.drawLine((int) d + w1, i, w1, i); + } + } + + } + + private void shearY(Graphics g, int w1, int h1, Color color) { + + // 50 + int period = random.nextInt(40) + 10; + + boolean borderGap = true; + int frames = 20; + int phase = 7; + for (int i = 0; i < w1; i++) { + double d = (double) (period >> 1) + * Math.sin((double) i / (double) period + + (6.2831853071795862D * (double) phase) + / (double) frames); + g.copyArea(i, 0, 1, h1, 0, (int) d); + if (borderGap) { + g.setColor(color); + g.drawLine(i, (int) d, i, 0); + g.drawLine(i, (int) d + h1, i, h1); + } + + } + + } + + public void write(OutputStream sos) throws IOException { + ImageIO.write(buffImg, "png", sos); + sos.close(); + } + + public BufferedImage getBuffImg() { + return buffImg; + } + + public String getCode() { + return code.toLowerCase(); + } + + /** + * 随机6位数生成 + */ + public String getRandomNum() { + + Random random = new Random(); + int num = random.nextInt(999999); + //不足六位前面补0 + String str = String.format("%06d", num); + return str; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/DateUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/DateUtil.java new file mode 100644 index 0000000..efd79b1 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/DateUtil.java @@ -0,0 +1,59 @@ +package com.sunyard.ssp.utils; + +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.Date; + +public class DateUtil { + + public static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + /** + * String 型转 date + * @param stringDate + * @return + */ + public static LocalDate StringToDate(String stringDate){ + LocalDate localDate = LocalDate.now(); + try { + if (stringDate != null && stringDate != "") { + localDate = LocalDate.parse(stringDate); + } + return localDate; + }catch (Exception e){ + e.printStackTrace(); + return null; + } + } + + /** + * 时间转String 遇到null 直接返回null + * @param stringDate + * @return + */ + public static LocalDate StringToDateOrNull(String stringDate){ + try { + if (stringDate != null && stringDate != "") { + LocalDate localDate = LocalDate.parse(stringDate); + return localDate; + }else { + return null; + } + }catch (Exception e){ + e.printStackTrace(); + return null; + } + } + + /** + * 获得一个格式化时间 + * @return + */ + public static String getFormatDate(){ + Date localDateTime = new Date(); + String result = simpleDateFormat.format(localDateTime); + return result; + } + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/FileUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/FileUtil.java new file mode 100644 index 0000000..239ddb8 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/FileUtil.java @@ -0,0 +1,187 @@ +package com.sunyard.ssp.utils; + +import cn.hutool.core.date.DateUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * @author:tsz + * @date:2020/3/6 + * @description: + */ +@Component +@Slf4j +public class FileUtil { + + @Value("${file.path}") + private String filePath; + + /** + * 文件路径上传完整路径 + * + * @param file + * @return + */ + public String localUpload(MultipartFile file) { + + String key = CommonUtil.renamePic(file.getOriginalFilename()); + String day = DateUtil.format(DateUtil.date(), "yyyyMMdd"); + String path = filePath + "/" + day; + File dir = new File(path); + if (!dir.exists()) { + dir.mkdirs(); + } + File f = new File(path + "/" + key); + if (f.exists()) { + throw new RuntimeException("文件名已存在"); + } + try { + file.transferTo(f); + return path + "/" + key; + } catch (IOException e) { + log.error(e.toString()); + throw new RuntimeException("上传文件出错"); + } + } + + /** + * 文件路径上传只返回文件名 + * + * @param file + * @return + */ + public String upload(MultipartFile file) throws IOException { + try { + //String key = Md5Util.md5HashCode(file.getInputStream()) +"_"+ file.getOriginalFilename(); + String key = file.getOriginalFilename(); + String s = Md5Util.little16MD5a(DigestUtils.md5Hex(file.getInputStream())); + String path = filePath + "/" + s; + File dir = new File(path); + if (!dir.exists()) { + dir.mkdirs(); + } + File f = new File(path + "/" + key); + //如果文件已经存在直接返回文件名证明快速上传了 + if (f.exists()) { + return s + "/" +key; + } + file.transferTo(f); + key = s + "/"+ key; + return key; + } catch (IOException e) { + e.printStackTrace(); + log.error(e.toString()); + throw new RuntimeException("上传文件出错"); + } + } + + /** + * 读取文件 + * + * @param url + * @param response + */ + public void view(String url, HttpServletResponse response) { + + File file = new File(url); + FileInputStream i = null; + OutputStream o = null; + + try { + i = new FileInputStream(file); + o = response.getOutputStream(); + + byte[] buf = new byte[1024]; + int bytesRead; + + while ((bytesRead = i.read(buf)) > 0) { + o.write(buf, 0, bytesRead); + o.flush(); + } + + i.close(); + o.close(); + } catch (IOException e) { + log.error(e.toString()); + throw new RuntimeException("读取文件出错"); + } + } + + /** + * 重命名 + * + * @param url + * @param toKey + * @return + */ + public String renameFile(String url, String toKey) { + + String result = copyFile(url, toKey); + deleteFile(url); + return result; + } + + /** + * 复制文件 + * + * @param url + * @param toKey + */ + public String copyFile(String url, String toKey) { + + File file = new File(url); + FileInputStream i = null; + FileOutputStream o = null; + + try { + i = new FileInputStream(file); + o = new FileOutputStream(new File(file.getParentFile() + "/" + toKey)); + + byte[] buf = new byte[1024]; + int bytesRead; + + while ((bytesRead = i.read(buf)) > 0) { + o.write(buf, 0, bytesRead); + } + + i.close(); + o.close(); + return file.getParentFile() + "/" + toKey; + } catch (IOException e) { + log.error(e.toString()); + throw new RuntimeException("复制文件出错"); + } + } + + /** + * 删除文件 + * + * @param url + */ + public void deleteFile(String url) { + + File file = new File(url); + file.delete(); + } + + /** + * 删除文件 + * + * @param url + */ + public void deleteFileName(String url) { + + File file = new File(filePath + "/" + url); + file.delete(); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/FileUtils.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/FileUtils.java new file mode 100644 index 0000000..0d42866 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/FileUtils.java @@ -0,0 +1,33 @@ +package com.sunyard.ssp.utils; + +import java.io.IOException; +import java.io.RandomAccessFile; + +public class FileUtils { + public static void writeFile(String filePath, byte[] data) throws IOException { + RandomAccessFile raf = null; + try { + raf = new RandomAccessFile(filePath, "rw"); + raf.write(data); + } finally { + if (raf != null) { + raf.close(); + } + } + } + + public static byte[] readFile(String filePath) throws IOException { + RandomAccessFile raf = null; + byte[] data; + try { + raf = new RandomAccessFile(filePath, "r"); + data = new byte[(int) raf.length()]; + raf.read(data); + return data; + } finally { + if (raf != null) { + raf.close(); + } + } + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/IpUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/IpUtil.java new file mode 100644 index 0000000..4aadf71 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/IpUtil.java @@ -0,0 +1,46 @@ +package com.sunyard.ssp.utils; + +import javax.servlet.http.HttpServletRequest; +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class IpUtil { + + + /** + * 获取真实ip地址,避免获取代理ip + */ + public static String getIpAddress(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + if ("127.0.0.1".equals(ip)) { + //根据网卡取本机配置的IP + InetAddress inet = null; + try { + inet = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + ip = inet.getHostAddress(); + } + } + + if (ip != null && ip.length() > 15) { + if (ip.indexOf(",") > 0) { + ip = ip.substring(0, ip.indexOf(",")); + } + } + if("0:0:0:0:0:0:0:1".equals(ip)){ + ip="127.0.0.1"; + } + return ip; + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/JsonUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/JsonUtil.java new file mode 100644 index 0000000..2158a23 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/JsonUtil.java @@ -0,0 +1,27 @@ +package com.sunyard.ssp.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.InputStreamReader; +import java.io.Reader; + +/** + * @author fyc + * @date 2020-6-3 + */ +public class JsonUtil { + + public static String getJsonStrFromJsonFile(File jsonFile) throws Exception { + FileReader fileReader = new FileReader(jsonFile); + Reader reader = new InputStreamReader(new FileInputStream(jsonFile), "utf-8"); + int ch = 0; + StringBuffer sb = new StringBuffer(); + while ((ch = reader.read()) != -1) { + sb.append((char) ch); + } + fileReader.close(); + reader.close(); + return sb.toString(); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/KeyUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/KeyUtil.java new file mode 100644 index 0000000..ddf28cc --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/KeyUtil.java @@ -0,0 +1,20 @@ +package com.sunyard.ssp.utils; + +import com.sunyard.ssp.vo.KeyVo; + +/** + * @date:2020/6/10 + * @description: + */ +public class KeyUtil { + + public static KeyVo parseKeyName(String keyName){ + String[] split = keyName.split("\\."); + KeyVo keyVo = new KeyVo(); + keyVo.setSolutionNumber(split[0]); + keyVo.setNodeNumber(split[1]); + keyVo.setTmplNumber(split[2]); + keyVo.setKeyNumber(split[3]); + return keyVo; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/Md5Util.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/Md5Util.java new file mode 100644 index 0000000..9582d43 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/Md5Util.java @@ -0,0 +1,110 @@ +package com.sunyard.ssp.utils; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.MessageDigest; + +/** + * @author:tsz + * @date:2020/5/13 + * @description: + */ +public class Md5Util { + + /** + * 获取文件的md5值 ,有可能不是32位 + * @param filePath 文件路径 + * @return + * @throws FileNotFoundException + */ + public static String md5HashCode(String filePath) throws FileNotFoundException{ + FileInputStream fis = new FileInputStream(filePath); + return md5HashCode(fis); + } + + /** + * 保证文件的MD5值为32位 + * @param filePath 文件路径 + * @return + * @throws FileNotFoundException + */ + public static String md5HashCode32(String filePath) throws FileNotFoundException{ + FileInputStream fis = new FileInputStream(filePath); + return md5HashCode32(fis); + } + + /** + * java获取文件的md5值 + * @param fis 输入流 + * @return + */ + public static String md5HashCode(InputStream fis) { + try { + //拿到一个MD5转换器,如果想使用SHA-1或SHA-256,则传入SHA-1,SHA-256 + MessageDigest md = MessageDigest.getInstance("MD5"); + + //分多次将一个文件读入,对于大型文件而言,比较推荐这种方式,占用内存比较少。 + byte[] buffer = new byte[1024]; + int length = -1; + while ((length = fis.read(buffer, 0, 1024)) != -1) { + md.update(buffer, 0, length); + } + fis.close(); + //转换并返回包含16个元素字节数组,返回数值范围为-128到127 + byte[] md5Bytes = md.digest(); + BigInteger bigInt = new BigInteger(1, md5Bytes);//1代表绝对值 + return bigInt.toString(16);//转换为16进制 + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + /** + * java计算文件32位md5值 + * @param fis 输入流 + * @return + */ + public static String md5HashCode32(InputStream fis) { + try { + //拿到一个MD5转换器,如果想使用SHA-1或SHA-256,则传入SHA-1,SHA-256 + MessageDigest md = MessageDigest.getInstance("MD5"); + + //分多次将一个文件读入,对于大型文件而言,比较推荐这种方式,占用内存比较少。 + byte[] buffer = new byte[1024]; + int length = -1; + while ((length = fis.read(buffer, 0, 1024)) != -1) { + md.update(buffer, 0, length); + } + fis.close(); + + //转换并返回包含16个元素字节数组,返回数值范围为-128到127 + byte[] md5Bytes = md.digest(); + StringBuffer hexValue = new StringBuffer(); + for (int i = 0; i < md5Bytes.length; i++) { + int val = ((int) md5Bytes[i]) & 0xff;//解释参见最下方 + if (val < 16) { + /** + * 如果小于16,那么val值的16进制形式必然为一位, + * 因为十进制0,1...9,10,11,12,13,14,15 对应的 16进制为 0,1...9,a,b,c,d,e,f; + * 此处高位补0。 + */ + hexValue.append("0"); + } + //这里借助了Integer类的方法实现16进制的转换 + hexValue.append(Integer.toHexString(val)); + } + return hexValue.toString(); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + // 16位是将32位中的16截取出来 + public static String little16MD5a(String str) { + return str.substring(8, 24); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/PageUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/PageUtil.java new file mode 100644 index 0000000..431eea5 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/PageUtil.java @@ -0,0 +1,164 @@ +package com.sunyard.ssp.utils; + +import cn.hutool.core.util.StrUtil; +import com.sunyard.ssp.common.PageVo; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +/** + * @author Exrickx + */ +public class PageUtil { + + /** + * JPA��ҳ + * + * @param page + * @return + */ + public static Pageable initPage(PageVo page) { + + Pageable pageable = null; + int pageNumber = page.getPageNumber(); + int pageSize = page.getPageSize(); + String sort = page.getSort(); + String order = page.getOrder(); + + if (pageNumber < 1) { + pageNumber = 1; + } + if (pageSize < 1) { + pageSize = 10; + } + + if (StrUtil.isNotBlank(sort)) { + Sort.Direction d; + if (StrUtil.isBlank(order)) { + d = Sort.Direction.DESC; + } else { + d = Sort.Direction.valueOf(order.toUpperCase()); + } + Sort s = Sort.by(d, sort); + pageable = PageRequest.of(pageNumber - 1, pageSize, s); + } else { + pageable = PageRequest.of(pageNumber - 1, pageSize); + } + return pageable; + } + + /* + * jpa的分页和mybatis的分页实现逻辑不一样 + * */ + public static Pageable initMybatisPage(PageVo page) { + Pageable pageable = null; + int pageNumber = page.getPageNumber(); + int pageSize = page.getPageSize(); + String sort = page.getSort(); + String order = page.getOrder(); + + if (pageNumber < 1) { + pageNumber = 1; + } + if (pageSize < 1) { + pageSize = 10; + } + if (StrUtil.isNotBlank(sort)) { + Sort.Direction d; + if (StrUtil.isBlank(order)) { + d = Sort.Direction.DESC; + } else { + d = Sort.Direction.valueOf(order.toUpperCase()); + } + Sort s = Sort.by(d, sort); + pageable = PageRequest.of(pageNumber, pageSize, s); + } else { + pageable = PageRequest.of(pageNumber, pageSize); + } + return pageable; + } + + /** + * List 分页 + * + * @param page + * @param list + * @return + */ + public static List listToPage(PageVo page, List list) { + + Map pageParam = getPageParam(page); + + int fromIndex = pageParam.get("fromIndex"); + int toIndex = pageParam.get("toIndex"); + + if (fromIndex > list.size()) { + return new ArrayList(); + } else if (toIndex >= list.size()) { + return list.subList(fromIndex, list.size()); + } else { + return list.subList(fromIndex, toIndex); + } + } + + /** + * set 分页 + * @param page + * @param set + * @return + */ + public static Set SetToPage(PageVo page, Set set) { + + Map pageParam = getPageParam(page); + + int fromIndex = pageParam.get("fromIndex"); + int toIndex = pageParam.get("toIndex"); + + List objList = new ArrayList<>(set); + + if (fromIndex > set.size()) { + return Collections.emptySet(); + } else if (toIndex >= set.size()) { + return new LinkedHashSet(objList.subList(fromIndex, set.size())); + } else { + return new LinkedHashSet(objList.subList(fromIndex, toIndex)); + } + } + + /** + * 获取分页参数 + * @param page + * @return + */ + public static Map getPageParam(PageVo page) { + + Map param = new HashMap<>(); + + int pageNumber = page.getPageNumber() - 1; + int pageSize = page.getPageSize(); + + if (pageNumber < 0) { + pageNumber = 0; + } + if (pageSize < 1) { + pageSize = 10; + } + + int fromIndex = pageNumber * pageSize; + int toIndex = pageNumber * pageSize + pageSize; + + param.put("fromIndex", fromIndex); + param.put("toIndex", toIndex); + + return param; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ProtobufUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ProtobufUtil.java new file mode 100644 index 0000000..06dbb77 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ProtobufUtil.java @@ -0,0 +1,11 @@ +package com.sunyard.ssp.utils; + +/** + * @author:tsz + * @date:2020/4/28 + * @description: + */ +public class ProtobufUtil { + + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ResponseUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ResponseUtil.java new file mode 100644 index 0000000..0b0c40a --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ResponseUtil.java @@ -0,0 +1,70 @@ +package com.sunyard.ssp.utils; + +import com.google.gson.Gson; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Exrickx + */ +@Slf4j +public class ResponseUtil { + + /** + * 使用response输出JSON + * @param response + * @param resultMap + */ + public static void out(HttpServletResponse response, Map resultMap){ + ServletOutputStream out = null; + try { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, HEAD, DELETE"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("access-control-allow-headers", "Content-Type,Accept,Authorization,accesstoken"); + response.setHeader("Content-type", "application/json;charset=UTF-8"); + response.setCharacterEncoding("UTF-8"); + //response.setContentType("application/json"); + out = response.getOutputStream(); + out.write(new Gson().toJson(resultMap).getBytes("UTF-8")); + } catch (Exception e) { + log.error(e + "输出JSON出错"); + } finally{ + if(out!=null){ + try { + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static Map resultMap(boolean flag, Integer code, String msg){ + + Map resultMap = new HashMap(16); + resultMap.put("success", flag); + resultMap.put("message", msg); + resultMap.put("code", code); + resultMap.put("timestamp", System.currentTimeMillis()); + return resultMap; + } + + public static Map resultMap(boolean flag, Integer code, String msg, Object data){ + + Map resultMap = new HashMap(16); + resultMap.put("success", flag); + resultMap.put("message", msg); + resultMap.put("code", code); + resultMap.put("timestamp", System.currentTimeMillis()); + resultMap.put("result", data); + return resultMap; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ResultUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ResultUtil.java new file mode 100644 index 0000000..35525f0 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ResultUtil.java @@ -0,0 +1,54 @@ +package com.sunyard.ssp.utils; + + +import com.sunyard.ssp.common.Result; + +/** + * @author Exrick + */ +public class ResultUtil { + + private Result result; + + public ResultUtil(){ + result=new Result<>(); + result.setSuccess(true); + result.setMessage("success"); + result.setCode(200); + } + + public Result setData(T t){ + this.result.setResult(t); + this.result.setCode(200); + return this.result; + } + + public Result setSuccessMsg(String msg){ + this.result.setSuccess(true); + this.result.setMessage(msg); + this.result.setCode(200); + this.result.setResult(null); + return this.result; + } + + public Result setData(T t, String msg){ + this.result.setResult(t); + this.result.setCode(200); + this.result.setMessage(msg); + return this.result; + } + + public Result setErrorMsg(String msg){ + this.result.setSuccess(false); + this.result.setMessage(msg); + this.result.setCode(500); + return this.result; + } + + public Result setErrorMsg(Integer code, String msg){ + this.result.setSuccess(false); + this.result.setMessage(msg); + this.result.setCode(code); + return this.result; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/SecurityUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/SecurityUtil.java new file mode 100644 index 0000000..aaf06f1 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/SecurityUtil.java @@ -0,0 +1,144 @@ +package com.sunyard.ssp.utils; + +import cn.hutool.core.util.StrUtil; +import com.google.gson.Gson; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.common.constant.SecurityConstant; +import com.sunyard.ssp.modules.user.entity.ScPermission; +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScDepartmentService; +import com.sunyard.ssp.modules.user.service.IScUserRoleService; +import com.sunyard.ssp.modules.user.service.IScUserService; +import com.sunyard.ssp.vo.TokenUser; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * @author Exrickx + */ +@Component +public class SecurityUtil { + + private Boolean tokenRedis = true; + + @Value("${ssp.saveLoginTime}") + private Integer saveLoginTime; + + @Value("${ssp.tokenExpireTime}") + private Integer tokenExpireTime; + + @Autowired + private IScUserService userService; + + @Autowired + private IScUserRoleService userRoleService; + + @Autowired + private IScDepartmentService departmentService; + + @Autowired + private StringRedisTemplate redisTemplate; + + public String getToken(String username, Boolean saveLogin){ + + Boolean saved = false; + if(saveLogin==null||saveLogin){ + saved = true; + if(!tokenRedis){ + tokenExpireTime = saveLoginTime * 60 * 24; + } + } + // 生成token + ScUser u = userService.findByUsername(username); + List list = new ArrayList<>(); + for(ScPermission p : u.getPermissions()){ + if(CommonConstant.PERMISSION_OPERATION.equals(p.getPType()) + && StrUtil.isNotBlank(p.getTitle()) + && StrUtil.isNotBlank(p.getPath())) { + list.add(p.getTitle()); + } + } + for(ScRole r : u.getRoles()){ + list.add(r.getName()); + } + // 登陆成功生成token + String token; + if(tokenRedis){ + // redis + token = UUID.randomUUID().toString().replace("-", ""); + TokenUser user = new TokenUser(u.getUsername(), list, saved); + // 单点登录 之前的token失效 + String oldToken = redisTemplate.opsForValue().get(SecurityConstant.USER_TOKEN + u.getUsername()); + if(StrUtil.isNotBlank(oldToken)){ + redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken); + } + if(saved){ + redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + u.getUsername(), token, saveLoginTime, TimeUnit.DAYS); + redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(user), saveLoginTime, TimeUnit.DAYS); + }else{ + redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + u.getUsername(), token, tokenExpireTime, TimeUnit.MINUTES); + redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(user), tokenExpireTime, TimeUnit.MINUTES); + } + }else{ + // jwt + token = SecurityConstant.TOKEN_SPLIT + Jwts.builder() + //主题 放入用户名 + .setSubject(u.getUsername()) + //自定义属性 放入用户拥有请求权限 + .claim(SecurityConstant.AUTHORITIES, new Gson().toJson(list)) + //失效时间 + .setExpiration(new Date(System.currentTimeMillis() + tokenExpireTime * 60 * 1000)) + //签名算法和密钥 + .signWith(SignatureAlgorithm.HS512, SecurityConstant.JWT_SIGN_KEY) + .compact(); + } + return token; + } + + /** + * 获取当前登录用户 + * @return + */ + public ScUser getCurrUser(){ + + UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + return userService.findByUsername(user.getUsername()); + } + + /** + * 获取当前用户数据权限 null代表具有所有权限 + */ + public List getDeparmentIds(){ + + List deparmentIds = new ArrayList<>(); + ScUser u = getCurrUser(); + // 用户角色 + List userRoleList = userRoleService.findByUserId(u.getId()); + // 判断有无全部数据的角色 + Boolean flagAll = false; + for(ScRole r : userRoleList){ + if(r.getDataType()==null||r.getDataType().equals(CommonConstant.DATA_TYPE_ALL)){ + flagAll = true; + break; + } + } + if(flagAll){ + return null; + } + // 查找自定义 + return userRoleService.findDepIdsByUserId(u.getId()); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/SpringUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/SpringUtil.java new file mode 100644 index 0000000..04a87b3 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/SpringUtil.java @@ -0,0 +1,40 @@ +package com.sunyard.ssp.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class SpringUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if(SpringUtil.applicationContext == null) { + SpringUtil.applicationContext = applicationContext; + } + } + + //获取applicationContext + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + //通过name获取 Bean. + public static Object getBean(String name){ + return getApplicationContext().getBean(name); + } + + //通过class获取Bean. + public static T getBean(Class clazz){ + return getApplicationContext().getBean(clazz); + } + + //通过name,以及Clazz返回指定的Bean + public static T getBean(String name,Class clazz){ + return getApplicationContext().getBean(name, clazz); + } + +} \ No newline at end of file diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/StringUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/StringUtil.java new file mode 100644 index 0000000..5097e4c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/StringUtil.java @@ -0,0 +1,50 @@ +package com.sunyard.ssp.utils; + +/** + * @author:tsz + * @date:2020/5/28 + * @description: + */ +public class StringUtil { + /** + * 截取字符串str中指定字符 strStart、strEnd之间的字符串 + * @param str + * @param strStart + * @param strEnd + * @return + */ + public static String subString(String str, String strStart, String strEnd) { + + /* 找出指定的2个字符在 该字符串里面的 位置 */ + int strStartIndex = str.indexOf(strStart); + int strEndIndex = str.indexOf(strEnd); + + /* index 为负数 即表示该字符串中 没有该字符 */ + if (strStartIndex < 0) { + return "字符串 :---->" + str + "<---- 中不存在 " + strStart + ", 无法截取目标字符串"; + } + if (strEndIndex < 0) { + return "字符串 :---->" + str + "<---- 中不存在 " + strEnd + ", 无法截取目标字符串"; + } + /* 开始截取 */ + String result = str.substring(strStartIndex, strEndIndex).substring(strStart.length()); + return result; + } + /** + * 将byte数组转换为16进制字符串 + * @param bytes 要转换的byte数组 + * @return 转换后的16进制字符串 + */ + public static String bytesToHex(byte[] bytes) { + StringBuilder hexBuilder = new StringBuilder(); + for (byte b : bytes) { + String hex = Integer.toHexString(b & 0xFF); // 将byte转换为无符号的16进制字符串 + if (hex.length() == 1) { + hexBuilder.append('0'); // 如果是单个字符,前面补0 + } + hexBuilder.append(hex); + } + return hexBuilder.toString(); + } +} + diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ThreadPoolUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ThreadPoolUtil.java new file mode 100644 index 0000000..b489047 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/ThreadPoolUtil.java @@ -0,0 +1,37 @@ +package com.sunyard.ssp.utils; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class ThreadPoolUtil { + /** + * 线程缓冲队列 + */ + private static BlockingQueue bqueue = new ArrayBlockingQueue(100); + /** + * 核心线程数,会一直存活,即使没有任务,线程池也会维护线程的最少数量 + */ + private static final int SIZE_CORE_POOL = 5; + /** + * 线程池维护线程的最大数量 + */ + private static final int SIZE_MAX_POOL = 10; + /** + * 线程池维护线程所允许的空闲时间 + */ + private static final long ALIVE_TIME = 2000; + + private static ThreadPoolExecutor pool = new ThreadPoolExecutor(SIZE_CORE_POOL, SIZE_MAX_POOL, ALIVE_TIME, TimeUnit.MILLISECONDS, bqueue, new ThreadPoolExecutor.CallerRunsPolicy()); + + static { + + pool.prestartAllCoreThreads(); + } + + public static ThreadPoolExecutor getPool() { + return pool; + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UserUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UserUtil.java new file mode 100644 index 0000000..1a80219 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UserUtil.java @@ -0,0 +1,81 @@ +package com.sunyard.ssp.utils; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.sunyard.ssp.common.constant.CommonConstant; +import com.sunyard.ssp.modules.user.entity.ScUser; +import com.sunyard.ssp.modules.user.service.IScUserService; + +import java.util.List; + +public class UserUtil { + private static SecurityUtil securityUtil = SpringUtil.getBean(SecurityUtil.class); + private static IScUserService userService = SpringUtil.getBean(IScUserService.class); + + public static void verifyUser(ScUser u) throws Exception { + if (StrUtil.isBlank(u.getPassword()) || StrUtil.isBlank(u.getUsername())) { + throw new Exception ("缺少必需表单字段"); + } + + /*if (u.getUsername().length() < 6 || u.getUsername().length() > 30){ + throw new Exception("用户名长度应为6到30字符"); + }*/ + + if ( StrUtil.isNotBlank(u.getUsername())){ + if(CollectionUtils.isNotEmpty(userService.list(new QueryWrapper().lambda() + .eq(ScUser::getUsername,u.getUsername())))){ + throw new Exception("该用户名已被注册"); + } + } + + /*if (!checkUserName(u.getUsername())){ + throw new Exception("用户名只能由数字、字母或下划线组成"); + }*/ + + if ( StrUtil.isNotBlank(u.getTel()) ){ + if(CollectionUtils.isNotEmpty(userService.list(new QueryWrapper().lambda().eq(ScUser::getTel,u.getTel())))){ + throw new Exception("该手机号已绑定其他账户"); + } + } + + if ( StrUtil.isNotBlank(u.getEmail())){ + List t = userService.list(new QueryWrapper().lambda().eq(ScUser::getEmail,u.getEmail())); + if(CollectionUtils.isNotEmpty(userService.list(new QueryWrapper().lambda().eq(ScUser::getEmail,u.getEmail())))){ + throw new Exception("该邮箱已绑定其他账户"); + } + } + + } + + public static boolean checkUserName(String name) { + String regExp = "^[0-9a-zA-Z_]{1,}$"; + if(name.matches(regExp)) { + return true; + }else { + return false; + } + } + + public static void verifyUfield(String signInfo,Long userId) throws Exception { + //校验签名信息,用户id不为空 + if(StrUtil.isBlank(signInfo)){ + throw new Exception("签名信息不能为空"); + } + if(null==userId){ + throw new Exception("用户id不能为空"); + } + //查询用户绑定U盾公钥 + ScUser user = userService.getById(userId); + if(null==user){ + throw new Exception("用户不存在"); + } + if(StrUtil.isBlank(user.getUPublickey())){ + throw new Exception("用户未绑定U盾"); + } + if(!CommonConstant.USER_STATUS_NORMAL.equals(user.getStatus())){ + throw new Exception("用户被禁用"); + } + + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UsernameUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UsernameUtil.java new file mode 100644 index 0000000..d88ce1a --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UsernameUtil.java @@ -0,0 +1,56 @@ +package com.sunyard.ssp.utils; + +import lombok.extern.slf4j.Slf4j; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 用户名验证工具类 + * @author Exrickx + */ +@Slf4j +public class UsernameUtil { + + /** + * 由字母数字下划线组成且开头必须是字母,不能超过16位 + */ + private static final Pattern pUsername = Pattern.compile("[a-zA-Z]{1}[a-zA-Z0-9_]{1,15}"); + + /** + * 手机号 + */ + private static final Pattern pMobile = Pattern.compile("^1[3|4|5|8][0-9]\\d{8}$"); + + /** + * 邮箱 + */ + private static final Pattern pEmail = Pattern.compile("^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*\\.[a-zA-Z0-9]{2,6}$"); + + public static boolean Username(String v){ + + Matcher m = pUsername.matcher(v); + if(m.matches()){ + return true; + } + return false; + } + + public static boolean Mobile(String v){ + + Matcher m = pMobile.matcher(v); + if(m.matches()){ + return true; + } + return false; + } + + public static boolean Email(String v){ + + Matcher m = pEmail.matcher(v); + if(m.matches()){ + return true; + } + return false; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UuidUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UuidUtil.java new file mode 100644 index 0000000..817d7b9 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/UuidUtil.java @@ -0,0 +1,17 @@ +package com.sunyard.ssp.utils; + +import java.util.UUID; + +/** + * 处理UUID + */ +public class UuidUtil { + + /** + * 生成一个UUID + * @return + */ + public static String generate(){ + return UUID.randomUUID().toString().replace("-", ""); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/RegexUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/RegexUtil.java new file mode 100644 index 0000000..f826441 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/RegexUtil.java @@ -0,0 +1,52 @@ +package com.sunyard.ssp.utils.regexp; + +import com.sunyard.ssp.utils.regexp.model.OrdinaryRegexNode; +import com.sunyard.ssp.utils.regexp.model.RegexNode; + +import java.util.regex.Pattern; + +/** + * @author:tsz + * @date:2020/4/14 + * @description: + */ +public class RegexUtil { + + /** + *@author :tsz + *@date :2020/04/14 17:56 + *@description : 根据表达式生成随机数 + */ + public static String genByExpression(String expression){ + RegexNode node = null; + try { + node = new OrdinaryRegexNode(expression); + Pattern pattern = Pattern.compile(expression); + String random = node.random(); + if (pattern.matcher(random).matches()) { + return random; + } else { + genByExpression(expression); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + + } + /** + *@author :tsz + *@param :expression 表达式 + *@param :number 要校验的值 + *@date :2020/04/14 17:55 + *@description : 参数校验 true校验成功false失败 + */ + public static Boolean checkNameByExpression(String expression,String number){ + Pattern pattern = Pattern.compile(expression); + if (pattern.matcher(number).matches()) { + return true; + } + return false; + + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/RegexpIllegalException.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/RegexpIllegalException.java new file mode 100644 index 0000000..7cd7967 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/RegexpIllegalException.java @@ -0,0 +1,16 @@ +package com.sunyard.ssp.utils.regexp.exception; + +public class RegexpIllegalException extends Exception { + + public RegexpIllegalException() { + super(); + } + + public RegexpIllegalException(String message) { + super(message); + } + + public RegexpIllegalException(String regexp, int index) { + super(String.format("Invalid regular expression: %s, Index: %d", regexp, index)); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/TypeNotMatchException.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/TypeNotMatchException.java new file mode 100644 index 0000000..f1e55c3 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/TypeNotMatchException.java @@ -0,0 +1,12 @@ +package com.sunyard.ssp.utils.regexp.exception; + +public class TypeNotMatchException extends Exception { + + public TypeNotMatchException() { + super(); + } + + public TypeNotMatchException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/UninitializedException.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/UninitializedException.java new file mode 100644 index 0000000..c0d667c --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/exception/UninitializedException.java @@ -0,0 +1,12 @@ +package com.sunyard.ssp.utils.regexp.exception; + +public class UninitializedException extends Exception { + + public UninitializedException() { + super(); + } + + public UninitializedException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/BaseRegexNode.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/BaseRegexNode.java new file mode 100644 index 0000000..f34f533 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/BaseRegexNode.java @@ -0,0 +1,171 @@ +package com.sunyard.ssp.utils.regexp.model; + + + +import com.sunyard.ssp.utils.regexp.exception.RegexpIllegalException; +import com.sunyard.ssp.utils.regexp.exception.TypeNotMatchException; +import com.sunyard.ssp.utils.regexp.exception.UninitializedException; + +import java.util.ArrayList; +import java.util.List; + +public abstract class BaseRegexNode implements RegexNode { + + private String expression; + private List expressionFragments; + private boolean initialized; + + protected BaseRegexNode(String expression) throws RegexpIllegalException, TypeNotMatchException { + this(expression, true); + } + + protected BaseRegexNode(String expression, boolean initialize) throws RegexpIllegalException, TypeNotMatchException { + this.expression = expression; + this.expressionFragments = spliceExpression(expression); + if (initialize) { + init(); + } + } + + protected BaseRegexNode(List expressionFragments) throws RegexpIllegalException, TypeNotMatchException { + this(expressionFragments, true); + } + + protected BaseRegexNode(List expressionFragments, boolean initialize) + throws RegexpIllegalException, TypeNotMatchException { + this.expressionFragments = expressionFragments; + StringBuilder stringBuilder = new StringBuilder(); + for (String fragment : expressionFragments) { + stringBuilder.append(fragment); + } + this.expression = stringBuilder.toString(); + if (initialize) { + init(); + } + } + + @Override + public String random() throws UninitializedException, RegexpIllegalException { + if (!initialized) { + throw new UninitializedException(); + } + return random(expression, expressionFragments); + } + + @Override + public boolean isInitialized() { + return initialized; + } + + @Override + public boolean test() { + return test(expression, expressionFragments); + } + + @Override + public void init() throws RegexpIllegalException, TypeNotMatchException { + if (!initialized) { + if (!test()) { + throw new TypeNotMatchException(); + } + init(expression, expressionFragments); + initialized = true; + } + } + + @Override + public String getExpression() { + return expression; + } + + protected String random(String expression, List expressionFragments) + throws RegexpIllegalException, UninitializedException { + return null; + } + + protected void init(String expression, List expressionFragments) + throws RegexpIllegalException, TypeNotMatchException { + + } + + protected boolean test(String expression, List expressionFragments) { + return true; + } + + private List spliceExpression(String expression) throws RegexpIllegalException { + int l = 0; + int r = expression.length(); + List fragments = new ArrayList<>(); + while (true) { + String result = findFirst(expression, l, r); + if (result == null || result.isEmpty()) { + break; + } + fragments.add(result); + l += result.length(); + } + return fragments; + } + + private String findFirst(String expression, int l, int r) throws RegexpIllegalException { + if (l == r) { + return null; + } + if (expression.charAt(l) == '\\') { + if (l + 1 >= r) { + throw new RegexpIllegalException(expression, l + 1); + } + return expression.substring(l, l + 2); + } + if (expression.charAt(l) == '[') { + int i = l + 1; + while (i < r) { + if (expression.charAt(i) == ']') { + return expression.substring(l, i + 1); + } + if (expression.charAt(i) == '\\') { + i++; + } + i++; + } + throw new RegexpIllegalException(expression, r); + } + if (expression.charAt(l) == '{') { + int i = l + 1; + boolean hasDelimiter = false; + while (i < r) { + if (expression.charAt(i) == '}') { + return expression.substring(l, i + 1); + } + if (expression.charAt(i) == ',') { + if (hasDelimiter) { + throw new RegexpIllegalException(expression, i); + } + hasDelimiter = true; + i++; + continue; + } + if (expression.charAt(i) < '0' || expression.charAt(i) > '9') { + throw new RegexpIllegalException(expression, i); + } + i++; + } + throw new RegexpIllegalException(expression, r); + } + if (expression.charAt(l) == '(') { + int i = l + 1; + while (true) { + String result = findFirst(expression, i, r); + if (result == null || result.length() == 0 || result.length() + i >= r) { + throw new RegexpIllegalException(expression, i); + } + i += result.length(); + if (expression.charAt(i) == ')') { + return expression.substring(l, i + 1); + } + } + } + return expression.substring(l, l + 1); + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/LinkRegexNode.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/LinkRegexNode.java new file mode 100644 index 0000000..4e42472 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/LinkRegexNode.java @@ -0,0 +1,68 @@ +package com.sunyard.ssp.utils.regexp.model; + + + +import com.sunyard.ssp.utils.regexp.exception.RegexpIllegalException; +import com.sunyard.ssp.utils.regexp.exception.TypeNotMatchException; +import com.sunyard.ssp.utils.regexp.exception.UninitializedException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class LinkRegexNode extends BaseRegexNode { + + private List children; + + protected LinkRegexNode(List expressionFragments) throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments); + } + + protected LinkRegexNode(List expressionFragments, boolean initialize) + throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments, initialize); + } + + @Override + protected boolean test(String expression, List expressionFragments) { + for (String fragment : expressionFragments) { + if ("|".equals(fragment)) { + return false; + } + } + return true; + } + + @Override + protected void init(String expression, List expressionFragments) + throws RegexpIllegalException, TypeNotMatchException { + children = new ArrayList<>(); + for (int i = 0; i < expressionFragments.size(); i++) { + RegexNode regexNode; + if (i + 1 < expressionFragments.size()) { + regexNode = new RepeatRegexNode( + Arrays.asList(expressionFragments.get(i), expressionFragments.get(i + 1)), + false); + if (regexNode.test()) { + regexNode.init(); + children.add(regexNode); + i++; + continue; + } + } + regexNode = new SingleRegexNode(Collections.singletonList(expressionFragments.get(i))); + children.add(regexNode); + } + } + + @Override + protected String random(String expression, List expressionFragments) + throws RegexpIllegalException, UninitializedException { + StringBuilder value = new StringBuilder(); + for (RegexNode regexNode : children) { + value.append(regexNode.random()); + } + return value.toString(); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/OptionalRegexNode.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/OptionalRegexNode.java new file mode 100644 index 0000000..173dc69 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/OptionalRegexNode.java @@ -0,0 +1,55 @@ +package com.sunyard.ssp.utils.regexp.model; + +import com.sunyard.ssp.utils.regexp.exception.RegexpIllegalException; +import com.sunyard.ssp.utils.regexp.exception.TypeNotMatchException; +import com.sunyard.ssp.utils.regexp.exception.UninitializedException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class OptionalRegexNode extends BaseRegexNode { + + private List children; + + protected OptionalRegexNode(List expressionFragments) throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments); + } + + protected OptionalRegexNode(List expressionFragments, boolean initialize) + throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments, initialize); + } + + @Override + protected boolean test(String expression, List expressionFragments) { + for (String fragment : expressionFragments) { + if ("|".equals(fragment)) { + return true; + } + } + return false; + } + + @Override + protected void init(String expression, List expressionFragments) + throws RegexpIllegalException, TypeNotMatchException { + children = new ArrayList<>(); + List subFragments = new ArrayList<>(); + for (String fragment : expressionFragments) { + if ("|".equals(fragment)) { + children.add(new OrdinaryRegexNode(subFragments)); + subFragments = new ArrayList<>(); + continue; + } + subFragments.add(fragment); + } + children.add(new OrdinaryRegexNode(subFragments)); + } + + @Override + protected String random(String expression, List expressionFragments) + throws UninitializedException, RegexpIllegalException { + return children.get(new Random().nextInt(children.size())).random(); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/OrdinaryRegexNode.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/OrdinaryRegexNode.java new file mode 100644 index 0000000..7b6ff52 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/OrdinaryRegexNode.java @@ -0,0 +1,51 @@ +package com.sunyard.ssp.utils.regexp.model; + +import com.sunyard.ssp.utils.regexp.exception.RegexpIllegalException; +import com.sunyard.ssp.utils.regexp.exception.TypeNotMatchException; +import com.sunyard.ssp.utils.regexp.exception.UninitializedException; + +import java.util.List; + +public class OrdinaryRegexNode extends BaseRegexNode { + + private RegexNode proxyRegexNode; + + public OrdinaryRegexNode(String expression) throws RegexpIllegalException, TypeNotMatchException { + super(expression); + } + + protected OrdinaryRegexNode(List expressionFragments) throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments); + } + + @Override + protected void init(String expression, List expressionFragments) + throws RegexpIllegalException, TypeNotMatchException { + if (expressionFragments.size() == 0) { + return; + } + RegexNode[] regexNodes = new RegexNode[]{ + new OptionalRegexNode(expressionFragments, false), + new SingleRegexNode(expressionFragments, false), + new RepeatRegexNode(expressionFragments, false), + new LinkRegexNode(expressionFragments, false) + }; + for (RegexNode regexNode : regexNodes) { + if (regexNode.test()) { + proxyRegexNode = regexNode; + proxyRegexNode.init(); + break; + } + } + } + + @Override + protected String random(String expression, List expressionFragments) + throws UninitializedException, RegexpIllegalException { + if (proxyRegexNode == null) { + return ""; + } + return proxyRegexNode.random(); + } + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/RegexNode.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/RegexNode.java new file mode 100644 index 0000000..a0784ed --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/RegexNode.java @@ -0,0 +1,18 @@ +package com.sunyard.ssp.utils.regexp.model; + +import com.sunyard.ssp.utils.regexp.exception.RegexpIllegalException; +import com.sunyard.ssp.utils.regexp.exception.TypeNotMatchException; +import com.sunyard.ssp.utils.regexp.exception.UninitializedException; + +public interface RegexNode { + + String getExpression(); + + String random() throws UninitializedException, RegexpIllegalException; + + boolean test(); + + void init() throws RegexpIllegalException, TypeNotMatchException; + + boolean isInitialized(); +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/RepeatRegexNode.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/RepeatRegexNode.java new file mode 100644 index 0000000..9eaac98 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/RepeatRegexNode.java @@ -0,0 +1,73 @@ +package com.sunyard.ssp.utils.regexp.model; + +import com.sunyard.ssp.utils.regexp.exception.RegexpIllegalException; +import com.sunyard.ssp.utils.regexp.exception.TypeNotMatchException; +import com.sunyard.ssp.utils.regexp.exception.UninitializedException; + +import java.util.Collections; +import java.util.List; +import java.util.Random; + +public class RepeatRegexNode extends BaseRegexNode { + + private static final int MAX_REPEAT = 16; + + private RegexNode regexNode; + private int minRepeat = 1; + private int maxRepeat = 1; + + protected RepeatRegexNode(List expressionFragments) throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments); + } + + protected RepeatRegexNode(List expressionFragments, boolean initialize) + throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments, initialize); + } + + @Override + protected boolean test(String expression, List expressionFragments) { + if (expressionFragments.size() == 2) { + String token = expressionFragments.get(1); + return token != null + && ("+".equals(token) || "?".equals(token) || "*".equals(token) || token.startsWith("{")); + } + return false; + } + + @Override + protected void init(String expression, List expressionFragments) + throws RegexpIllegalException, TypeNotMatchException { + regexNode = new SingleRegexNode(Collections.singletonList(expressionFragments.get(0))); + String token = expressionFragments.get(1); + if ("+".equals(token)) { + maxRepeat = MAX_REPEAT; + } else if ("?".equals(token)) { + minRepeat = 0; + } else if ("*".equals(token)) { + minRepeat = 0; + maxRepeat = MAX_REPEAT; + } else if (token.startsWith("{")) { + String[] numbers = token.substring(1, token.length() - 1).split(",", 2); + minRepeat = maxRepeat = Integer.parseInt(numbers[0]); + if (numbers.length > 1) { + maxRepeat = numbers[1].isEmpty() ? Math.max(MAX_REPEAT, minRepeat) : Integer.parseInt(numbers[1]); + if (maxRepeat < minRepeat) { + throw new RegexpIllegalException("Invalid regular expression: " + + getExpression() + " : Numbers out of order in {} quantifier"); + } + } + } + } + + @Override + protected String random(String expression, List expressionFragments) + throws RegexpIllegalException, UninitializedException { + int repeat = new Random().nextInt(maxRepeat - minRepeat + 1) + minRepeat; + StringBuilder value = new StringBuilder(); + while (repeat-- > 0) { + value.append(regexNode.random()); + } + return value.toString(); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/SingleRegexNode.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/SingleRegexNode.java new file mode 100644 index 0000000..d23f668 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/regexp/model/SingleRegexNode.java @@ -0,0 +1,155 @@ +package com.sunyard.ssp.utils.regexp.model; + +import com.sunyard.ssp.utils.regexp.exception.RegexpIllegalException; +import com.sunyard.ssp.utils.regexp.exception.TypeNotMatchException; +import com.sunyard.ssp.utils.regexp.exception.UninitializedException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class SingleRegexNode extends BaseRegexNode { + + private RegexNode regexNode; + + private List intervals; + + protected SingleRegexNode(List expressionFragments) throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments); + } + + protected SingleRegexNode(List expressionFragments, boolean initialize) + throws RegexpIllegalException, TypeNotMatchException { + super(expressionFragments, initialize); + } + + + @Override + protected boolean test(String expression, List expressionFragments) { + return expressionFragments != null && expressionFragments.size() == 1; + } + + @Override + protected void init(String expression, List expressionFragments) + throws RegexpIllegalException, TypeNotMatchException { + if (expression.startsWith("(")) { + regexNode = new OrdinaryRegexNode(expression.substring(1, expression.length() - 1)); + return; + } + if (expression.startsWith("[")) { + int i = 1; + Character preChar = null; + while (i < expression.length() - 1) { + if (expression.charAt(i) == '\\') { + if (i + 1 >= expression.length() - 1) { + throw new RegexpIllegalException(expression, i); + } + if (preChar != null && "dws".contains(expression.charAt(i + 1) + "")) { + addIntervals(preChar, null, '-', null); + preChar = null; + } + if (expression.charAt(i + 1) == 'd') { + addIntervals('0', '9'); + } else if (expression.charAt(i + 1) == 'w') { + addIntervals('0', '9', 'A', 'Z', 'a', 'z', '_', null); + } else if (expression.charAt(i + 1) == 's') { + addIntervals(' ', null, '\t', null); + } else { + if (preChar != null) { + addIntervals(preChar, expression.charAt(i + 1)); + preChar = null; + } else if (i + 2 < expression.length() && expression.charAt(i + 2) == '-') { + preChar = expression.charAt(i + 1); + i++; + } else { + addIntervals(expression.charAt(i + 1), null); + } + } + i++; + } else if (preChar != null) { + addIntervals(preChar, expression.charAt(i)); + preChar = null; + } else if (i + 1 < expression.length() && expression.charAt(i + 1) == '-') { + preChar = expression.charAt(i); + i++; + } else { + addIntervals(expression.charAt(i), null); + } + i++; + } + if (preChar != null) { + addIntervals(preChar, null, '-', null); + } + } else if (".".equals(expression)) { + addIntervals( + (char) 0, (char) ('\n' - 1), + (char) ('\n' + 1), (char) ('\r' - 1), + (char) ('\r' + 1), (char) 255); + } else if ("\\s".equals(expression)) { + addIntervals(' ', null, '\t', null); + } else if ("\\d".equals(expression)) { + addIntervals('0', '9'); + } else if ("\\w".equals(expression)) { + addIntervals('0', '9', 'A', 'Z', 'a', 'z', '_', null); + } else if (expression.startsWith("\\")) { + addIntervals(expression.charAt(1), null); + } + } + + @Override + protected String random(String expression, List expressionFragments) + throws RegexpIllegalException, UninitializedException { + if (regexNode != null) { + return regexNode.random(); + } + if (intervals != null && intervals.size() > 0) { + Character value = randomCharFromInterval(intervals.toArray(new Interval[0])); + return value == null ? "" : value.toString(); + } + return expression; + } + + private Character randomCharFromInterval(Interval... intervals) { + int count = 0; + for (Interval interval : intervals) { + count += interval.end + 1 - interval.start; + } + int randomValue = new Random().nextInt(count); + for (Interval interval : intervals) { + if (randomValue < interval.end + 1 - interval.start) { + return (char) (interval.start + randomValue); + } + randomValue -= interval.end + 1 - interval.start; + } + return null; + } + + private void addIntervals(Character... chars) throws RegexpIllegalException { + if (intervals == null) { + intervals = new ArrayList<>(); + } + for (int i = 0; i + 1 < chars.length; i += 2) { + Character start = chars[i]; + Character end = chars[i + 1] == null ? start : chars[i + 1]; + if (start == null) { + throw new RegexpIllegalException("Invalid regular expression: " + + getExpression() + " : Character class is null"); + } + if (end < start) { + throw new RegexpIllegalException("Invalid regular expression: " + + getExpression() + " : Range out of order in character class"); + } + intervals.add(new Interval(start, end)); + } + } + + private static class Interval { + private char start; + private char end; + + private Interval(char start, char end) { + this.start = start; + this.end = end; + } + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/BCECUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/BCECUtil.java new file mode 100644 index 0000000..e1c7b5e --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/BCECUtil.java @@ -0,0 +1,500 @@ +package com.sunyard.ssp.utils.sm2; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.asn1.x9.X962Parameters; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.asn1.x9.X9ECPoint; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.generators.ECKeyPairGenerator; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECKeyGenerationParameters; +import org.bouncycastle.crypto.params.ECKeyParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; +import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; +import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemReader; +import org.bouncycastle.util.io.pem.PemWriter; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +/** + * 这个工具类的方法,也适用于其他基于BC库的ECC算法 + */ +public class BCECUtil { + private static final String ALGO_NAME_EC = "EC"; + private static final String PEM_STRING_PUBLIC = "PUBLIC KEY"; + private static final String PEM_STRING_ECPRIVATEKEY = "EC PRIVATE KEY"; + + /** + * 生成ECC密钥对 + * + * @return ECC密钥对 + */ + public static AsymmetricCipherKeyPair generateKeyPairParameter( + ECDomainParameters domainParameters, SecureRandom random) { + ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(domainParameters, + random); + ECKeyPairGenerator keyGen = new ECKeyPairGenerator(); + keyGen.init(keyGenerationParams); + return keyGen.generateKeyPair(); + } + + public static KeyPair generateKeyPair(ECDomainParameters domainParameters, SecureRandom random) + throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME); + ECParameterSpec parameterSpec = new ECParameterSpec(domainParameters.getCurve(), domainParameters.getG(), + domainParameters.getN(), domainParameters.getH()); + kpg.initialize(parameterSpec, random); + return kpg.generateKeyPair(); + } + + public static int getCurveLength(ECKeyParameters ecKey) { + return getCurveLength(ecKey.getParameters()); + } + + public static int getCurveLength(ECDomainParameters domainParams) { + return (domainParams.getCurve().getFieldSize() + 7) / 8; + } + + public static byte[] fixToCurveLengthBytes(int curveLength, byte[] src) { + if (src.length == curveLength) { + return src; + } + + byte[] result = new byte[curveLength]; + if (src.length > curveLength) { + System.arraycopy(src, src.length - result.length, result, 0, result.length); + } else { + System.arraycopy(src, 0, result, result.length - src.length, src.length); + } + return result; + } + + /** + * @param dHex 十六进制字符串形式的私钥d值,如果是SM2算法,Hex字符串长度应该是64(即32字节) + * @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS} + * @return + */ + public static ECPrivateKeyParameters createECPrivateKeyParameters( + String dHex, ECDomainParameters domainParameters) { + return createECPrivateKeyParameters(ByteUtils.fromHexString(dHex), domainParameters); + } + + /** + * @param dBytes 字节数组形式的私钥d值,如果是SM2算法,应该是32字节 + * @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS} + * @return + */ + public static ECPrivateKeyParameters createECPrivateKeyParameters( + byte[] dBytes, ECDomainParameters domainParameters) { + return createECPrivateKeyParameters(new BigInteger(1, dBytes), domainParameters); + } + + /** + * @param d 大数形式的私钥d值 + * @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS} + * @return + */ + public static ECPrivateKeyParameters createECPrivateKeyParameters( + BigInteger d, ECDomainParameters domainParameters) { + return new ECPrivateKeyParameters(d, domainParameters); + } + + /** + * @param x 大数形式的公钥x分量 + * @param y 大数形式的公钥y分量 + * @param curve EC曲线参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#CURVE} + * @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS} + * @return + */ + public static ECPublicKeyParameters createECPublicKeyParameters( + BigInteger x, BigInteger y, ECCurve curve, ECDomainParameters domainParameters) { + return createECPublicKeyParameters(x.toByteArray(), y.toByteArray(), curve, domainParameters); + } + + /** + * @param xHex 十六进制形式的公钥x分量,如果是SM2算法,Hex字符串长度应该是64(即32字节) + * @param yHex 十六进制形式的公钥y分量,如果是SM2算法,Hex字符串长度应该是64(即32字节) + * @param curve EC曲线参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#CURVE} + * @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS} + * @return + */ + public static ECPublicKeyParameters createECPublicKeyParameters( + String xHex, String yHex, ECCurve curve, ECDomainParameters domainParameters) { + return createECPublicKeyParameters(ByteUtils.fromHexString(xHex), ByteUtils.fromHexString(yHex), + curve, domainParameters); + } + + /** + * @param xBytes 十六进制形式的公钥x分量,如果是SM2算法,应该是32字节 + * @param yBytes 十六进制形式的公钥y分量,如果是SM2算法,应该是32字节 + * @param curve EC曲线参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#CURVE} + * @param domainParameters EC Domain参数,一般是固定的,如果是SM2算法的可参考{@link SM2Util#DOMAIN_PARAMS} + * @return + */ + public static ECPublicKeyParameters createECPublicKeyParameters( + byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters) { + final byte uncompressedFlag = 0x04; + int curveLength = getCurveLength(domainParameters); + xBytes = fixToCurveLengthBytes(curveLength, xBytes); + yBytes = fixToCurveLengthBytes(curveLength, yBytes); + byte[] encodedPubKey = new byte[1 + xBytes.length + yBytes.length]; + encodedPubKey[0] = uncompressedFlag; + System.arraycopy(xBytes, 0, encodedPubKey, 1, xBytes.length); + System.arraycopy(yBytes, 0, encodedPubKey, 1 + xBytes.length, yBytes.length); + return new ECPublicKeyParameters(curve.decodePoint(encodedPubKey), domainParameters); + } + + public static ECPrivateKeyParameters convertPrivateKeyToParameters(BCECPrivateKey ecPriKey) { + ECParameterSpec parameterSpec = ecPriKey.getParameters(); + ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), + parameterSpec.getN(), parameterSpec.getH()); + return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters); + } + + public static ECPublicKeyParameters convertPublicKeyToParameters(BCECPublicKey ecPubKey) { + ECParameterSpec parameterSpec = ecPubKey.getParameters(); + ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), + parameterSpec.getN(), parameterSpec.getH()); + return new ECPublicKeyParameters(ecPubKey.getQ(), domainParameters); + } + + public static BCECPublicKey createPublicKeyFromSubjectPublicKeyInfo(SubjectPublicKeyInfo subPubInfo) + throws NoSuchProviderException, + NoSuchAlgorithmException, InvalidKeySpecException, IOException { + return BCECUtil.convertX509ToECPublicKey(subPubInfo.toASN1Primitive().getEncoded(ASN1Encoding.DER)); + } + + /** + * 将ECC私钥转换为PKCS8标准的字节流 + * + * @param priKey + * @param pubKey 可以为空,但是如果为空的话得到的结果OpenSSL可能解析不了 + * @return + */ + public static byte[] convertECPrivateKeyToPKCS8( + ECPrivateKeyParameters priKey, ECPublicKeyParameters pubKey) { + ECDomainParameters domainParams = priKey.getParameters(); + ECParameterSpec spec = new ECParameterSpec(domainParams.getCurve(), domainParams.getG(), + domainParams.getN(), domainParams.getH()); + BCECPublicKey publicKey = null; + if (pubKey != null) { + publicKey = new BCECPublicKey(ALGO_NAME_EC, pubKey, spec, + BouncyCastleProvider.CONFIGURATION); + } + BCECPrivateKey privateKey = new BCECPrivateKey(ALGO_NAME_EC, priKey, publicKey, + spec, BouncyCastleProvider.CONFIGURATION); + return privateKey.getEncoded(); + } + + /** + * 将PKCS8标准的私钥字节流转换为私钥对象 + * + * @param pkcs8Key + * @return + * @throws NoSuchAlgorithmException + * @throws NoSuchProviderException + * @throws InvalidKeySpecException + */ + public static BCECPrivateKey convertPKCS8ToECPrivateKey(byte[] pkcs8Key) + throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { + PKCS8EncodedKeySpec peks = new PKCS8EncodedKeySpec(pkcs8Key); + KeyFactory kf = KeyFactory.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME); + return (BCECPrivateKey) kf.generatePrivate(peks); + } + + /** + * 将PKCS8标准的私钥字节流转换为PEM + * + * @param encodedKey + * @return + * @throws IOException + */ + public static String convertECPrivateKeyPKCS8ToPEM(byte[] encodedKey) throws IOException { + return convertEncodedDataToPEM(PEM_STRING_ECPRIVATEKEY, encodedKey); + } + + /** + * 将PEM格式的私钥转换为PKCS8标准字节流 + * + * @param pemString + * @return + * @throws IOException + */ + public static byte[] convertECPrivateKeyPEMToPKCS8(String pemString) throws IOException { + return convertPEMToEncodedData(pemString); + } + + /** + * 将ECC私钥转换为SEC1标准的字节流 + * openssl d2i_ECPrivateKey函数要求的DER编码的私钥也是SEC1标准的, + * 这个工具函数的主要目的就是为了能生成一个openssl可以直接“识别”的ECC私钥. + * 相对RSA私钥的PKCS1标准,ECC私钥的标准为SEC1 + * + * @param priKey + * @param pubKey + * @return + * @throws IOException + */ + public static byte[] convertECPrivateKeyToSEC1( + ECPrivateKeyParameters priKey, ECPublicKeyParameters pubKey) throws IOException { + byte[] pkcs8Bytes = convertECPrivateKeyToPKCS8(priKey, pubKey); + PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pkcs8Bytes); + ASN1Encodable encodable = pki.parsePrivateKey(); + ASN1Primitive primitive = encodable.toASN1Primitive(); + byte[] sec1Bytes = primitive.getEncoded(); + return sec1Bytes; + } + + /** + * 将SEC1标准的私钥字节流恢复为PKCS8标准的字节流 + * + * @param sec1Key + * @return + * @throws IOException + */ + public static byte[] convertECPrivateKeySEC1ToPKCS8(byte[] sec1Key) throws IOException { + /** + * 参考org.bouncycastle.asn1.pkcs.PrivateKeyInfo和 + * org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey,逆向拼装 + */ + X962Parameters params = getDomainParametersFromName(SM2Util.JDK_EC_SPEC, false); + ASN1OctetString privKey = new DEROctetString(sec1Key); + ASN1EncodableVector v = new ASN1EncodableVector(); + v.add(new ASN1Integer(0)); //版本号 + v.add(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params)); //算法标识 + v.add(privKey); + DERSequence ds = new DERSequence(v); + return ds.getEncoded(ASN1Encoding.DER); + } + + /** + * 将SEC1标准的私钥字节流转为BCECPrivateKey对象 + * + * @param sec1Key + * @return + * @throws NoSuchAlgorithmException + * @throws NoSuchProviderException + * @throws InvalidKeySpecException + * @throws IOException + */ + public static BCECPrivateKey convertSEC1ToBCECPrivateKey(byte[] sec1Key) + throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException { + PKCS8EncodedKeySpec peks = new PKCS8EncodedKeySpec(convertECPrivateKeySEC1ToPKCS8(sec1Key)); + KeyFactory kf = KeyFactory.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME); + return (BCECPrivateKey) kf.generatePrivate(peks); + } + + /** + * 将SEC1标准的私钥字节流转为ECPrivateKeyParameters对象 + * openssl i2d_ECPrivateKey函数生成的DER编码的ecc私钥是:SEC1标准的、带有EC_GROUP、带有公钥的, + * 这个工具函数的主要目的就是为了使Java程序能够“识别”openssl生成的ECC私钥 + * + * @param sec1Key + * @return + * @throws NoSuchAlgorithmException + * @throws NoSuchProviderException + * @throws InvalidKeySpecException + */ + public static ECPrivateKeyParameters convertSEC1ToECPrivateKey(byte[] sec1Key) + throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException { + BCECPrivateKey privateKey = convertSEC1ToBCECPrivateKey(sec1Key); + return convertPrivateKeyToParameters(privateKey); + } + + /** + * 将ECC公钥对象转换为X509标准的字节流 + * + * @param pubKey + * @return + */ + public static byte[] convertECPublicKeyToX509(ECPublicKeyParameters pubKey) { + ECDomainParameters domainParams = pubKey.getParameters(); + ECParameterSpec spec = new ECParameterSpec(domainParams.getCurve(), domainParams.getG(), + domainParams.getN(), domainParams.getH()); + BCECPublicKey publicKey = new BCECPublicKey(ALGO_NAME_EC, pubKey, spec, + BouncyCastleProvider.CONFIGURATION); + return publicKey.getEncoded(); + } + + /** + * 将X509标准的公钥字节流转为公钥对象 + * + * @param x509Bytes + * @return + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + * @throws InvalidKeySpecException + */ + public static BCECPublicKey convertX509ToECPublicKey(byte[] x509Bytes) throws NoSuchProviderException, + NoSuchAlgorithmException, InvalidKeySpecException { + X509EncodedKeySpec eks = new X509EncodedKeySpec(x509Bytes); + KeyFactory kf = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME); + return (BCECPublicKey) kf.generatePublic(eks); + } + + /** + * 将X509标准的公钥字节流转为PEM + * + * @param encodedKey + * @return + * @throws IOException + */ + public static String convertECPublicKeyX509ToPEM(byte[] encodedKey) throws IOException { + return convertEncodedDataToPEM(PEM_STRING_PUBLIC, encodedKey); + } + + /** + * 将PEM格式的公钥转为X509标准的字节流 + * + * @param pemString + * @return + * @throws IOException + */ + public static byte[] convertECPublicKeyPEMToX509(String pemString) throws IOException { + return convertPEMToEncodedData(pemString); + } + + /** + * copy from BC + * + * @param genSpec + * @return + */ + public static X9ECParameters getDomainParametersFromGenSpec(ECGenParameterSpec genSpec) { + return getDomainParametersFromName(genSpec.getName()); + } + + /** + * copy from BC + * + * @param curveName + * @return + */ + public static X9ECParameters getDomainParametersFromName(String curveName) { + X9ECParameters domainParameters; + try { + if (curveName.charAt(0) >= '0' && curveName.charAt(0) <= '2') { + ASN1ObjectIdentifier oidID = new ASN1ObjectIdentifier(curveName); + domainParameters = ECUtil.getNamedCurveByOid(oidID); + } else { + if (curveName.indexOf(' ') > 0) { + curveName = curveName.substring(curveName.indexOf(' ') + 1); + domainParameters = ECUtil.getNamedCurveByName(curveName); + } else { + domainParameters = ECUtil.getNamedCurveByName(curveName); + } + } + } catch (IllegalArgumentException ex) { + domainParameters = ECUtil.getNamedCurveByName(curveName); + } + return domainParameters; + } + + /** + * copy from BC + * + * @param ecSpec + * @param withCompression + * @return + */ + public static X962Parameters getDomainParametersFromName( + java.security.spec.ECParameterSpec ecSpec, boolean withCompression) { + X962Parameters params; + + if (ecSpec instanceof ECNamedCurveSpec) { + ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec) ecSpec).getName()); + if (curveOid == null) { + curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec) ecSpec).getName()); + } + params = new X962Parameters(curveOid); + } else if (ecSpec == null) { + params = new X962Parameters(DERNull.INSTANCE); + } else { + ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); + + X9ECParameters ecP = new X9ECParameters( + curve, + new X9ECPoint(EC5Util.convertPoint(curve, ecSpec.getGenerator()), withCompression), + ecSpec.getOrder(), + BigInteger.valueOf(ecSpec.getCofactor()), + ecSpec.getCurve().getSeed()); + + //// 如果是1.62或更低版本的bcprov-jdk15on应该使用以下这段代码,因为高版本的EC5Util.convertPoint没有向下兼容 + /* + X9ECParameters ecP = new X9ECParameters( + curve, + EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), + ecSpec.getOrder(), + BigInteger.valueOf(ecSpec.getCofactor()), + ecSpec.getCurve().getSeed()); + */ + + params = new X962Parameters(ecP); + } + + return params; + } + + private static String convertEncodedDataToPEM(String type, byte[] encodedData) throws IOException { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + PemWriter pWrt = new PemWriter(new OutputStreamWriter(bOut)); + try { + PemObject pemObj = new PemObject(type, encodedData); + pWrt.writeObject(pemObj); + } finally { + pWrt.close(); + } + return new String(bOut.toByteArray()); + } + + private static byte[] convertPEMToEncodedData(String pemString) throws IOException { + ByteArrayInputStream bIn = new ByteArrayInputStream(pemString.getBytes()); + PemReader pRdr = new PemReader(new InputStreamReader(bIn)); + try { + PemObject pemObject = pRdr.readPemObject(); + return pemObject.getContent(); + } finally { + pRdr.close(); + } + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/GMBaseUtil.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/GMBaseUtil.java new file mode 100644 index 0000000..6574413 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/GMBaseUtil.java @@ -0,0 +1,11 @@ +package com.sunyard.ssp.utils.sm2; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.security.Security; + +public class GMBaseUtil { + static { + Security.addProvider(new BouncyCastleProvider()); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/SM2Util.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/SM2Util.java new file mode 100644 index 0000000..eba95e7 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm2/SM2Util.java @@ -0,0 +1,593 @@ +package com.sunyard.ssp.utils.sm2; + +import cn.hutool.core.util.ReflectUtil; +import com.sunyard.ssp.BytesUtil; +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.CryptoException; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.engines.SM2Engine; +import org.bouncycastle.crypto.engines.SM2Engine.Mode; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.crypto.params.ParametersWithID; +import org.bouncycastle.crypto.params.ParametersWithRandom; +import org.bouncycastle.crypto.signers.SM2Signer; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; +import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.EllipticCurve; +import java.util.Base64; + +@Slf4j +public class SM2Util extends GMBaseUtil { + ////////////////////////////////////////////////////////////////////////////////////// + /* + * 以下为SM2推荐曲线参数 + */ + public static final SM2P256V1Curve CURVE = new SM2P256V1Curve(); + public final static BigInteger SM2_ECC_P = CURVE.getQ(); + public final static BigInteger SM2_ECC_A = CURVE.getA().toBigInteger(); + public final static BigInteger SM2_ECC_B = CURVE.getB().toBigInteger(); + public final static BigInteger SM2_ECC_N = CURVE.getOrder(); + public final static BigInteger SM2_ECC_H = CURVE.getCofactor(); + public final static BigInteger SM2_ECC_GX = new BigInteger( + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16); + public final static BigInteger SM2_ECC_GY = new BigInteger( + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16); + public static final ECPoint G_POINT = CURVE.createPoint(SM2_ECC_GX, SM2_ECC_GY); + public static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G_POINT, + SM2_ECC_N, SM2_ECC_H); + public static final int CURVE_LEN = BCECUtil.getCurveLength(DOMAIN_PARAMS); + ////////////////////////////////////////////////////////////////////////////////////// + + public static final EllipticCurve JDK_CURVE = new EllipticCurve(new ECFieldFp(SM2_ECC_P), SM2_ECC_A, SM2_ECC_B); + public static final java.security.spec.ECPoint JDK_G_POINT = new java.security.spec.ECPoint( + G_POINT.getAffineXCoord().toBigInteger(), G_POINT.getAffineYCoord().toBigInteger()); + public static final ECParameterSpec JDK_EC_SPEC = new ECParameterSpec( + JDK_CURVE, JDK_G_POINT, SM2_ECC_N, SM2_ECC_H.intValue()); + + ////////////////////////////////////////////////////////////////////////////////////// + + public static final int SM3_DIGEST_LENGTH = 32; + + + private static final String PK_MARK_HEAD = "-----BEGIN ECDSA PUBLIC KEY-----"; + private static final String PK_MARK_TAIL = "-----END ECDSA PUBLIC KEY-----"; + + public static boolean verifyByPk(String data,String pk,String sign ) { +// String data = "592B5E2D7AFEF43552D02A4630A78BBA316A13D0D0C341C595004B2B5CFB25BA11-----BEGIN ECDSA PUBLIC KEY-----MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEAxNwJKcYPJNzAexpc1a5HdpMP1TlZHcja/kAlbq0fSC5m/efIlH28IfV79MFds9yNajGOJffqG2ngIIuRaOooQ==-----END ECDSA PUBLIC KEY-----"; +// String pk = "-----BEGIN ECDSA PUBLIC KEY-----MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEAxNwJKcYPJNzAexpc1a5HdpMP1TlZHcja/kAlbq0fSC5m/efIlH28IfV79MFds9yNajGOJffqG2ngIIuRaOooQ==-----END ECDSA PUBLIC KEY-----"; +// String sign = "MEUCIQDy+6Ge95Pv5qQWeO8/ooQB5vLp+cEP3KnyvRz3gvGS2wIgWuWZGI42NH1o0Ti2QhJTwAdNnNwvbbxBDwqt7ECtRfQ="; + + if (pk.startsWith(PK_MARK_HEAD) && pk.endsWith(PK_MARK_TAIL)) { + pk = pk.substring(PK_MARK_HEAD.length(), pk.length() - PK_MARK_TAIL.length()); + pk = pk.trim(); + } + + // 3059301306072A8648CE3D020106082A811CCF5501822D03420004EB1F1EC734D710C016B171C4A0DC5418BD9AE89EEFE8DA7C36D7192B40F8CF9B80EFF7D62F98A9D84BF910B85AD8F2F19D8DC1EE61458A01B7FB21C1850C7290 +// System.out.println(pk); + + + // EB1F1EC734D710C016B171C4A0DC5418BD9AE89EEFE8DA7C36D7192B40F8CF9B80EFF7D62F98A9D84BF910B85AD8F2F19D8DC1EE61458A01B7FB21C1850C7290 + byte[] pkHex = Base64.getDecoder().decode(pk.getBytes(StandardCharsets.UTF_8)); + String pkDer = com.sunyard.ssp.util.BytesUtil.bytes2HexString(pkHex); + pkDer = pkDer.substring(pkDer.indexOf("03420004") + 8); + String xHex = pkDer.substring(0, 64); + String yHex = pkDer.substring(64); + +// System.out.println("x=" + xHex); +// System.out.println("y=" + yHex); + ECPublicKeyParameters pubKey = BCECUtil.createECPublicKeyParameters(xHex, yHex, SM2Util.CURVE, SM2Util.DOMAIN_PARAMS); + + + byte[] s = com.sunyard.ssp.util.BytesUtil.decodeBase64( sign ); + log.info( com.sunyard.ssp.util.BytesUtil.bytes2HexString( s ) ); + + + byte[] d = data.getBytes(); + log.info("data=" + com.sunyard.ssp.util.BytesUtil.bytes2HexString(d) ); + + return SM2Util.verify(pubKey, data.getBytes(), s); + + } + + + /** + * 生成ECC密钥对 + * + * @return ECC密钥对 + */ + public static AsymmetricCipherKeyPair generateKeyPairParameter() { + SecureRandom random = new SecureRandom(); + return BCECUtil.generateKeyPairParameter(DOMAIN_PARAMS, random); + } + + /** + * 生成ECC密钥对 + * + * @return + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + * @throws InvalidAlgorithmParameterException + */ + public static KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + SecureRandom random = new SecureRandom(); + return BCECUtil.generateKeyPair(DOMAIN_PARAMS, random); + } + + /** + * 只获取私钥里的d值,32字节 + * + * @param privateKey + * @return + */ + public static byte[] getRawPrivateKey(BCECPrivateKey privateKey) { + return fixToCurveLengthBytes(privateKey.getD().toByteArray()); + } + + /** + * 只获取公钥里的XY分量,64字节 + * + * @param publicKey + * @return 64字节数组 + */ + public static byte[] getRawPublicKey(BCECPublicKey publicKey) { + byte[] src65 = publicKey.getQ().getEncoded(false); + byte[] rawXY = new byte[CURVE_LEN * 2];//SM2的话这里应该是64字节 + System.arraycopy(src65, 1, rawXY, 0, rawXY.length); + return rawXY; + } + + /** + * @param pubKey 公钥 + * @param srcData 原文 + * @return 默认输出C1C3C2顺序的密文。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @throws InvalidCipherTextException + */ + public static byte[] encrypt(BCECPublicKey pubKey, byte[] srcData) throws InvalidCipherTextException { + ECPublicKeyParameters pubKeyParameters = BCECUtil.convertPublicKeyToParameters(pubKey); + return encrypt(Mode.C1C3C2, pubKeyParameters, srcData); + } + + /** + * @param mode 指定密文结构,旧标准的为C1C2C3,新的[《SM2密码算法使用规范》 GM/T 0009-2012]标准为C1C3C2 + * @param pubKey 公钥 + * @param srcData 原文 + * @return 根据mode不同,输出的密文C1C2C3排列顺序不同。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @throws InvalidCipherTextException + */ + public static byte[] encrypt(Mode mode, BCECPublicKey pubKey, byte[] srcData) throws InvalidCipherTextException { + ECPublicKeyParameters pubKeyParameters = BCECUtil.convertPublicKeyToParameters(pubKey); + return encrypt(mode, pubKeyParameters, srcData); + } + + /** + * @param pubKeyParameters 公钥 + * @param srcData 原文 + * @return 默认输出C1C3C2顺序的密文。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @throws InvalidCipherTextException + */ + public static byte[] encrypt(ECPublicKeyParameters pubKeyParameters, byte[] srcData) + throws InvalidCipherTextException { + return encrypt(Mode.C1C3C2, pubKeyParameters, srcData); + } + + /** + * @param mode 指定密文结构,旧标准的为C1C2C3,新的[《SM2密码算法使用规范》 GM/T 0009-2012]标准为C1C3C2 + * @param pubKeyParameters 公钥 + * @param srcData 原文 + * @return 根据mode不同,输出的密文C1C2C3排列顺序不同。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @throws InvalidCipherTextException + */ + public static byte[] encrypt(Mode mode, ECPublicKeyParameters pubKeyParameters, byte[] srcData) + throws InvalidCipherTextException { + SM2Engine engine = new SM2Engine(mode); + ParametersWithRandom pwr = new ParametersWithRandom(pubKeyParameters, new SecureRandom()); + engine.init(true, pwr); + return engine.processBlock(srcData, 0, srcData.length); + } + + /** + * @param priKey 私钥 + * @param sm2Cipher 默认输入C1C3C2顺序的密文。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @return 原文。SM2解密返回了数据则一定是原文,因为SM2自带校验,如果密文被篡改或者密钥对不上,都是会直接报异常的。 + * @throws InvalidCipherTextException + */ + public static byte[] decrypt(BCECPrivateKey priKey, byte[] sm2Cipher) throws InvalidCipherTextException { + ECPrivateKeyParameters priKeyParameters = BCECUtil.convertPrivateKeyToParameters(priKey); + return decrypt(Mode.C1C3C2, priKeyParameters, sm2Cipher); + } + + /** + * @param mode 指定密文结构,旧标准的为C1C2C3,新的[《SM2密码算法使用规范》 GM/T 0009-2012]标准为C1C3C2 + * @param priKey 私钥 + * @param sm2Cipher 根据mode不同,需要输入的密文C1C2C3排列顺序不同。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @return 原文。SM2解密返回了数据则一定是原文,因为SM2自带校验,如果密文被篡改或者密钥对不上,都是会直接报异常的。 + * @throws InvalidCipherTextException + */ + public static byte[] decrypt(Mode mode, BCECPrivateKey priKey, byte[] sm2Cipher) throws InvalidCipherTextException { + ECPrivateKeyParameters priKeyParameters = BCECUtil.convertPrivateKeyToParameters(priKey); + return decrypt(mode, priKeyParameters, sm2Cipher); + } + + /** + * @param priKeyParameters 私钥 + * @param sm2Cipher 默认输入C1C3C2顺序的密文。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @return 原文。SM2解密返回了数据则一定是原文,因为SM2自带校验,如果密文被篡改或者密钥对不上,都是会直接报异常的。 + * @throws InvalidCipherTextException + */ + public static byte[] decrypt(ECPrivateKeyParameters priKeyParameters, byte[] sm2Cipher) + throws InvalidCipherTextException { + return decrypt(Mode.C1C3C2, priKeyParameters, sm2Cipher); + } + + /** + * @param mode 指定密文结构,旧标准的为C1C2C3,新的[《SM2密码算法使用规范》 GM/T 0009-2012]标准为C1C3C2 + * @param priKeyParameters 私钥 + * @param sm2Cipher 根据mode不同d,需要输入的密文C1C2C3排列顺序不同。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @return 原文dddd。SM2解密返回了数据则一定是原文,因为SM2自带校验,如果密文被篡改或者密钥对不上,都是会直接报异常的。 + * @throws InvalidCipherTextException + */ + public static byte[] decrypt(Mode mode, ECPrivateKeyParameters priKeyParameters, byte[] sm2Cipher) + throws InvalidCipherTextException { + SM2Engine engine = new SM2Engine(mode); + engine.init(false, priKeyParameters); + return engine.processBlock(sm2Cipher, 0, sm2Cipher.length); + } + + + /** + * DER编码密文 + * + * @param cipher 默认输入C1C3C2顺序的密文。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @return DER编码后的密文 + * @throws IOException + */ + public static byte[] encodeSM2CipherToDER(byte[] cipher) throws Exception { + int curveLength = BCECUtil.getCurveLength(DOMAIN_PARAMS); + return encodeSM2CipherToDER(Mode.C1C3C2, curveLength, SM3_DIGEST_LENGTH, cipher); + } + + /** + * DER编码密文 + * + * @param mode 指定密文结构,旧标准的为C1C2C3,新的[《SM2密码算法使用规范》 GM/T 0009-2012]标准为C1C3C2 + * @param cipher 根据mode不同,需要输入的密文C1C2C3排列顺序不同。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @return 按指定mode DER编码后的密文 + * @throws Exception + */ + public static byte[] encodeSM2CipherToDER(Mode mode, byte[] cipher) throws Exception { + int curveLength = BCECUtil.getCurveLength(DOMAIN_PARAMS); + return encodeSM2CipherToDER(mode, curveLength, SM3_DIGEST_LENGTH, cipher); + } + + /** + * DER编码密文 + * + * @param curveLength 曲线长度,SM2的话就是256位。 + * @param digestLength 摘要长度,如果是SM2的话因为默认使用SM3摘要,SM3摘要长度为32字节。 + * @param cipher 默认输入C1C3C2顺序的密文。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @return 默认输出按C1C3C2编码的结果 + * @throws IOException + */ + public static byte[] encodeSM2CipherToDER(int curveLength, int digestLength, byte[] cipher) + throws Exception { + return encodeSM2CipherToDER(Mode.C1C3C2, curveLength, digestLength, cipher); + } + + /** + * @param mode 指定密文结构,旧标准的为C1C2C3,新的[《SM2密码算法使用规范》 GM/T 0009-2012]标准为C1C3C2 + * @param curveLength 曲线长度,SM2的话就是256位。 + * @param digestLength 摘要长度,如果是SM2的话因为默认使用SM3摘要,SM3摘要长度为32字节。 + * @param cipher 根据mode不同,需要输入的密文C1C2C3排列顺序不同。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @return 按指定mode DER编码后的密文 + * @throws Exception + */ + public static byte[] encodeSM2CipherToDER(Mode mode, int curveLength, int digestLength, byte[] cipher) + throws Exception { + + byte[] c1x = new byte[curveLength]; + byte[] c1y = new byte[curveLength]; + byte[] c2 = new byte[cipher.length - c1x.length - c1y.length - 1 - digestLength]; + byte[] c3 = new byte[digestLength]; + + int startPos = 1; + System.arraycopy(cipher, startPos, c1x, 0, c1x.length); + startPos += c1x.length; + System.arraycopy(cipher, startPos, c1y, 0, c1y.length); + startPos += c1y.length; + if (mode == Mode.C1C2C3) { + System.arraycopy(cipher, startPos, c2, 0, c2.length); + startPos += c2.length; + System.arraycopy(cipher, startPos, c3, 0, c3.length); + } else if (mode == Mode.C1C3C2) { + System.arraycopy(cipher, startPos, c3, 0, c3.length); + startPos += c3.length; + System.arraycopy(cipher, startPos, c2, 0, c2.length); + } else { + throw new Exception("Unsupported mode:" + mode); + } + + ASN1Encodable[] arr = new ASN1Encodable[4]; + arr[0] = new ASN1Integer(c1x); + arr[1] = new ASN1Integer(c1y); + if (mode == Mode.C1C2C3) { + arr[2] = new DEROctetString(c2); + arr[3] = new DEROctetString(c3); + } else if (mode == Mode.C1C3C2) { + arr[2] = new DEROctetString(c3); + arr[3] = new DEROctetString(c2); + } + DERSequence ds = new DERSequence(arr); + return ds.getEncoded(ASN1Encoding.DER); + } + + /** + * 解码DER密文 + * + * @param derCipher 默认输入按C1C3C2顺序DER编码的密文 + * @return 输出按C1C3C2排列的字节数组,C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + */ + public static byte[] decodeDERSM2Cipher(byte[] derCipher) throws Exception { + return decodeDERSM2Cipher(Mode.C1C3C2, derCipher); + } + + /** + * @param mode 指定密文结构,旧标准的为C1C2C3,新的[《SM2密码算法使用规范》 GM/T 0009-2012]标准为C1C3C2 + * @param derCipher 根据mode输入C1C2C3或C1C3C2顺序DER编码后的密文 + * @return 根据mode不同,输出的密文C1C2C3排列顺序不同。C1为65字节第1字节为压缩标识,这里固定为0x04,后面64字节为xy分量各32字节。C3为32字节。C2长度与原文一致。 + * @throws Exception + */ + public static byte[] decodeDERSM2Cipher(Mode mode, byte[] derCipher) throws Exception { + ASN1Sequence as = DERSequence.getInstance(derCipher); + byte[] c1x = ((ASN1Integer) as.getObjectAt(0)).getValue().toByteArray(); + byte[] c1y = ((ASN1Integer) as.getObjectAt(1)).getValue().toByteArray(); + byte[] c3; + byte[] c2; + if (mode == Mode.C1C2C3) { + c2 = ((DEROctetString) as.getObjectAt(2)).getOctets(); + c3 = ((DEROctetString) as.getObjectAt(3)).getOctets(); + } else if (mode == Mode.C1C3C2) { + c3 = ((DEROctetString) as.getObjectAt(2)).getOctets(); + c2 = ((DEROctetString) as.getObjectAt(3)).getOctets(); + } else { + throw new Exception("Unsupported mode:" + mode); + } + + int pos = 0; + byte[] cipherText = new byte[1 + c1x.length + c1y.length + c2.length + c3.length]; + final byte uncompressedFlag = 0x04; + cipherText[0] = uncompressedFlag; + pos += 1; + System.arraycopy(c1x, 0, cipherText, pos, c1x.length); + pos += c1x.length; + System.arraycopy(c1y, 0, cipherText, pos, c1y.length); + pos += c1y.length; + if (mode == Mode.C1C2C3) { + System.arraycopy(c2, 0, cipherText, pos, c2.length); + pos += c2.length; + System.arraycopy(c3, 0, cipherText, pos, c3.length); + } else if (mode == Mode.C1C3C2) { + System.arraycopy(c3, 0, cipherText, pos, c3.length); + pos += c3.length; + System.arraycopy(c2, 0, cipherText, pos, c2.length); + } + return cipherText; + } + + /** + * 签名 + * + * @param priKey 私钥 + * @param srcData 原文 + * @return DER编码后的签名值 + * @throws CryptoException + */ + public static byte[] sign(BCECPrivateKey priKey, byte[] srcData) throws CryptoException { + ECPrivateKeyParameters priKeyParameters = BCECUtil.convertPrivateKeyToParameters(priKey); + return sign(priKeyParameters, null, srcData); + } + + /** + * 签名 + * 不指定withId,则默认withId为字节数组:"1234567812345678".getBytes() + * + * @param priKeyParameters 私钥 + * @param srcData 原文 + * @return DER编码后的签名值 + * @throws CryptoException + */ + public static byte[] sign(ECPrivateKeyParameters priKeyParameters, byte[] srcData) throws CryptoException { + return sign(priKeyParameters, null, srcData); + } + + /** + * 私钥签名 + * + * @param priKey 私钥 + * @param withId 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes() + * @param srcData 原文 + * @return DER编码后的签名值 + * @throws CryptoException + */ + public static byte[] sign(BCECPrivateKey priKey, byte[] withId, byte[] srcData) throws CryptoException { + ECPrivateKeyParameters priKeyParameters = BCECUtil.convertPrivateKeyToParameters(priKey); + return sign(priKeyParameters, withId, srcData); + } + + /** + * 签名 + * + * @param priKeyParameters 私钥 + * @param withId 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes() + * @param srcData 源数据 + * @return DER编码后的签名值 + * @throws CryptoException + */ + public static byte[] sign(ECPrivateKeyParameters priKeyParameters, byte[] withId, byte[] srcData) + throws CryptoException { + SM2Signer signer = new SM2Signer(); + CipherParameters param = null; + ParametersWithRandom pwr = new ParametersWithRandom(priKeyParameters, new SecureRandom()); + if (withId != null) { + param = new ParametersWithID(pwr, withId); + } else { + param = pwr; + } + signer.init(true, param); + + System.out.println("Z=" + BytesUtil.bytes2HexString((byte[]) ReflectUtil.getFieldValue( signer, "z"))); + + signer.update(srcData, 0, srcData.length); + return signer.generateSignature(); + } + + /** + * 将DER编码的SM2签名解码成64字节的纯R+S字节流 + * + * @param derSign + * @return 64字节数组,前32字节为R,后32字节为S + */ + public static byte[] decodeDERSM2Sign(byte[] derSign) { + ASN1Sequence as = DERSequence.getInstance(derSign); + byte[] rBytes = ((ASN1Integer) as.getObjectAt(0)).getValue().toByteArray(); + byte[] sBytes = ((ASN1Integer) as.getObjectAt(1)).getValue().toByteArray(); + //由于大数的补0规则,所以可能会出现33个字节的情况,要修正回32个字节 + rBytes = fixToCurveLengthBytes(rBytes); + sBytes = fixToCurveLengthBytes(sBytes); + byte[] rawSign = new byte[rBytes.length + sBytes.length]; + System.arraycopy(rBytes, 0, rawSign, 0, rBytes.length); + System.arraycopy(sBytes, 0, rawSign, rBytes.length, sBytes.length); + return rawSign; + } + + /** + * 把64字节的纯R+S字节数组编码成DER编码 + * + * @param rawSign 64字节数组形式的SM2签名值,前32字节为R,后32字节为S + * @return DER编码后的SM2签名值 + * @throws IOException + */ + public static byte[] encodeSM2SignToDER(byte[] rawSign) throws IOException { + //要保证大数是正数 + BigInteger r = new BigInteger(1, extractBytes(rawSign, 0, 32)); + BigInteger s = new BigInteger(1, extractBytes(rawSign, 32, 32)); + ASN1EncodableVector v = new ASN1EncodableVector(); + v.add(new ASN1Integer(r)); + v.add(new ASN1Integer(s)); + return new DERSequence(v).getEncoded(ASN1Encoding.DER); + } + + /** + * 验签 + * + * @param pubKey 公钥 + * @param srcData 原文 + * @param sign DER编码的签名值 + * @return + */ + public static boolean verify(BCECPublicKey pubKey, byte[] srcData, byte[] sign) { + ECPublicKeyParameters pubKeyParameters = BCECUtil.convertPublicKeyToParameters(pubKey); + return verify(pubKeyParameters, null, srcData, sign); + } + + /** + * 验签 + * 不指定withId,则默认withId为字节数组:"1234567812345678".getBytes() + * + * @param pubKeyParameters 公钥 + * @param srcData 原文 + * @param sign DER编码的签名值 + * @return 验签成功返回true,失败返回false + */ + public static boolean verify(ECPublicKeyParameters pubKeyParameters, byte[] srcData, byte[] sign) { + return verify(pubKeyParameters, null, srcData, sign); + } + + /** + * 验签 + * + * @param pubKey 公钥 + * @param withId 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes() + * @param srcData 原文 + * @param sign DER编码的签名值 + * @return + */ + public static boolean verify(BCECPublicKey pubKey, byte[] withId, byte[] srcData, byte[] sign) { + ECPublicKeyParameters pubKeyParameters = BCECUtil.convertPublicKeyToParameters(pubKey); + return verify(pubKeyParameters, withId, srcData, sign); + } + + /** + * 验签 + * + * @param pubKeyParameters 公钥 + * @param withId 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes() + * @param srcData 原文 + * @param sign DER编码的签名值 + * @return 验签成功返回true,失败返回false + */ + public static boolean verify(ECPublicKeyParameters pubKeyParameters, byte[] withId, byte[] srcData, byte[] sign) { + SM2Signer signer = new SM2Signer(); + CipherParameters param; + if (withId != null) { + param = new ParametersWithID(pubKeyParameters, withId); + } else { + param = pubKeyParameters; + } + signer.init(false, param); + System.out.println("Z=" + BytesUtil.bytes2HexString((byte[]) ReflectUtil.getFieldValue( signer, "z"))); + +// Digest digest = (Digest) ReflectUtil.getFieldValue( signer, "digest" ); +// digest.update( srcData, 0, srcData.length ); +// byte[] result = new byte[digest.getDigestSize()]; +// digest.doFinal(result, 0); +// System.out.println("hash=" + Util.bytes2HexString(result)); + + signer.update(srcData, 0, srcData.length); + return signer.verifySignature(sign); + } + + private static byte[] extractBytes(byte[] src, int offset, int length) { + byte[] result = new byte[length]; + System.arraycopy(src, offset, result, 0, result.length); + return result; + } + + private static byte[] fixToCurveLengthBytes(byte[] src) { + if (src.length == CURVE_LEN) { + return src; + } + + byte[] result = new byte[CURVE_LEN]; + if (src.length > CURVE_LEN) { + System.arraycopy(src, src.length - result.length, result, 0, result.length); + } else { + System.arraycopy(src, 0, result, result.length - src.length, src.length); + } + return result; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/SM3.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/SM3.java new file mode 100644 index 0000000..65c82eb --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/SM3.java @@ -0,0 +1,351 @@ +package com.sunyard.ssp.utils.sm3; + +public class SM3 { + + public static final byte[] iv = { 0x73, (byte) 0x80, 0x16, 0x6f, 0x49, + 0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte) 0xd7, + (byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30, + (byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte) 0xe3, + (byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb, 0x0e, + 0x4e }; + + public static int[] Tj = new int[64]; + + static + { + for (int i = 0; i < 16; i++) + { + Tj[i] = 0x79cc4519; + } + + for (int i = 16; i < 64; i++) + { + Tj[i] = 0x7a879d8a; + } + } + + public static byte[] CF(byte[] V, byte[] B) + { + int[] v, b; + v = convert(V); + b = convert(B); + return convert(CF(v, b)); + } + + private static int[] convert(byte[] arr) + { + int[] out = new int[arr.length / 4]; + byte[] tmp = new byte[4]; + for (int i = 0; i < arr.length; i += 4) + { + System.arraycopy(arr, i, tmp, 0, 4); + out[i / 4] = bigEndianByteToInt(tmp); + } + return out; + } + + private static byte[] convert(int[] arr) + { + byte[] out = new byte[arr.length * 4]; + byte[] tmp = null; + for (int i = 0; i < arr.length; i++) + { + tmp = bigEndianIntToByte(arr[i]); + System.arraycopy(tmp, 0, out, i * 4, 4); + } + return out; + } + + public static int[] CF(int[] V, int[] B) + { + int a, b, c, d, e, f, g, h; + int ss1, ss2, tt1, tt2; + a = V[0]; + b = V[1]; + c = V[2]; + d = V[3]; + e = V[4]; + f = V[5]; + g = V[6]; + h = V[7]; + + /*System.out.println("IV: "); + System.out.print(Integer.toHexString(a)+" "); + System.out.print(Integer.toHexString(b)+" "); + System.out.print(Integer.toHexString(c)+" "); + System.out.print(Integer.toHexString(d)+" "); + System.out.print(Integer.toHexString(e)+" "); + System.out.print(Integer.toHexString(f)+" "); + System.out.print(Integer.toHexString(g)+" "); + System.out.print(Integer.toHexString(h)+" "); + System.out.println(""); + System.out.println(""); + + System.out.println("填充后的消息: "); + for(int i=0; i= 0 && j <= 15) + { + return FF1j(X, Y, Z); + } + else + { + return FF2j(X, Y, Z); + } + } + + private static int GGj(int X, int Y, int Z, int j) + { + if (j >= 0 && j <= 15) + { + return GG1j(X, Y, Z); + } + else + { + return GG2j(X, Y, Z); + } + } + + // 逻辑位运算函数 + private static int FF1j(int X, int Y, int Z) + { + int tmp = X ^ Y ^ Z; + return tmp; + } + + private static int FF2j(int X, int Y, int Z) + { + int tmp = ((X & Y) | (X & Z) | (Y & Z)); + return tmp; + } + + private static int GG1j(int X, int Y, int Z) + { + int tmp = X ^ Y ^ Z; + return tmp; + } + + private static int GG2j(int X, int Y, int Z) + { + int tmp = (X & Y) | (~X & Z); + return tmp; + } + + private static int P0(int X) + { + int y = rotateLeft(X, 9); + y = bitCycleLeft(X, 9); + int z = rotateLeft(X, 17); + z = bitCycleLeft(X, 17); + int t = X ^ y ^ z; + return t; + } + + private static int P1(int X) + { + int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23); + return t; + } + + /** + * 对最后一个分组字节数据padding + * + * @param in + * @param bLen + * 分组个数 + * @return + */ + public static byte[] padding(byte[] in, int bLen) + { + int k = 448 - (8 * in.length + 1) % 512; + if (k < 0) + { + k = 960 - (8 * in.length + 1) % 512; + } + k += 1; + byte[] padd = new byte[k / 8]; + padd[0] = (byte) 0x80; + long n = in.length * 8 + bLen * 512; + byte[] out = new byte[in.length + k / 8 + 64 / 8]; + int pos = 0; + System.arraycopy(in, 0, out, 0, in.length); + pos += in.length; + System.arraycopy(padd, 0, out, pos, padd.length); + pos += padd.length; + byte[] tmp = back(Util.longToBytes(n)); + System.arraycopy(tmp, 0, out, pos, tmp.length); + return out; + } + + /** + * 字节数组逆序 + * + * @param in + * @return + */ + private static byte[] back(byte[] in) + { + byte[] out = new byte[in.length]; + for (int i = 0; i < out.length; i++) + { + out[i] = in[out.length - i - 1]; + } + + return out; + } + + public static int rotateLeft(int x, int n) + { + return (x << n) | (x >> (32 - n)); + } + + private static int bitCycleLeft(int n, int bitLen) + { + bitLen %= 32; + byte[] tmp = bigEndianIntToByte(n); + int byteLen = bitLen / 8; + int len = bitLen % 8; + if (byteLen > 0) + { + tmp = byteCycleLeft(tmp, byteLen); + } + + if (len > 0) + { + tmp = bitSmall8CycleLeft(tmp, len); + } + + return bigEndianByteToInt(tmp); + } + + private static byte[] bitSmall8CycleLeft(byte[] in, int len) + { + byte[] tmp = new byte[in.length]; + int t1, t2, t3; + for (int i = 0; i < tmp.length; i++) + { + t1 = (byte) ((in[i] & 0x000000ff) << len); + t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len)); + t3 = (byte) (t1 | t2); + tmp[i] = (byte) t3; + } + + return tmp; + } + + private static byte[] byteCycleLeft(byte[] in, int byteLen) + { + byte[] tmp = new byte[in.length]; + System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen); + System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen); + return tmp; + } + + /*private static void print(int[] arr) + { + for (int i = 0; i < arr.length; i++) + { + System.out.print(Integer.toHexString(arr[i]) + " "); + if ((i + 1) % 16 == 0) + { + System.out.println(); + } + } + System.out.println(); + }*/ +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/SM3Digest.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/SM3Digest.java new file mode 100644 index 0000000..b7f34a7 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/SM3Digest.java @@ -0,0 +1,183 @@ +package com.sunyard.ssp.utils.sm3; + + +import com.sunyard.config.security.SM3PasswordEncoder; + +public class SM3Digest +{ + /** SM3值的长度 */ + private static final int BYTE_LENGTH = 32; + + /** SM3分组长度 */ + private static final int BLOCK_LENGTH = 64; + + /** 缓冲区长度 */ + private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1; + + /** 缓冲区 */ + private byte[] xBuf = new byte[BUFFER_LENGTH]; + + /** 缓冲区偏移量 */ + private int xBufOff; + + /** 初始向量 */ + private byte[] V = SM3.iv.clone(); + + private int cntBlock = 0; + + public SM3Digest() { + } + + public SM3Digest(SM3Digest t) + { + System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length); + this.xBufOff = t.xBufOff; + System.arraycopy(t.V, 0, this.V, 0, t.V.length); + } + + /** + * SM3结果输出 + * + * @param out 保存SM3结构的缓冲区 + * @param outOff 缓冲区偏移量 + * @return + */ + public int doFinal(byte[] out, int outOff) + { + byte[] tmp = doFinal(); + System.arraycopy(tmp, 0, out, 0, tmp.length); + return BYTE_LENGTH; + } + + public void reset() + { + xBufOff = 0; + cntBlock = 0; + V = SM3.iv.clone(); + } + + /** + * 明文输入 + * + * @param in + * 明文输入缓冲区 + * @param inOff + * 缓冲区偏移量 + * @param len + * 明文长度 + */ + public void update(byte[] in, int inOff, int len) + { + int partLen = BUFFER_LENGTH - xBufOff; + int inputLen = len; + int dPos = inOff; + if (partLen < inputLen) + { + System.arraycopy(in, dPos, xBuf, xBufOff, partLen); + inputLen -= partLen; + dPos += partLen; + doUpdate(); + while (inputLen > BUFFER_LENGTH) + { + System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH); + inputLen -= BUFFER_LENGTH; + dPos += BUFFER_LENGTH; + doUpdate(); + } + } + + System.arraycopy(in, dPos, xBuf, xBufOff, inputLen); + xBufOff += inputLen; + } + + private void doUpdate() + { + byte[] B = new byte[BLOCK_LENGTH]; + for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH) + { + System.arraycopy(xBuf, i, B, 0, B.length); + doHash(B); + } + xBufOff = 0; + } + + private void doHash(byte[] B) + { + byte[] tmp = SM3.CF(V, B); + System.arraycopy(tmp, 0, V, 0, V.length); + cntBlock++; + } + + private byte[] doFinal() + { + byte[] B = new byte[BLOCK_LENGTH]; + byte[] buffer = new byte[xBufOff]; + System.arraycopy(xBuf, 0, buffer, 0, buffer.length); + byte[] tmp = SM3.padding(buffer, cntBlock); + for (int i = 0; i < tmp.length; i += BLOCK_LENGTH) + { + System.arraycopy(tmp, i, B, 0, B.length); + doHash(B); + } + return V; + } + + public void update(byte in) + { + byte[] buffer = new byte[] { in }; + update(buffer, 0, 1); + } + + public int getDigestSize() + { + return BYTE_LENGTH; + } + + + + /* + * 字节数组转16进制字符串 + */ + public static String bytes2HexString(byte[] b) { + StringBuilder bs = new StringBuilder(); + + for (int i = 0; i < b.length; i++) { + String hex = Integer.toHexString(b[i] & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + bs.append( hex.toUpperCase() ); + } + + return bs.toString(); + } + + public static String encode(String rawPassword){ + byte[] md2 = new byte[32]; + byte[] msg2 = rawPassword.getBytes(); + SM3Digest sm3 = new SM3Digest(); + + sm3.update(msg2, 0, msg2.length); + sm3.doFinal(md2, 0); + return bytes2HexString(md2); + } + + public static void main(String[] args) { +// byte[] md2 = new byte[32]; +// byte[] msg2 = ("123456"+"cw777").getBytes(); +// SM3Digest sm3 = new SM3Digest(); +// +// sm3.update(msg2, 0, msg2.length); +// sm3.doFinal(md2, 0); +// String s2 = bytes2HexString(md2); +// System.out.println("加密后result:" + s2); + + String s=""; + SM3PasswordEncoder passwordEncoder = new SM3PasswordEncoder(); + String encode = passwordEncoder.encode(s); + System.out.println("加密后结果="+encode); + + boolean matches = passwordEncoder.matches("123", encode); + System.out.println("校验结果="+matches); + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/Util.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/Util.java new file mode 100644 index 0000000..c2d7fa9 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/utils/sm3/Util.java @@ -0,0 +1,662 @@ +package com.sunyard.ssp.utils.sm3; + +import java.math.BigInteger; + +public class Util +{ + /** + * 整形转换成网络传输的字节流(字节数组)型数据 + * + * @param num 一个整型数据 + * @return 4个字节的自己数组 + */ + public static byte[] intToBytes(int num) + { + byte[] bytes = new byte[4]; + bytes[0] = (byte) (0xff & (num >> 0)); + bytes[1] = (byte) (0xff & (num >> 8)); + bytes[2] = (byte) (0xff & (num >> 16)); + bytes[3] = (byte) (0xff & (num >> 24)); + return bytes; + } + + /** + * 四个字节的字节数据转换成一个整形数据 + * + * @param bytes 4个字节的字节数组 + * @return 一个整型数据 + */ + public static int byteToInt(byte[] bytes) + { + int num = 0; + int temp; + temp = (0x000000ff & (bytes[0])) << 0; + num = num | temp; + temp = (0x000000ff & (bytes[1])) << 8; + num = num | temp; + temp = (0x000000ff & (bytes[2])) << 16; + num = num | temp; + temp = (0x000000ff & (bytes[3])) << 24; + num = num | temp; + return num; + } + + /** + * 长整形转换成网络传输的字节流(字节数组)型数据 + * + * @param num 一个长整型数据 + * @return 4个字节的自己数组 + */ + public static byte[] longToBytes(long num) + { + byte[] bytes = new byte[8]; + for (int i = 0; i < 8; i++) + { + bytes[i] = (byte) (0xff & (num >> (i * 8))); + } + + return bytes; + } + + /** + * 大数字转换字节流(字节数组)型数据 + * + * @param n + * @return + */ + public static byte[] byteConvert32Bytes(BigInteger n) + { + byte tmpd[] = (byte[])null; + if(n == null) + { + return null; + } + + if(n.toByteArray().length == 33) + { + tmpd = new byte[32]; + System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32); + } + else if(n.toByteArray().length == 32) + { + tmpd = n.toByteArray(); + } + else + { + tmpd = new byte[32]; + for(int i = 0; i < 32 - n.toByteArray().length; i++) + { + tmpd[i] = 0; + } + System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length); + } + return tmpd; + } + + /** + * 换字节流(字节数组)型数据转大数字 + * + * @param b + * @return + */ + public static BigInteger byteConvertInteger(byte[] b) + { + if (b[0] < 0) + { + byte[] temp = new byte[b.length + 1]; + temp[0] = 0; + System.arraycopy(b, 0, temp, 1, b.length); + return new BigInteger(temp); + } + return new BigInteger(b); + } + + /** + * 根据字节数组获得值(十六进制数字) + * + * @param bytes + * @return + */ + public static String getHexString(byte[] bytes) + { + return getHexString(bytes, true); + } + + /** + * 根据字节数组获得值(十六进制数字) + * + * @param bytes + * @param upperCase + * @return + */ + public static String getHexString(byte[] bytes, boolean upperCase) + { + String ret = ""; + for (int i = 0; i < bytes.length; i++) + { + ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1); + } + return upperCase ? ret.toUpperCase() : ret; + } + + /** + * 打印十六进制字符串 + * + * @param bytes + */ + public static void printHexString(byte[] bytes) + { + for (int i = 0; i < bytes.length; i++) + { + String hex = Integer.toHexString(bytes[i] & 0xFF); + if (hex.length() == 1) + { + hex = '0' + hex; + } + System.out.print("0x" + hex.toUpperCase() + ","); + } + System.out.println(""); + } + + /** + * Convert hex string to byte[] + * + * @param hexString + * the hex string + * @return byte[] + */ + public static byte[] hexStringToBytes(String hexString) + { + if (hexString == null || hexString.equals("")) + { + return null; + } + + hexString = hexString.toUpperCase(); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) + { + int pos = i * 2; + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); + } + return d; + } + + /** + * Convert char to byte + * + * @param c + * char + * @return byte + */ + public static byte charToByte(char c) + { + return (byte) "0123456789ABCDEF".indexOf(c); + } + + /** + * 用于建立十六进制字符的输出的小写字符数组 + */ + private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + /** + * 用于建立十六进制字符的输出的大写字符数组 + */ + private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + /** + * 将字节数组转换为十六进制字符数组 + * + * @param data byte[] + * @return 十六进制char[] + */ + public static char[] encodeHex(byte[] data) { + return encodeHex(data, true); + } + + /** + * 将字节数组转换为十六进制字符数组 + * + * @param data byte[] + * @param toLowerCase true 传换成小写格式 , false 传换成大写格式 + * @return 十六进制char[] + */ + public static char[] encodeHex(byte[] data, boolean toLowerCase) { + return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + /** + * 将字节数组转换为十六进制字符数组 + * + * @param data byte[] + * @param toDigits 用于控制输出的char[] + * @return 十六进制char[] + */ + protected static char[] encodeHex(byte[] data, char[] toDigits) { + int l = data.length; + char[] out = new char[l << 1]; + // two characters form the hex value. + for (int i = 0, j = 0; i < l; i++) { + out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; + out[j++] = toDigits[0x0F & data[i]]; + } + return out; + } + + /** + * 将字节数组转换为十六进制字符串 + * + * @param data byte[] + * @return 十六进制String + */ + public static String encodeHexString(byte[] data) { + return encodeHexString(data, true); + } + + /** + * 将字节数组转换为十六进制字符串 + * + * @param data byte[] + * @param toLowerCase true 传换成小写格式 , false 传换成大写格式 + * @return 十六进制String + */ + public static String encodeHexString(byte[] data, boolean toLowerCase) { + return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + /** + * 将字节数组转换为十六进制字符串 + * + * @param data byte[] + * @param toDigits 用于控制输出的char[] + * @return 十六进制String + */ + protected static String encodeHexString(byte[] data, char[] toDigits) { + return new String(encodeHex(data, toDigits)); + } + + /** + * 将十六进制字符数组转换为字节数组 + * + * @param data 十六进制char[] + * @return byte[] + * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常 + */ + public static byte[] decodeHex(char[] data) { + int len = data.length; + + if ((len & 0x01) != 0) { + throw new RuntimeException("Odd number of characters."); + } + + byte[] out = new byte[len >> 1]; + + // two characters form the hex value. + for (int i = 0, j = 0; j < len; i++) { + int f = toDigit(data[j], j) << 4; + j++; + f = f | toDigit(data[j], j); + j++; + out[i] = (byte) (f & 0xFF); + } + + return out; + } + + /** + * 将十六进制字符转换成一个整数 + * + * @param ch 十六进制char + * @param index 十六进制字符在字符数组中的位置 + * @return 一个整数 + * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常 + */ + protected static int toDigit(char ch, int index) { + int digit = Character.digit(ch, 16); + if (digit == -1) { + throw new RuntimeException("Illegal hexadecimal character " + ch + + " at index " + index); + } + return digit; + } + + /** + * 数字字符串转ASCII码字符串 + * + * @param content + * 字符串 + * @return ASCII字符串 + */ + public static String StringToAsciiString(String content) { + String result = ""; + int max = content.length(); + for (int i = 0; i < max; i++) { + char c = content.charAt(i); + String b = Integer.toHexString(c); + result = result + b; + } + return result; + } + + /** + * 十六进制转字符串 + * + * @param hexString + * 十六进制字符串 + * @param encodeType + * 编码类型4:Unicode,2:普通编码 + * @return 字符串 + */ + public static String hexStringToString(String hexString, int encodeType) { + String result = ""; + int max = hexString.length() / encodeType; + for (int i = 0; i < max; i++) { + char c = (char) hexStringToAlgorism(hexString + .substring(i * encodeType, (i + 1) * encodeType)); + result += c; + } + return result; + } + + /** + * 十六进制字符串装十进制 + * + * @param hex + * 十六进制字符串 + * @return 十进制数值 + */ + public static int hexStringToAlgorism(String hex) { + hex = hex.toUpperCase(); + int max = hex.length(); + int result = 0; + for (int i = max; i > 0; i--) { + char c = hex.charAt(i - 1); + int algorism = 0; + if (c >= '0' && c <= '9') { + algorism = c - '0'; + } else { + algorism = c - 55; + } + result += Math.pow(16, max - i) * algorism; + } + return result; + } + + /** + * 十六转二进制 + * + * @param hex + * 十六进制字符串 + * @return 二进制字符串 + */ + public static String hexStringToBinary(String hex) { + hex = hex.toUpperCase(); + String result = ""; + int max = hex.length(); + for (int i = 0; i < max; i++) { + char c = hex.charAt(i); + switch (c) { + case '0': + result += "0000"; + break; + case '1': + result += "0001"; + break; + case '2': + result += "0010"; + break; + case '3': + result += "0011"; + break; + case '4': + result += "0100"; + break; + case '5': + result += "0101"; + break; + case '6': + result += "0110"; + break; + case '7': + result += "0111"; + break; + case '8': + result += "1000"; + break; + case '9': + result += "1001"; + break; + case 'A': + result += "1010"; + break; + case 'B': + result += "1011"; + break; + case 'C': + result += "1100"; + break; + case 'D': + result += "1101"; + break; + case 'E': + result += "1110"; + break; + case 'F': + result += "1111"; + break; + } + } + return result; + } + + /** + * ASCII码字符串转数字字符串 + * + * @param content + * ASCII字符串 + * @return 字符串 + */ + public static String AsciiStringToString(String content) { + String result = ""; + int length = content.length() / 2; + for (int i = 0; i < length; i++) { + String c = content.substring(i * 2, i * 2 + 2); + int a = hexStringToAlgorism(c); + char b = (char) a; + String d = String.valueOf(b); + result += d; + } + return result; + } + + /** + * 将十进制转换为指定长度的十六进制字符串 + * + * @param algorism + * int 十进制数字 + * @param maxLength + * int 转换后的十六进制字符串长度 + * @return String 转换后的十六进制字符串 + */ + public static String algorismToHexString(int algorism, int maxLength) { + String result = ""; + result = Integer.toHexString(algorism); + + if (result.length() % 2 == 1) { + result = "0" + result; + } + return patchHexString(result.toUpperCase(), maxLength); + } + + /** + * 字节数组转为普通字符串(ASCII对应的字符) + * + * @param bytearray + * byte[] + * @return String + */ + public static String byteToString(byte[] bytearray) { + String result = ""; + char temp; + + int length = bytearray.length; + for (int i = 0; i < length; i++) { + temp = (char) bytearray[i]; + result += temp; + } + return result; + } + + /** + * 二进制字符串转十进制 + * + * @param binary + * 二进制字符串 + * @return 十进制数值 + */ + public static int binaryToAlgorism(String binary) { + int max = binary.length(); + int result = 0; + for (int i = max; i > 0; i--) { + char c = binary.charAt(i - 1); + int algorism = c - '0'; + result += Math.pow(2, max - i) * algorism; + } + return result; + } + + /** + * 十进制转换为十六进制字符串 + * + * @param algorism + * int 十进制的数字 + * @return String 对应的十六进制字符串 + */ + public static String algorismToHEXString(int algorism) { + String result = ""; + result = Integer.toHexString(algorism); + + if (result.length() % 2 == 1) { + result = "0" + result; + + } + result = result.toUpperCase(); + + return result; + } + + /** + * HEX字符串前补0,主要用于长度位数不足。 + * + * @param str + * String 需要补充长度的十六进制字符串 + * @param maxLength + * int 补充后十六进制字符串的长度 + * @return 补充结果 + */ + static public String patchHexString(String str, int maxLength) { + String temp = ""; + for (int i = 0; i < maxLength - str.length(); i++) { + temp = "0" + temp; + } + str = (temp + str).substring(0, maxLength); + return str; + } + + /** + * 将一个字符串转换为int + * + * @param s + * String 要转换的字符串 + * @param defaultInt + * int 如果出现异常,默认返回的数字 + * @param radix + * int 要转换的字符串是什么进制的,如16 8 10. + * @return int 转换后的数字 + */ + public static int parseToInt(String s, int defaultInt, int radix) { + int i = 0; + try { + i = Integer.parseInt(s, radix); + } catch (NumberFormatException ex) { + i = defaultInt; + } + return i; + } + + /** + * 将一个十进制形式的数字字符串转换为int + * + * @param s + * String 要转换的字符串 + * @param defaultInt + * int 如果出现异常,默认返回的数字 + * @return int 转换后的数字 + */ + public static int parseToInt(String s, int defaultInt) { + int i = 0; + try { + i = Integer.parseInt(s); + } catch (NumberFormatException ex) { + i = defaultInt; + } + return i; + } + + /** + * 十六进制串转化为byte数组 + * + * @return the array of byte + */ + public static byte[] hexToByte(String hex) + throws IllegalArgumentException { + if (hex.length() % 2 != 0) { + throw new IllegalArgumentException(); + } + char[] arr = hex.toCharArray(); + byte[] b = new byte[hex.length() / 2]; + for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) { + String swap = "" + arr[i++] + arr[i]; + int byteint = Integer.parseInt(swap, 16) & 0xFF; + b[j] = new Integer(byteint).byteValue(); + } + return b; + } + + /** + * 字节数组转换为十六进制字符串 + * + * @param b + * byte[] 需要转换的字节数组 + * @return String 十六进制字符串 + */ + public static String byteToHex(byte b[]) { + if (b == null) { + throw new IllegalArgumentException( + "Argument b ( byte array ) is null! "); + } + String hs = ""; + String stmp = ""; + for (int n = 0; n < b.length; n++) { + stmp = Integer.toHexString(b[n] & 0xff); + if (stmp.length() == 1) { + hs = hs + "0" + stmp; + } else { + hs = hs + stmp; + } + } + return hs.toUpperCase(); + } + + public static byte[] subByte(byte[] input, int startIndex, int length) { + byte[] bt = new byte[length]; + for (int i = 0; i < length; i++) { + bt[i] = input[i + startIndex]; + } + return bt; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/KeyVo.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/KeyVo.java new file mode 100644 index 0000000..5e50c19 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/KeyVo.java @@ -0,0 +1,24 @@ +package com.sunyard.ssp.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @date:2020/6/10 + * @description: + */ +@Data +public class KeyVo { + @ApiModelProperty(value = "方案编号") + private String solutionNumber; + + @ApiModelProperty(value = "模板编号") + private String tmplNumber; + + @ApiModelProperty(value = "节点编号") + private String nodeNumber; + + @ApiModelProperty(value = "密钥编号") + private String keyNumber; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/ScRoleVo.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/ScRoleVo.java new file mode 100644 index 0000000..8247e90 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/ScRoleVo.java @@ -0,0 +1,30 @@ +package com.sunyard.ssp.vo; + +import com.sunyard.ssp.modules.user.entity.ScRole; +import com.sunyard.ssp.modules.user.entity.ScRoleDepartment; +import com.sunyard.ssp.modules.user.entity.ScRolePermission; +import lombok.Data; + +import java.util.List; + +/** + *

+ * + *

+ * + * @author tsz + * @since 2020-03-11 + */ +@Data +public class ScRoleVo extends ScRole { + + private List permissions; + + private List departments; + + public ScRoleVo(ScRole role, List permissions, List departments) { + super(role); + this.permissions = permissions; + this.departments = departments; + } +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/SearchVo.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/SearchVo.java new file mode 100644 index 0000000..6d60327 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/SearchVo.java @@ -0,0 +1,19 @@ +package com.sunyard.ssp.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author Exrickx + */ +@Data +public class SearchVo implements Serializable { + + @ApiModelProperty(value = "起始日期") + private String startDate; + + @ApiModelProperty(value = "结束日期") + private String endDate; +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/TokenUser.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/TokenUser.java new file mode 100644 index 0000000..19ec756 --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/TokenUser.java @@ -0,0 +1,22 @@ +package com.sunyard.ssp.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @author Exrickx + */ +@Data +@AllArgsConstructor +public class TokenUser implements Serializable{ + + private String username; + + private List permissions; + + private Boolean saveLogin; + +} diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/UPublicKeyVo.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/UPublicKeyVo.java new file mode 100644 index 0000000..a77d6fd --- /dev/null +++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/vo/UPublicKeyVo.java @@ -0,0 +1,31 @@ +package com.sunyard.ssp.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @date:2020/6/10 + * @description: + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UPublicKeyVo { + @ApiModelProperty(value = "用户id") + private Long userId; + + @ApiModelProperty(value = "用户拥有的角色ids") + private Long[] roldIds; + + @ApiModelProperty(value = "用户绑定U盾公钥") + private String uPublicKey; + + @ApiModelProperty(value = "用户绑定U盾私钥") + private String uPrivateKey; + + @ApiModelProperty(value = "数字签名") + private String signInfo; + +} diff --git a/chsm-web-manage/src/main/resources/application.yml b/chsm-web-manage/src/main/resources/application.yml new file mode 100644 index 0000000..1c51068 --- /dev/null +++ b/chsm-web-manage/src/main/resources/application.yml @@ -0,0 +1,150 @@ +server: + port: 88 + tomcat: + uri-encoding: UTF-8 + threads: + max: 1000 + min-spare: 30 + +spring: + main: + allow-circular-references: true + # 数据源 + datasource: + driverClassName: dm.jdbc.driver.DmDriver + url: jdbc:dm://172.16.17.236:5236?schema=SSP&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=UTF-8 + username: SUNYARD + # Jasypt加密 可到common-utils中找到JasyptUtil加解密工具类生成加密结果 格式为ENC(加密结果) + password: 123456 + redis: + #是否开启集群 false 不开启集群 , true 开启集群 + isJq: ${solo_switch:false} + host: 172.16.17.163 + port: 6379 + password: sunyard2 + # 连接超时时长(毫秒) + timeout: 6000ms + cluster: + nodes: 47.99.123.162:6379,47.99.152.68:6379,47.110.92.9:6379,47.99.123.162:6378,47.99.152.68:6378,47.110.92.9:6378 + # 集群模式下,集群最大转发的数量 + max-redirects: 3 + jedis: + pool: + # 连接池最大连接数(使用负值表示没有限制) + max-active: 1000 + # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + # 连接池中的最大空闲连接      + max-idle: 50 + # 连接池中的最小空闲连接 + min-idle: 25 + servlet: + multipart: + #默认单个上传文件是1MB + max-file-size: 50MB + #默认上传文件总大小是10MB + max-request-size: 50MB + #开启切面 + aop: + proxy-target-class: true + auto: true + +file: + path: ${file_path:Y:\} +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + # 原生配置 + configuration: + map-underscore-to-camel-case: true + cache-enabled: false + lazy-loading-enabled: false + global-config: + # 数据库相关配置 + db-config: + #主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID"; + id-type: ASSIGN_ID + #驼峰下划线转换 + table-underline: true + #是否开启大写命名,默认不开启 + capital-mode: true + #逻辑删除配置 + #logic-delete-value: 1 + #logic-not-delete-value: 0 +# Swagger界面内容配置 +swagger: + title: sspweb API接口文档 + description: + version: 1.0.0 + termsOfServiceUrl: + contact: + name: + url: + email: +ssp: + token: + # 默认JWT 启用Redis后设置为true后,token将存入redis,并具有单点登录功能 + redis: true + # 限制用户登陆错误次数(次) + loginTimeLimit: 3 + # 错误超过次数后多少分钟后才能继续登录(分钟) + loginAfterTime: 10 + # token过期时间(分钟) + tokenExpireTime: 10080 + # 用户选择保存登录状态对应token过期时间(天) + saveLoginTime: 7 + # 密码过期时间 (日) + passMaxDays: 90 + #密码过期前多少天开始提示 + passWarnAge: 7 +# 需要验证码校验的接口路径 支持通配符 自动过滤拦截校验 无需开发人员再次校验 +captcha: + # 图片验证码验证 + image: + - /login # 登录接口 +# 忽略鉴权url +ignored: + urls: + - /** + - /common/captcha/** + - /swagger/** + - /**/v2/api-docs + - /**/*.js + - /**/*.css + - /**/*.png + - /**/*.ico + - /login + - /certificate/certificate/save + - /swagger-ui.html + - /swagger-resources/** + - /swagger/** + - /druid/** + - /Certificate/** + - /sysconf/paramConf/selectByItem + - /ushield/dowloadFile + - /ushield/ulogin + - /sysconf/scDictData/selectVersion + - /user/admin/init + - /user/initialization/check + - /sysconf/scDictData/selectByType + - /ushield/urandom + - /cipherMachine + - /ushield/bindUPublickey + - /ushield/init/bindUPublickey + - /status/set + - /test/setALL +logging: +# config: classpath:log4j2.xml + level: + cn.jay.repository: trace + + +monitorSwitch: + redis: ${redisMonitorSwitch:true} + db: ${dbMonitorSwitch:true} + +scheduler: + cron: 0 0 * * * ? +releaseTime: 1718332531 +#redisSyncTask: +# packageName: com.sunyard.ssp.modules.redisSyncTask.task + diff --git a/chsm-web-server/pom.xml b/chsm-web-server/pom.xml new file mode 100644 index 0000000..57eb6c7 --- /dev/null +++ b/chsm-web-server/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.sunyard.chsm + chsm + 1.0-SNAPSHOT + + + chsm-web-server + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/config/redis.config.json b/config/redis.config.json new file mode 100644 index 0000000..9395349 --- /dev/null +++ b/config/redis.config.json @@ -0,0 +1,16 @@ +{ + "password" : "sunyard2", + "mode" : "solo", + "node" : { + "ip" : "172.16.17.163", + "port" : 6379 + }, + "nodes" : [ + { + "ip" : "172.16.17.163", + "port" : 6379 + } + ] + + +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a24c90c --- /dev/null +++ b/pom.xml @@ -0,0 +1,121 @@ + + + + org.springframework.boot + spring-boot-starter-parent + 2.7.15 + + + com.sunyard.chsm + chsm + 1.0-SNAPSHOT + + chsm-web-server + chsm-model + chsm-web-manage + chsm-common + + + 4.0.0 + pom + + + + 1.69 + 2.7.15 + + 1.8 + 1.8 + 1.8 + 1.8 + UTF-8 + + + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + + + + + + com.sunyard + proto + 1.0.20221215 + + + com.baomidou + mybatis-plus-boot-starter + 3.5.5 + + + org.bouncycastle + bcprov-jdk15on + ${bcprov.version} + + + org.bouncycastle + bcpkix-jdk15on + ${bcprov.version} + + + + + + + nexus-sunyard + nexus-sunyard + http://172.16.17.15:8081/repository/maven-public/ + default + + true + always + + + true + always + + + + tencent + tencent maven + https://mirrors.cloud.tencent.com/nexus/repository/maven-public/ + + true + + + true + + + + + + nexus-sunyard + nexus-sunyard + http://172.16.17.15:8081/repository/maven-public/ + + + + + + nexus-sunyard + repo-snapshot + http://172.16.17.15:8081/repository/maven-snapshots + + + nexus-sunyard + repo-release + http://172.16.17.15:8081/repository/maven-releases + + +