From 20066bc864b32d1a21c492d0f05abd644e13e9eb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 2 May 2021 00:41:21 +0800 Subject: [PATCH] 项目结构调整 x 15 : 将 web、security、operatelog 等组件拆分出去 --- yudao-admin-server/pom.xml | 18 ++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiAccessLogConvert.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiErrorLogConvert.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileConfiguration.java | 12 ++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileProperties.java | 22 ++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/package-info.java | 16 ++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/package-info.java | 6 ++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/file/impl/InfFileServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsCallbackController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/errorcode/SysErrorCodeConvert.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/auth/SysUserSessionDO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/logger/SysOperateLogDO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/permission/SysRoleDO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java | 4 +--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaConfig.java | 9 +++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaProperties.java | 31 +++++++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/package-info.java | 4 ++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenConfiguration.java | 9 +++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenProperties.java | 28 ++++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/package-info.java | 4 ++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/package-info.java | 6 ++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysCaptchaServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java | 4 ++-- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java | 2 +- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeConfiguration.java | 36 ++++++++++++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeProperties.java | 26 ++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java | 34 ++++++++++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeRespDTO.java | 28 ++++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java | 15 +++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoader.java | 24 ++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/service/ErrorCodeFrameworkService.java | 35 +++++++++++++++++++++++++++++++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/package-info.java | 6 ++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/package-info.java | 6 ++++++ yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java | 6 +++--- yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java | 4 ++-- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java | 2 +- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java | 6 +++--- yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java | 2 +- yudao-dependencies/pom.xml | 37 ++++++++++++++++++++++++++++++++++++- yudao-framework/pom.xml | 5 +++++ yudao-framework/yudao-common/pom.xml | 6 ++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java | 28 ++++++++++++++++++++++++++++ yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java | 30 ++++++++++++++++++++++++++++++ yudao-framework/yudao-framework-all/pom.xml | 28 ---------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaConfig.java | 9 --------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaProperties.java | 31 ------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenConfiguration.java | 9 --------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenProperties.java | 28 ---------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeConfiguration.java | 36 ------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeProperties.java | 26 -------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java | 34 ---------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeRespDTO.java | 28 ---------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java | 15 --------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java | 98 -------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoader.java | 24 ------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java | 73 ------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/service/ErrorCodeFrameworkService.java | 35 ----------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/package-info.java | 6 ------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileConfiguration.java | 12 ------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileProperties.java | 22 ---------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/package-info.java | 16 ---------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/config/JacksonConfig.java | 35 ----------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/deser/LocalDateTimeDeserializer.java | 26 -------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/ser/LocalDateTimeSerializer.java | 24 ------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/config/ApiLogConfiguration.java | 34 ---------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java | 112 ---------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java | 23 ----------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java | 23 ----------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiAccessLogCreateDTO.java | 85 ------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiErrorLogCreateDTO.java | 109 ------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/config/OperateLogConfiguration.java | 15 --------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java | 57 --------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java | 354 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/dto/OperateLogCreateReqDTO.java | 84 ------------------------------------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateTypeEnum.java | 55 ------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/package-info.java | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java | 17 ----------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/util/OperateLogUtils.java | 21 --------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/package-info.java | 10 ---------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityConfiguration.java | 166 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityProperties.java | 52 ---------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java | 93 --------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/enums/DataScopeEnum.java | 28 ---------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/filter/JwtAuthenticationTokenFilter.java | 85 ------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java | 43 ------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AuthenticationEntryPointImpl.java | 37 ------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/LogoutSuccessHandlerImpl.java | 42 ------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityAuthFrameworkService.java | 37 ------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityPermissionFrameworkService.java | 44 -------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityFrameworkUtils.java | 102 ------------------------------------------------------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/package-info.java | 7 ------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md | 2 -- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerAutoConfiguration.java | 105 --------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerProperties.java | 43 ------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/package-info.java | 6 ------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/《芋道 Spring Boot API 接口文档 Swagger 入门》.md | 1 - yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java | 4 ++-- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java | 2 +- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java | 28 ---------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java | 88 ---------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java | 37 ------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/XssProperties.java | 29 ----------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java | 26 -------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyFilter.java | 31 ------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyWrapper.java | 63 --------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/DemoFilter.java | 35 ----------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssFilter.java | 51 --------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java | 136 ---------------------------------------------------------------------------------------------------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java | 276 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalResponseBodyHandler.java | 45 --------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java | 46 ---------------------------------------------- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/package-info.java | 4 ---- yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/《芋道 Spring Boot SpringMVC 入门》.md | 1 - yudao-framework/yudao-spring-boot-starter-monitor/pom.xml | 18 ++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml | 14 +++++++------- yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java | 29 ++++++++++++++--------------- yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml | 44 ++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java | 15 +++++++++++++++ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java | 354 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java | 1 + yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java | 17 +++++++++++++++++ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java | 21 +++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java | 6 ++++++ yudao-framework/yudao-spring-boot-starter-protection/pom.xml | 18 ++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/pom.xml | 38 ++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityConfiguration.java | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/enums/DataScopeEnum.java | 28 ++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java | 44 ++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/package-info.java | 7 +++++++ yudao-framework/yudao-spring-boot-starter-security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md | 2 ++ yudao-framework/yudao-spring-boot-starter-web/pom.xml | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java | 23 +++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java | 23 +++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiAccessLogCreateDTO.java | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/package-info.java | 8 ++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java | 35 +++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java | 26 ++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeSerializer.java | 24 ++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/package-info.java | 1 + yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java | 1 + yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/package-info.java | 6 ++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java | 29 +++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java | 31 +++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java | 35 +++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalResponseBodyHandler.java | 45 +++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/package-info.java | 4 ++++ yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot API 接口文档 Swagger 入门》.md | 1 + yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot SpringMVC 入门》.md | 1 + 216 files changed, 3789 insertions(+), 3527 deletions(-) create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileConfiguration.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileProperties.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/package-info.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/package-info.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaConfig.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaProperties.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/package-info.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenConfiguration.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenProperties.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/package-info.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/package-info.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeConfiguration.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeProperties.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeRespDTO.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoader.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/service/ErrorCodeFrameworkService.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/package-info.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/package-info.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaConfig.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeRespDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoader.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/service/ErrorCodeFrameworkService.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/config/JacksonConfig.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/deser/LocalDateTimeDeserializer.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/ser/LocalDateTimeSerializer.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/config/ApiLogConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiAccessLogCreateDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiErrorLogCreateDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/config/OperateLogConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/dto/OperateLogCreateReqDTO.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateTypeEnum.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/util/OperateLogUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/enums/DataScopeEnum.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/filter/JwtAuthenticationTokenFilter.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AuthenticationEntryPointImpl.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/LogoutSuccessHandlerImpl.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityAuthFrameworkService.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityPermissionFrameworkService.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityFrameworkUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerAutoConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/《芋道 Spring Boot API 接口文档 Swagger 入门》.md delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/XssProperties.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyFilter.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyWrapper.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/DemoFilter.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssFilter.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalResponseBodyHandler.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/package-info.java delete mode 100644 yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/《芋道 Spring Boot SpringMVC 入门》.md create mode 100644 yudao-framework/yudao-spring-boot-starter-monitor/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-protection/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-security/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/enums/DataScopeEnum.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md create mode 100644 yudao-framework/yudao-spring-boot-starter-web/pom.xml create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiAccessLogCreateDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeSerializer.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalResponseBodyHandler.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot API 接口文档 Swagger 入门》.md create mode 100644 yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot SpringMVC 入门》.md diff --git a/yudao-admin-server/pom.xml b/yudao-admin-server/pom.xml index 16aef71..d0b7670 100644 --- a/yudao-admin-server/pom.xml +++ b/yudao-admin-server/pom.xml @@ -23,6 +23,17 @@ ${revision} + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + cn.iocoder.boot @@ -53,6 +64,13 @@ podam test + + + + cn.iocoder.boot + yudao-spring-boot-starter-operatelog + + diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java index 4919293..a4b6359 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/InfConfigController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.infra.controller.config; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.infra.controller.config.vo.*; import cn.iocoder.dashboard.modules.infra.convert.config.InfConfigConvert; import cn.iocoder.dashboard.modules.infra.dal.dataobject.config.InfConfigDO; @@ -23,7 +23,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_SENSITIVE; @Api(tags = "参数配置") diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java index fb053ec..155abe6 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.infra.controller.job; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.framework.quartz.core.util.CronUtils; import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.*; import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert; @@ -28,7 +28,7 @@ import java.util.Date; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "定时任务") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java index 0b338a3..bf5c92f 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.infra.controller.job; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExcelVO; import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogPageReqVO; @@ -29,7 +29,7 @@ import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "定时任务日志") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java index 4c4f068..b4bdc61 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiAccessLogController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.infra.controller.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExcelVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; @@ -26,7 +26,7 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "API 访问日志") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java index b50adba..9827d33 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/InfApiErrorLogController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.infra.controller.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExcelVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; @@ -26,8 +26,8 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; -import static cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Api(tags = "API 错误日志") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiAccessLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiAccessLogConvert.java index e8afada..54dce31 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiAccessLogConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiAccessLogConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.convert.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiAccessLogCreateDTO; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExcelVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogRespVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiErrorLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiErrorLogConvert.java index 874a0c7..91ecb45 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiErrorLogConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/convert/logger/InfApiErrorLogConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.convert.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExcelVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogRespVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileConfiguration.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileConfiguration.java new file mode 100644 index 0000000..ef3532d --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileConfiguration.java @@ -0,0 +1,12 @@ +package cn.iocoder.dashboard.modules.infra.framework.file.config; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 文件 配置类 + */ +@Configuration +@EnableConfigurationProperties(FileProperties.class) +public class FileConfiguration { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileProperties.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileProperties.java new file mode 100644 index 0000000..ad14835 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/config/FileProperties.java @@ -0,0 +1,22 @@ +package cn.iocoder.dashboard.modules.infra.framework.file.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; + +@ConfigurationProperties(prefix = "yudao.file") +@Validated +@Data +public class FileProperties { + + /** + * 对应 InfFileController 的 getFile 方法 + */ + @NotNull(message = "基础文件路径不能为空") + private String basePath; + + // TODO 七牛、等等 + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/package-info.java new file mode 100644 index 0000000..0816a33 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/file/package-info.java @@ -0,0 +1,16 @@ +/** + * 文件的存储,推荐使用七牛、阿里云、华为云、腾讯云等文件服务 + * + * 在不采用云服务的情况下,我们有几种技术选型: + * 方案 1. 使用自建的文件服务,例如说 minIO、FastDFS 等等 + * 方案 2. 使用服务器的文件系统存储 + * 方案 3. 使用数据库进行存储 + * + * 如果考虑额外在搭建服务,推荐方案 1。 + * 对于方案 2 来说,如果要实现文件存储的高可用,需要多台服务器之间做实时同步,可以基于 rsync + inotify 来做 + * 对于方案 3 的话,实现起来最简单,但是数据库本身不适合存储海量的文件 + * + * 综合考虑,暂时使用方案 3 的方式,比较适合这样一个 all in one 的项目。 + * 随着文件的量级大了之后,还是推荐采用云服务。 + */ +package cn.iocoder.dashboard.modules.infra.framework.file; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/package-info.java new file mode 100644 index 0000000..9018262 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 infra 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.dashboard.modules.infra.framework; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/file/impl/InfFileServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/file/impl/InfFileServiceImpl.java index bedfe40..9b22733 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/file/impl/InfFileServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/file/impl/InfFileServiceImpl.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.infra.service.file.impl; import cn.hutool.core.io.FileTypeUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.file.config.FileProperties; +import cn.iocoder.dashboard.modules.infra.framework.file.config.FileProperties; import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO; import cn.iocoder.dashboard.modules.infra.dal.mysql.file.InfFileMapper; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogService.java index b486bda..d657ae7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogService.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiAccessLogFrameworkService; +import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogService.java index 270b724..2a6278c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogService.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService; +import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java index 0b80c28..35f73b8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.service.logger.impl; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiAccessLogCreateDTO; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; import cn.iocoder.dashboard.modules.infra.convert.logger.InfApiAccessLogConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java index 54268bd..7ce523c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.infra.service.logger.impl; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; import cn.iocoder.dashboard.modules.infra.convert.logger.InfApiErrorLogConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java index 1e37f2c..6c7b715 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.controller.auth; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginRespVO; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; @@ -27,8 +27,8 @@ import javax.validation.Valid; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserRoleIds; import static cn.iocoder.yudao.framework.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.util.servlet.ServletUtils.getUserAgent; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java index 9034f01..5f87e38 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/SysPostController.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.*; import cn.iocoder.dashboard.modules.system.convert.dept.SysPostConvert; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO; @@ -25,7 +25,7 @@ import java.util.Comparator; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "岗位") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java index 8f90081..4411d73 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictDataController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.dict; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.*; import cn.iocoder.dashboard.modules.system.convert.dict.SysDictDataConvert; import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictDataDO; @@ -22,7 +22,7 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "字典数据") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java index 7dca824..21e1f75 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/SysDictTypeController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.dict; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.dict.vo.type.*; import cn.iocoder.dashboard.modules.system.convert.dict.SysDictTypeConvert; import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictTypeDO; @@ -22,7 +22,7 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "字典类型") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java index 4b3d224..80d7698 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/errorcode/SysErrorCodeController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.errorcode; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.convert.errorcode.SysErrorCodeConvert; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.*; import cn.iocoder.dashboard.modules.system.dal.dataobject.errorcode.SysErrorCodeDO; @@ -22,7 +22,7 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "错误码") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java index 930c768..3758546 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysLoginLogController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExcelVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; @@ -25,7 +25,7 @@ import javax.validation.Valid; import java.io.IOException; import java.util.List; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "登陆日志") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java index ea87414..8637510 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExcelVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; @@ -33,7 +33,7 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "操作日志") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java index 3930297..0e660af 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysRoleController.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.*; import cn.iocoder.dashboard.modules.system.convert.permission.SysRoleConvert; import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO; @@ -25,7 +25,7 @@ import java.util.Comparator; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "角色") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsCallbackController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsCallbackController.java index 63b2323..3f70116 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsCallbackController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsCallbackController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.sms; import cn.hutool.core.util.URLUtil; import cn.hutool.extra.servlet.ServletUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService; import io.swagger.annotations.Api; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java index d765b7b..d2fe951 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsLogController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.sms; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExcelVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO; @@ -26,7 +26,7 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "短信日志") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java index 806f143..16745d7 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SysSmsTemplateController.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.sms; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.*; import cn.iocoder.dashboard.modules.system.convert.sms.SysSmsTemplateConvert; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO; @@ -22,7 +22,7 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api("短信模板") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java index b47dc83..4a79d08 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*; import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO; @@ -31,7 +31,7 @@ import java.io.IOException; import java.util.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "用户") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java index fc362e1..60e51ee 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java @@ -29,7 +29,7 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_IS_EMPTY; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java index 20d3e7b..b90eae2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.convert.auth; -import cn.iocoder.dashboard.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/errorcode/SysErrorCodeConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/errorcode/SysErrorCodeConvert.java index a3c93a4..118d4d5 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/errorcode/SysErrorCodeConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/errorcode/SysErrorCodeConvert.java @@ -1,8 +1,8 @@ package cn.iocoder.dashboard.modules.system.convert.errorcode; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeRespDTO; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeExcelVO; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeRespVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java index 9d88b1f..980510e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.convert.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.operatelog.core.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExcelVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogRespVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/auth/SysUserSessionDO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/auth/SysUserSessionDO.java index 874031e..4fa45e1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/auth/SysUserSessionDO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/auth/SysUserSessionDO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.dal.dataobject.auth; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.dashboard.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/logger/SysOperateLogDO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/logger/SysOperateLogDO.java index bda9b2e..2143851 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/logger/SysOperateLogDO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/logger/SysOperateLogDO.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.dal.dataobject.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum; +import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/permission/SysRoleDO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/permission/SysRoleDO.java index b214784..e6dfd74 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/permission/SysRoleDO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/permission/SysRoleDO.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.dal.dataobject.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; -import cn.iocoder.dashboard.framework.security.core.enums.DataScopeEnum; +import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum; import cn.iocoder.dashboard.modules.system.enums.permission.RoleCodeEnum; import cn.iocoder.dashboard.modules.system.enums.permission.SysRoleTypeEnum; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java index 070f65c..38cdac0 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/SysRedisKeyConstants.java @@ -1,9 +1,7 @@ package cn.iocoder.dashboard.modules.system.dal.redis; import cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine; -import cn.iocoder.dashboard.framework.security.core.LoginUser; - -import java.time.Duration; +import cn.iocoder.yudao.framework.security.core.LoginUser; import static cn.iocoder.dashboard.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java index 332a100..d960c20 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/dal/redis/auth/SysLoginUserRedisDAO.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.dal.redis.auth; -import cn.iocoder.dashboard.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.service.auth.SysUserSessionService; import cn.iocoder.yudao.framework.util.json.JsonUtils; import org.springframework.data.redis.core.StringRedisTemplate; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaConfig.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaConfig.java new file mode 100644 index 0000000..4df03f8 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaConfig.java @@ -0,0 +1,9 @@ +package cn.iocoder.dashboard.modules.system.framework.captcha.config; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(CaptchaProperties.class) +public class CaptchaConfig { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaProperties.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaProperties.java new file mode 100644 index 0000000..c3e466d --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/config/CaptchaProperties.java @@ -0,0 +1,31 @@ +package cn.iocoder.dashboard.modules.system.framework.captcha.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; +import java.time.Duration; + +@ConfigurationProperties(prefix = "yudao.captcha") +@Validated +@Data +public class CaptchaProperties { + + /** + * 验证码的过期时间 + */ + @NotNull(message = "验证码的过期时间不为空") + private Duration timeout; + /** + * 验证码的高度 + */ + @NotNull(message = "验证码的高度不能为空") + private Integer height; + /** + * 验证码的宽度 + */ + @NotNull(message = "验证码的宽度不能为空") + private Integer width; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/package-info.java new file mode 100644 index 0000000..9c4e944 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/captcha/package-info.java @@ -0,0 +1,4 @@ +/** + * 基于 Hutool captcha 库,实现验证码功能 + */ +package cn.iocoder.dashboard.modules.system.framework.captcha; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenConfiguration.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenConfiguration.java new file mode 100644 index 0000000..26faf29 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenConfiguration.java @@ -0,0 +1,9 @@ +package cn.iocoder.dashboard.modules.system.framework.codegen.config; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(CodegenProperties.class) +public class CodegenConfiguration { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenProperties.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenProperties.java new file mode 100644 index 0000000..7e174f5 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/config/CodegenProperties.java @@ -0,0 +1,28 @@ +package cn.iocoder.dashboard.modules.system.framework.codegen.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Collection; + +@ConfigurationProperties(prefix = "yudao.codegen") +@Validated +@Data +public class CodegenProperties { + + /** + * 生成的 Java 代码的基础包 + */ + @NotNull(message = "Java 代码的基础包不能为空") + private String basePackage; + + /** + * 数据库名数组 + */ + @NotEmpty(message = "数据库不能为空") + private Collection dbSchemas; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/package-info.java new file mode 100644 index 0000000..2be2578 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/codegen/package-info.java @@ -0,0 +1,4 @@ +/** + * 代码生成器 + */ +package cn.iocoder.dashboard.modules.system.framework.codegen; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/package-info.java new file mode 100644 index 0000000..3d233e1 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 system 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.dashboard.modules.system.framework; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthService.java index 04eb6d9..e51c09d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthService.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.service.auth; -import cn.iocoder.dashboard.framework.security.core.service.SecurityAuthFrameworkService; +import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionService.java index f5e1c5a..54c9470 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionService.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.service.auth; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.auth.SysUserSessionDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java index f8e60ad..860a9b9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java @@ -2,8 +2,8 @@ package cn.iocoder.dashboard.modules.system.service.auth.impl; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.dashboard.framework.security.core.LoginUser; -import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.util.monitor.TracerUtils; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java index 3752ee1..b9294f4 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysUserSessionServiceImpl.java @@ -4,9 +4,9 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.security.config.SecurityProperties; -import cn.iocoder.dashboard.framework.security.core.LoginUser; -import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; +import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.util.monitor.TracerUtils; import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.auth.SysUserSessionDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysCaptchaServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysCaptchaServiceImpl.java index 7867de1..f3be748 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysCaptchaServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/common/impl/SysCaptchaServiceImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.common.impl; import cn.hutool.captcha.CaptchaUtil; import cn.hutool.captcha.CircleCaptcha; import cn.hutool.core.util.IdUtil; -import cn.iocoder.dashboard.framework.captcha.config.CaptchaProperties; +import cn.iocoder.dashboard.modules.system.framework.captcha.config.CaptchaProperties; import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; import cn.iocoder.dashboard.modules.system.convert.common.SysCaptchaConvert; import cn.iocoder.dashboard.modules.system.dal.redis.common.SysCaptchaRedisDAO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeService.java index 6af17b6..1fdb574 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeService.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.service.errorcode; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.errorcode.core.service.ErrorCodeFrameworkService; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeExportReqVO; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodePageReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java index c0d7fd8..17e90f3 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/errorcode/impl/SysErrorCodeServiceImpl.java @@ -2,8 +2,8 @@ package cn.iocoder.dashboard.modules.system.service.errorcode.impl; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeRespDTO; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; import cn.iocoder.dashboard.modules.system.convert.errorcode.SysErrorCodeConvert; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeExportReqVO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java index 46d3293..1397a65 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogFrameworkService; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java index 8b950de..6263baf 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.logger.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.operatelog.core.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java index 6bb79c4..ed1426c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.system.service.permission; -import cn.iocoder.dashboard.framework.security.core.service.SecurityPermissionFrameworkService; +import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService; import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysMenuDO; import org.springframework.lang.Nullable; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java index 08a8ab0..45a17ee 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.permission.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ArrayUtil; -import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysRoleMenuMapper; import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysUserRoleMapper; import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysMenuDO; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java index 806ee5e..c8d84a9 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java @@ -4,7 +4,7 @@ import cn.hutool.core.thread.ThreadUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.dashboard.framework.tracer.core.annotation.BizTrace; import cn.iocoder.dashboard.modules.tool.controller.test.vo.*; import cn.iocoder.dashboard.modules.tool.convert.test.ToolTestDemoConvert; @@ -26,7 +26,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "测试示例") @RestController diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java index e46454b..45f516e 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/dal/dataobject/test/ToolTestDemoDO.java @@ -38,7 +38,7 @@ public class ToolTestDemoDO extends BaseDO { /** * 类型 * - * 枚举 {@link cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum} + * 枚举 {@link cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum} */ private Integer type; /** diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeConfiguration.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeConfiguration.java new file mode 100644 index 0000000..695f466 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeConfiguration.java @@ -0,0 +1,36 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.config; + +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.generator.ErrorCodeAutoGenerator; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.loader.ErrorCodeLoader; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.loader.ErrorCodeLoaderImpl; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.generator.ErrorCodeAutoGeneratorImpl; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * 错误码配置类 + */ +@Configuration +@EnableConfigurationProperties(ErrorCodeProperties.class) +@EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码 +public class ErrorCodeConfiguration { + + @Bean + public ErrorCodeAutoGenerator errorCodeAutoGenerator(@Value("${spring.application.name}") String applicationName, + ErrorCodeProperties errorCodeProperties, + ErrorCodeFrameworkService errorCodeFrameworkService) { + return new ErrorCodeAutoGeneratorImpl(applicationName, errorCodeProperties.getConstantsClassList(), + errorCodeFrameworkService); + } + + @Bean + public ErrorCodeLoader errorCodeLoader(@Value("${spring.application.name}") String applicationName, + ErrorCodeFrameworkService errorCodeFrameworkService) { + return new ErrorCodeLoaderImpl(applicationName, errorCodeFrameworkService); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeProperties.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeProperties.java new file mode 100644 index 0000000..b3bf2cb --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/config/ErrorCodeProperties.java @@ -0,0 +1,26 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 错误码的配置属性类 + * + * @author dlyan + */ +@ConfigurationProperties("yudao.error-code") +@Data +@Validated +public class ErrorCodeProperties { + + /** + * 错误码枚举类 + */ + @NotNull(message = "错误码枚举类不能为空") + private List constantsClassList; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java new file mode 100644 index 0000000..4ec2feb --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java @@ -0,0 +1,34 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 错误码自动生成 DTO + * + * @author dylan + */ +@Data +@Accessors(chain = true) +public class ErrorCodeAutoGenerateReqDTO { + + /** + * 应用名 + */ + @NotNull(message = "应用名不能为空") + private String applicationName; + /** + * 错误码编码 + */ + @NotNull(message = "错误码编码不能为空") + private Integer code; + /** + * 错误码错误提示 + */ + @NotEmpty(message = "错误码错误提示不能为空") + private String message; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeRespDTO.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeRespDTO.java new file mode 100644 index 0000000..78b0a6c --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/dto/ErrorCodeRespDTO.java @@ -0,0 +1,28 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto; + +import lombok.Data; + +import java.util.Date; + +/** + * 错误码的 Response DTO + * + * @author 芋道源码 + */ +@Data +public class ErrorCodeRespDTO { + + /** + * 错误码编码 + */ + private Integer code; + /** + * 错误码错误提示 + */ + private String message; + /** + * 更新时间 + */ + private Date updateTime; + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java new file mode 100644 index 0000000..a152f1f --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java @@ -0,0 +1,15 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.core.generator; + +/** + * 错误码的自动生成器 + * + * @author dylan + */ +public interface ErrorCodeAutoGenerator { + + /** + * 将配置类到错误码写入数据库 + */ + void execute(); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java new file mode 100644 index 0000000..0660de2 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java @@ -0,0 +1,98 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.core.generator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * ErrorCodeAutoGenerator 的实现类 + * 目的是,扫描指定的 {@link #constantsClassList} 类,写入到 system 服务中 + * + * @author dylan + */ +@RequiredArgsConstructor +@Slf4j +public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator { + + /** + * 应用分组 + */ + private final String applicationName; + /** + * 错误码枚举类 + */ + private final List constantsClassList; + /** + * 错误码 Service + */ + private final ErrorCodeFrameworkService errorCodeService; + + @Override + @EventListener(ApplicationReadyEvent.class) + @Async // 异步,保证项目的启动过程,毕竟非关键流程 + public void execute() { + // 第一步,解析错误码 + List autoGenerateDTOs = parseErrorCode(); + log.info("[execute][解析到错误码数量为 ({}) 个]", autoGenerateDTOs.size()); + + // 第二步,写入到 system 服务 + errorCodeService.autoGenerateErrorCodes(autoGenerateDTOs); + log.info("[execute][写入到 system 组件完成]"); + } + + /** + * 解析 constantsClassList 变量,转换成错误码数组 + * + * @return 错误码数组 + */ + private List parseErrorCode() { + // 校验 errorCodeConstantsClass 参数 + if (CollUtil.isEmpty(constantsClassList)) { + log.info("[execute][未配置 yudao.error-code.constants-class-list 配置项,不进行自动写入到 system 服务中]"); + return new ArrayList<>(); + } + + // 解析错误码 + List autoGenerateDTOs = new ArrayList<>(); + constantsClassList.forEach(constantsClass -> { + // 解析错误码枚举类 + Class errorCodeConstantsClazz = ClassUtil.loadClass(constantsClass); + // 解析错误码 + autoGenerateDTOs.addAll(parseErrorCode(errorCodeConstantsClazz)); + }); + return autoGenerateDTOs; + } + + /** + * 解析错误码类,获得错误码数组 + * + * @return 错误码数组 + */ + private List parseErrorCode(Class constantsClass) { + List autoGenerateDTOs = new ArrayList<>(); + Arrays.stream(constantsClass.getFields()).forEach(field -> { + if (field.getType() != ErrorCode.class) { + return; + } + // 转换成 ErrorCodeAutoGenerateReqDTO 对象 + ErrorCode errorCode = (ErrorCode) ReflectUtil.getFieldValue(constantsClass, field); + autoGenerateDTOs.add(new ErrorCodeAutoGenerateReqDTO().setApplicationName(applicationName) + .setCode(errorCode.getCode()).setMessage(errorCode.getMsg())); + }); + return autoGenerateDTOs; + } + +} + diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoader.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoader.java new file mode 100644 index 0000000..aac3e89 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoader.java @@ -0,0 +1,24 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.core.loader; + +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; + +/** + * 错误码加载器 + * + * 注意,错误码最终加载到 {@link ServiceExceptionUtil} 的 MESSAGES 变量中! + * + * @author dlyan + */ +public interface ErrorCodeLoader { + + /** + * 添加错误码 + * + * @param code 错误码的编号 + * @param msg 错误码的提示 + */ + default void putErrorCode(Integer code, String msg) { + ServiceExceptionUtil.put(code, msg); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java new file mode 100644 index 0000000..e9b6592 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java @@ -0,0 +1,73 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.core.loader; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.service.ErrorCodeFrameworkService; +import cn.iocoder.yudao.framework.util.date.DateUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.Date; +import java.util.List; + +/** + * ErrorCodeLoader 的实现类,从 infra 的数据库中,加载错误码。 + * + * 考虑到错误码会刷新,所以按照 {@link #REFRESH_ERROR_CODE_PERIOD} 频率,增量加载错误码。 + * + * @author dlyan + */ +@RequiredArgsConstructor +@Slf4j +public class ErrorCodeLoaderImpl implements ErrorCodeLoader { + + /** + * 刷新错误码的频率,单位:毫秒 + */ + private static final int REFRESH_ERROR_CODE_PERIOD = 60 * 1000; + + /** + * 应用分组 + */ + private final String applicationName; + /** + * 错误码 Service + */ + private final ErrorCodeFrameworkService errorCodeService; + + /** + * 缓存错误码的最大更新时间,用于后续的增量轮询,判断是否有更新 + */ + private Date maxUpdateTime; + + @EventListener(ApplicationReadyEvent.class) + public void loadErrorCodes() { + this.loadErrorCodes0(); + } + + @Scheduled(fixedDelay = REFRESH_ERROR_CODE_PERIOD, initialDelay = REFRESH_ERROR_CODE_PERIOD) + public void refreshErrorCodes() { + this.loadErrorCodes0(); + } + + private void loadErrorCodes0() { + // 加载错误码 + List errorCodeRespDTOs = errorCodeService.getErrorCodeList(applicationName, maxUpdateTime); + if (CollUtil.isEmpty(errorCodeRespDTOs)) { + return; + } + log.info("[loadErrorCodes0][加载到 ({}) 个错误码]", errorCodeRespDTOs.size()); + + // 刷新错误码的缓存 + errorCodeRespDTOs.forEach(errorCodeRespDTO -> { + // 写入到错误码的缓存 + putErrorCode(errorCodeRespDTO.getCode(), errorCodeRespDTO.getMessage()); + // 记录下更新时间,方便增量更新 + maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeRespDTO.getUpdateTime()); + }); + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/service/ErrorCodeFrameworkService.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/service/ErrorCodeFrameworkService.java new file mode 100644 index 0000000..30b707a --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/core/service/ErrorCodeFrameworkService.java @@ -0,0 +1,35 @@ +package cn.iocoder.dashboard.modules.tool.framework.errorcode.core.service; + +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeRespDTO; + +import javax.validation.Valid; +import java.util.Date; +import java.util.List; + +/** + * 错误码 Framework Service 接口 + * + * @author 芋道源码 + */ +public interface ErrorCodeFrameworkService { + + /** + * 自动创建错误码 + * + * @param autoGenerateDTOs 错误码信息 + */ + void autoGenerateErrorCodes(@Valid List autoGenerateDTOs); + + /** + * 增量获得错误码数组 + * + * 如果 minUpdateTime 为空时,则获取所有错误码 + * + * @param applicationName 应用名 + * @param minUpdateTime 最小更新时间 + * @return 错误码数组 + */ + List getErrorCodeList(String applicationName, Date minUpdateTime); + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/package-info.java new file mode 100644 index 0000000..7d75bc3 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/errorcode/package-info.java @@ -0,0 +1,6 @@ +/** + * 错误码组件 + * + * 将错误码缓存在内存中,同时通过定时器每 n 分钟更新 + */ +package cn.iocoder.dashboard.modules.tool.framework.errorcode; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/package-info.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/package-info.java new file mode 100644 index 0000000..3c4ce27 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 tool 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.dashboard.modules.tool.framework; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java index 51e9f32..b70f823 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngine.java @@ -9,12 +9,12 @@ import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.codegen.config.CodegenProperties; +import cn.iocoder.dashboard.modules.system.framework.codegen.config.CodegenProperties; import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat; import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert; import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; -import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; diff --git a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java index e89970d..f50ec78 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.tool.service.codegen.impl; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.codegen.config.CodegenProperties; +import cn.iocoder.dashboard.modules.system.framework.codegen.config.CodegenProperties; import cn.iocoder.dashboard.modules.tool.controller.codegen.vo.ToolCodegenUpdateReqVO; import cn.iocoder.dashboard.modules.tool.controller.codegen.vo.table.ToolCodegenTablePageReqVO; import cn.iocoder.dashboard.modules.tool.convert.codegen.ToolCodegenConvert; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java index 4bb665c..f15d82e 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/file/InfFileServiceTest.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.infra.service.file; import cn.hutool.core.io.resource.ResourceUtil; import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.file.config.FileProperties; +import cn.iocoder.dashboard.modules.infra.framework.file.config.FileProperties; import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO; import cn.iocoder.dashboard.modules.infra.dal.mysql.file.InfFileMapper; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java index d91e685..f919016 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java @@ -5,7 +5,7 @@ import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiAccessLogCreateDTO; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java index 4685050..040fa40 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java @@ -4,7 +4,7 @@ import cn.hutool.core.util.RandomUtil; import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java index e6cfabe..9be405a 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.service.auth; import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.dashboard.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java index efbca5d..e812697 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysUserSessionServiceImplTest.java @@ -29,8 +29,8 @@ import cn.hutool.core.date.DateUtil; import cn.iocoder.dashboard.BaseDbAndRedisUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.security.config.SecurityProperties; -import cn.iocoder.dashboard.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.controller.auth.vo.session.SysUserSessionPageReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.auth.SysUserSessionDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java index 5350cd3..d397ef1 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.service.common; import cn.iocoder.dashboard.BaseRedisUnitTest; -import cn.iocoder.dashboard.framework.captcha.config.CaptchaProperties; +import cn.iocoder.dashboard.modules.system.framework.captcha.config.CaptchaProperties; import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; import cn.iocoder.dashboard.modules.system.dal.redis.common.SysCaptchaRedisDAO; import cn.iocoder.dashboard.modules.system.service.common.impl.SysCaptchaServiceImpl; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java index 74e1471..701fb85 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/errorcode/SysErrorCodeServiceTest.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.service.errorcode; import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; +import cn.iocoder.dashboard.modules.tool.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; import cn.iocoder.dashboard.modules.infra.enums.config.InfConfigTypeEnum; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.errorcode.vo.SysErrorCodeExportReqVO; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java index aee0fd7..d51b58f 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.service.logger; import cn.hutool.core.util.RandomUtil; import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; +import cn.iocoder.yudao.framework.util.monitor.TracerUtils; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java index d720734..e118ae7 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java @@ -5,9 +5,9 @@ import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum; -import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; -import cn.iocoder.dashboard.framework.logger.operatelog.core.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; +import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO; import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO; diff --git a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java index 72ea726..7cc87a3 100644 --- a/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java +++ b/yudao-admin-server/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleServiceTest.java @@ -4,7 +4,7 @@ import cn.hutool.core.bean.BeanUtil; import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.dashboard.framework.security.core.enums.DataScopeEnum; +import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum; import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.SysRoleCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.SysRolePageReqVO; import cn.iocoder.dashboard.modules.system.controller.permission.vo.role.SysRoleUpdateReqVO; diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 632e43e..c2ee169 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -80,6 +80,18 @@ + cn.iocoder.boot + yudao-spring-boot-starter-web + ${revision} + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + ${revision} + + + com.github.xiaoymin knife4j-spring-boot-starter ${knife4j.version} @@ -108,7 +120,7 @@ cn.iocoder.boot yudao-spring-boot-starter-mybatis - 1.0.0 + ${revision} @@ -149,6 +161,12 @@ + cn.iocoder.boot + yudao-spring-boot-starter-protection + ${revision} + + + com.baomidou lock4j-redisson-spring-boot-starter ${lock4j.version} @@ -162,12 +180,23 @@ io.github.resilience4j + resilience4j-ratelimiter + ${resilience4j.version} + + + io.github.resilience4j resilience4j-spring-boot2 ${resilience4j.version} + cn.iocoder.boot + yudao-spring-boot-starter-monitor + ${revision} + + + org.apache.skywalking apm-toolkit-trace ${skywalking.version} @@ -227,6 +256,12 @@ + cn.iocoder.boot + yudao-spring-boot-starter-operatelog + ${revision} + + + org.projectlombok lombok ${lombok.version} diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index e2d6889..cd02578 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -13,6 +13,11 @@ yudao-common yudao-framework-all yudao-spring-boot-starter-mybatis + yudao-spring-boot-starter-web + yudao-spring-boot-starter-security + yudao-spring-boot-starter-monitor + yudao-spring-boot-starter-protection + yudao-spring-boot-starter-operatelog yudao-framework diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index f799c3d..17d971c 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -57,6 +57,12 @@ provided + + + org.apache.skywalking + apm-toolkit-trace + + org.projectlombok diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java new file mode 100644 index 0000000..6ad94a3 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/WebFilterOrderEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.common.enums; + +/** + * Web 过滤器顺序的枚举类,保证过滤器按照符合我们的预期 + * + * 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 util 包下 + * + * @author 芋道源码 + */ +public interface WebFilterOrderEnum { + + int CORS_FILTER = Integer.MIN_VALUE; + + int TRACE_FILTER = CORS_FILTER + 1; + + int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500; + + // OrderedRequestContextFilter 默认为 -105,用于国际化上下文等等 + + int API_ACCESS_LOG_FILTER = -104; // 需要保证在 RequestBodyCacheFilter 后面 + + int XSS_FILTER = -103; // 需要保证在 RequestBodyCacheFilter 后面 + + // Spring Security Filter 默认为 -100,可见 SecurityProperties 配置属性类 + + int DEMO_FILTER = Integer.MAX_VALUE; + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java new file mode 100644 index 0000000..384a3df --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/util/monitor/TracerUtils.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.framework.util.monitor; + +import org.apache.skywalking.apm.toolkit.trace.TraceContext; + +/** + * 链路追踪工具类 + * + * 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 util 包下 + * + * @author 芋道源码 + */ +public class TracerUtils { + + /** + * 私有化构造方法 + */ + private TracerUtils() { + } + + /** + * 获得链路追踪编号,直接返回 SkyWalking 的 TraceId。 + * 如果不存在的话为空字符串!!! + * + * @return 链路追踪编号 + */ + public static String getTraceId() { + return TraceContext.traceId(); + } + +} diff --git a/yudao-framework/yudao-framework-all/pom.xml b/yudao-framework/yudao-framework-all/pom.xml index a656755..5bca4c8 100644 --- a/yudao-framework/yudao-framework-all/pom.xml +++ b/yudao-framework/yudao-framework-all/pom.xml @@ -24,35 +24,7 @@ true - - org.springframework.boot - spring-boot-starter-aop - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-security - - - - org.springframework.boot - spring-boot-starter-validation - - - - com.github.xiaoymin - knife4j-spring-boot-starter - - - io.swagger - swagger-annotations - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaConfig.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaConfig.java deleted file mode 100644 index b1fb8f2..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaConfig.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.dashboard.framework.captcha.config; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@EnableConfigurationProperties(CaptchaProperties.class) -public class CaptchaConfig { -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaProperties.java deleted file mode 100644 index 9530ea1..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/config/CaptchaProperties.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.dashboard.framework.captcha.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -import javax.validation.constraints.NotNull; -import java.time.Duration; - -@ConfigurationProperties(prefix = "yudao.captcha") -@Validated -@Data -public class CaptchaProperties { - - /** - * 验证码的过期时间 - */ - @NotNull(message = "验证码的过期时间不为空") - private Duration timeout; - /** - * 验证码的高度 - */ - @NotNull(message = "验证码的高度不能为空") - private Integer height; - /** - * 验证码的宽度 - */ - @NotNull(message = "验证码的宽度不能为空") - private Integer width; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/package-info.java deleted file mode 100644 index 432e3d4..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/captcha/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 基于 Hutool captcha 库,实现验证码功能 - */ -package cn.iocoder.dashboard.framework.captcha; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenConfiguration.java deleted file mode 100644 index 7e357bc..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenConfiguration.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.dashboard.framework.codegen.config; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@EnableConfigurationProperties(CodegenProperties.class) -public class CodegenConfiguration { -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenProperties.java deleted file mode 100644 index 8b77bbf..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/config/CodegenProperties.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.dashboard.framework.codegen.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.util.Collection; - -@ConfigurationProperties(prefix = "yudao.codegen") -@Validated -@Data -public class CodegenProperties { - - /** - * 生成的 Java 代码的基础包 - */ - @NotNull(message = "Java 代码的基础包不能为空") - private String basePackage; - - /** - * 数据库名数组 - */ - @NotEmpty(message = "数据库不能为空") - private Collection dbSchemas; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/package-info.java deleted file mode 100644 index 29f1464..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/codegen/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 代码生成器 - */ -package cn.iocoder.dashboard.framework.codegen; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeConfiguration.java deleted file mode 100644 index 21e967e..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeConfiguration.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.config; - -import cn.iocoder.dashboard.framework.errorcode.core.generator.ErrorCodeAutoGenerator; -import cn.iocoder.dashboard.framework.errorcode.core.loader.ErrorCodeLoader; -import cn.iocoder.dashboard.framework.errorcode.core.service.ErrorCodeFrameworkService; -import cn.iocoder.dashboard.framework.errorcode.core.loader.ErrorCodeLoaderImpl; -import cn.iocoder.dashboard.framework.errorcode.core.generator.ErrorCodeAutoGeneratorImpl; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableScheduling; - -/** - * 错误码配置类 - */ -@Configuration -@EnableConfigurationProperties(ErrorCodeProperties.class) -@EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码 -public class ErrorCodeConfiguration { - - @Bean - public ErrorCodeAutoGenerator errorCodeAutoGenerator(@Value("${spring.application.name}") String applicationName, - ErrorCodeProperties errorCodeProperties, - ErrorCodeFrameworkService errorCodeFrameworkService) { - return new ErrorCodeAutoGeneratorImpl(applicationName, errorCodeProperties.getConstantsClassList(), - errorCodeFrameworkService); - } - - @Bean - public ErrorCodeLoader errorCodeLoader(@Value("${spring.application.name}") String applicationName, - ErrorCodeFrameworkService errorCodeFrameworkService) { - return new ErrorCodeLoaderImpl(applicationName, errorCodeFrameworkService); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeProperties.java deleted file mode 100644 index 2f629a2..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/config/ErrorCodeProperties.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -import javax.validation.constraints.NotNull; -import java.util.List; - -/** - * 错误码的配置属性类 - * - * @author dlyan - */ -@ConfigurationProperties("yudao.error-code") -@Data -@Validated -public class ErrorCodeProperties { - - /** - * 错误码枚举类 - */ - @NotNull(message = "错误码枚举类不能为空") - private List constantsClassList; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java deleted file mode 100644 index c89744d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeAutoGenerateReqDTO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.core.dto; - -import lombok.Data; -import lombok.experimental.Accessors; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -/** - * 错误码自动生成 DTO - * - * @author dylan - */ -@Data -@Accessors(chain = true) -public class ErrorCodeAutoGenerateReqDTO { - - /** - * 应用名 - */ - @NotNull(message = "应用名不能为空") - private String applicationName; - /** - * 错误码编码 - */ - @NotNull(message = "错误码编码不能为空") - private Integer code; - /** - * 错误码错误提示 - */ - @NotEmpty(message = "错误码错误提示不能为空") - private String message; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeRespDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeRespDTO.java deleted file mode 100644 index d54064b..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/dto/ErrorCodeRespDTO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.core.dto; - -import lombok.Data; - -import java.util.Date; - -/** - * 错误码的 Response DTO - * - * @author 芋道源码 - */ -@Data -public class ErrorCodeRespDTO { - - /** - * 错误码编码 - */ - private Integer code; - /** - * 错误码错误提示 - */ - private String message; - /** - * 更新时间 - */ - private Date updateTime; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java deleted file mode 100644 index 530ff9c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.core.generator; - -/** - * 错误码的自动生成器 - * - * @author dylan - */ -public interface ErrorCodeAutoGenerator { - - /** - * 将配置类到错误码写入数据库 - */ - void execute(); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java deleted file mode 100644 index cce51b0..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.core.generator; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ClassUtil; -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.dashboard.framework.errorcode.core.service.ErrorCodeFrameworkService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.scheduling.annotation.Async; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * ErrorCodeAutoGenerator 的实现类 - * 目的是,扫描指定的 {@link #constantsClassList} 类,写入到 system 服务中 - * - * @author dylan - */ -@RequiredArgsConstructor -@Slf4j -public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator { - - /** - * 应用分组 - */ - private final String applicationName; - /** - * 错误码枚举类 - */ - private final List constantsClassList; - /** - * 错误码 Service - */ - private final ErrorCodeFrameworkService errorCodeService; - - @Override - @EventListener(ApplicationReadyEvent.class) - @Async // 异步,保证项目的启动过程,毕竟非关键流程 - public void execute() { - // 第一步,解析错误码 - List autoGenerateDTOs = parseErrorCode(); - log.info("[execute][解析到错误码数量为 ({}) 个]", autoGenerateDTOs.size()); - - // 第二步,写入到 system 服务 - errorCodeService.autoGenerateErrorCodes(autoGenerateDTOs); - log.info("[execute][写入到 system 组件完成]"); - } - - /** - * 解析 constantsClassList 变量,转换成错误码数组 - * - * @return 错误码数组 - */ - private List parseErrorCode() { - // 校验 errorCodeConstantsClass 参数 - if (CollUtil.isEmpty(constantsClassList)) { - log.info("[execute][未配置 yudao.error-code.constants-class-list 配置项,不进行自动写入到 system 服务中]"); - return new ArrayList<>(); - } - - // 解析错误码 - List autoGenerateDTOs = new ArrayList<>(); - constantsClassList.forEach(constantsClass -> { - // 解析错误码枚举类 - Class errorCodeConstantsClazz = ClassUtil.loadClass(constantsClass); - // 解析错误码 - autoGenerateDTOs.addAll(parseErrorCode(errorCodeConstantsClazz)); - }); - return autoGenerateDTOs; - } - - /** - * 解析错误码类,获得错误码数组 - * - * @return 错误码数组 - */ - private List parseErrorCode(Class constantsClass) { - List autoGenerateDTOs = new ArrayList<>(); - Arrays.stream(constantsClass.getFields()).forEach(field -> { - if (field.getType() != ErrorCode.class) { - return; - } - // 转换成 ErrorCodeAutoGenerateReqDTO 对象 - ErrorCode errorCode = (ErrorCode) ReflectUtil.getFieldValue(constantsClass, field); - autoGenerateDTOs.add(new ErrorCodeAutoGenerateReqDTO().setApplicationName(applicationName) - .setCode(errorCode.getCode()).setMessage(errorCode.getMsg())); - }); - return autoGenerateDTOs; - } - -} - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoader.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoader.java deleted file mode 100644 index e945e23..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoader.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.core.loader; - -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; - -/** - * 错误码加载器 - * - * 注意,错误码最终加载到 {@link ServiceExceptionUtil} 的 MESSAGES 变量中! - * - * @author dlyan - */ -public interface ErrorCodeLoader { - - /** - * 添加错误码 - * - * @param code 错误码的编号 - * @param msg 错误码的提示 - */ - default void putErrorCode(Integer code, String msg) { - ServiceExceptionUtil.put(code, msg); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java deleted file mode 100644 index f05ef4c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java +++ /dev/null @@ -1,73 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.core.loader; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeRespDTO; -import cn.iocoder.dashboard.framework.errorcode.core.service.ErrorCodeFrameworkService; -import cn.iocoder.yudao.framework.util.date.DateUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.event.EventListener; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.Date; -import java.util.List; - -/** - * ErrorCodeLoader 的实现类,从 infra 的数据库中,加载错误码。 - * - * 考虑到错误码会刷新,所以按照 {@link #REFRESH_ERROR_CODE_PERIOD} 频率,增量加载错误码。 - * - * @author dlyan - */ -@RequiredArgsConstructor -@Slf4j -public class ErrorCodeLoaderImpl implements ErrorCodeLoader { - - /** - * 刷新错误码的频率,单位:毫秒 - */ - private static final int REFRESH_ERROR_CODE_PERIOD = 60 * 1000; - - /** - * 应用分组 - */ - private final String applicationName; - /** - * 错误码 Service - */ - private final ErrorCodeFrameworkService errorCodeService; - - /** - * 缓存错误码的最大更新时间,用于后续的增量轮询,判断是否有更新 - */ - private Date maxUpdateTime; - - @EventListener(ApplicationReadyEvent.class) - public void loadErrorCodes() { - this.loadErrorCodes0(); - } - - @Scheduled(fixedDelay = REFRESH_ERROR_CODE_PERIOD, initialDelay = REFRESH_ERROR_CODE_PERIOD) - public void refreshErrorCodes() { - this.loadErrorCodes0(); - } - - private void loadErrorCodes0() { - // 加载错误码 - List errorCodeRespDTOs = errorCodeService.getErrorCodeList(applicationName, maxUpdateTime); - if (CollUtil.isEmpty(errorCodeRespDTOs)) { - return; - } - log.info("[loadErrorCodes0][加载到 ({}) 个错误码]", errorCodeRespDTOs.size()); - - // 刷新错误码的缓存 - errorCodeRespDTOs.forEach(errorCodeRespDTO -> { - // 写入到错误码的缓存 - putErrorCode(errorCodeRespDTO.getCode(), errorCodeRespDTO.getMessage()); - // 记录下更新时间,方便增量更新 - maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeRespDTO.getUpdateTime()); - }); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/service/ErrorCodeFrameworkService.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/service/ErrorCodeFrameworkService.java deleted file mode 100644 index 53f3f2c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/core/service/ErrorCodeFrameworkService.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.dashboard.framework.errorcode.core.service; - -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.dashboard.framework.errorcode.core.dto.ErrorCodeRespDTO; - -import javax.validation.Valid; -import java.util.Date; -import java.util.List; - -/** - * 错误码 Framework Service 接口 - * - * @author 芋道源码 - */ -public interface ErrorCodeFrameworkService { - - /** - * 自动创建错误码 - * - * @param autoGenerateDTOs 错误码信息 - */ - void autoGenerateErrorCodes(@Valid List autoGenerateDTOs); - - /** - * 增量获得错误码数组 - * - * 如果 minUpdateTime 为空时,则获取所有错误码 - * - * @param applicationName 应用名 - * @param minUpdateTime 最小更新时间 - * @return 错误码数组 - */ - List getErrorCodeList(String applicationName, Date minUpdateTime); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/package-info.java deleted file mode 100644 index 18ec4eb..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/errorcode/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 错误码组件 - * - * 将错误码缓存在内存中,同时通过定时器每 n 分钟更新 - */ -package cn.iocoder.dashboard.framework.errorcode; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileConfiguration.java deleted file mode 100644 index 673c3d2..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileConfiguration.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.dashboard.framework.file.config; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -/** - * 文件 配置类 - */ -@Configuration -@EnableConfigurationProperties(FileProperties.class) -public class FileConfiguration { -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileProperties.java deleted file mode 100644 index 318a97f..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/config/FileProperties.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.dashboard.framework.file.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -import javax.validation.constraints.NotNull; - -@ConfigurationProperties(prefix = "yudao.file") -@Validated -@Data -public class FileProperties { - - /** - * 对应 InfFileController 的 getFile 方法 - */ - @NotNull(message = "基础文件路径不能为空") - private String basePath; - - // TODO 七牛、等等 - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/package-info.java deleted file mode 100644 index 1c2900f..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/file/package-info.java +++ /dev/null @@ -1,16 +0,0 @@ -/** - * 文件的存储,推荐使用七牛、阿里云、华为云、腾讯云等文件服务 - * - * 在不采用云服务的情况下,我们有几种技术选型: - * 方案 1. 使用自建的文件服务,例如说 minIO、FastDFS 等等 - * 方案 2. 使用服务器的文件系统存储 - * 方案 3. 使用数据库进行存储 - * - * 如果考虑额外在搭建服务,推荐方案 1。 - * 对于方案 2 来说,如果要实现文件存储的高可用,需要多台服务器之间做实时同步,可以基于 rsync + inotify 来做 - * 对于方案 3 的话,实现起来最简单,但是数据库本身不适合存储海量的文件 - * - * 综合考虑,暂时使用方案 3 的方式,比较适合这样一个 all in one 的项目。 - * 随着文件的量级大了之后,还是推荐采用云服务。 - */ -package cn.iocoder.dashboard.framework.file; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/config/JacksonConfig.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/config/JacksonConfig.java deleted file mode 100644 index 1930ca2..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/config/JacksonConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.dashboard.framework.jackson.config; - -import cn.iocoder.dashboard.framework.jackson.deser.LocalDateTimeDeserializer; -import cn.iocoder.dashboard.framework.jackson.ser.LocalDateTimeSerializer; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.time.LocalDateTime; - -@Configuration -public class JacksonConfig { - - @Bean - @SuppressWarnings("InstantiationOfUtilityClass") - public JsonUtils jsonUtils(ObjectMapper objectMapper) { - SimpleModule simpleModule = new SimpleModule(); - /* - * 1. 新增Long类型序列化规则,数值超过2^53-1,在JS会出现精度丢失问题,因此Long自动序列化为字符串类型 - * 2. 新增LocalDateTime序列化、反序列化规则 - */ - simpleModule -// .addSerializer(Long.class, ToStringSerializer.instance) -// .addSerializer(Long.TYPE, ToStringSerializer.instance) - .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE) - .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE); - - objectMapper.registerModules(simpleModule); - - JsonUtils.init(objectMapper); - return new JsonUtils(); - } -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/deser/LocalDateTimeDeserializer.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/deser/LocalDateTimeDeserializer.java deleted file mode 100644 index 122f461..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/deser/LocalDateTimeDeserializer.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.dashboard.framework.jackson.deser; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; - -import java.io.IOException; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; - -/** - * LocalDateTime反序列化规则 - *

- * 会将毫秒级时间戳反序列化为LocalDateTime - */ -public class LocalDateTimeDeserializer extends JsonDeserializer { - - public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer(); - - @Override - public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault()); - } -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/ser/LocalDateTimeSerializer.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/ser/LocalDateTimeSerializer.java deleted file mode 100644 index d7230ea..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/jackson/ser/LocalDateTimeSerializer.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.dashboard.framework.jackson.ser; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -import java.io.IOException; -import java.time.LocalDateTime; -import java.time.ZoneId; - -/** - * LocalDateTime序列化规则 - *

- * 会将LocalDateTime序列化为毫秒级时间戳 - */ -public class LocalDateTimeSerializer extends JsonSerializer { - - public static final LocalDateTimeSerializer INSTANCE = new LocalDateTimeSerializer(); - - @Override - public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); - } -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/config/ApiLogConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/config/ApiLogConfiguration.java deleted file mode 100644 index df5a5db..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/config/ApiLogConfiguration.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.apilog.config; - -import cn.iocoder.dashboard.framework.logger.apilog.core.filter.ApiAccessLogFilter; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiAccessLogFrameworkService; -import cn.iocoder.dashboard.framework.web.config.WebProperties; -import cn.iocoder.dashboard.framework.web.core.enums.FilterOrderEnum; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.servlet.Filter; - -@Configuration -public class ApiLogConfiguration { - - /** - * 创建 ApiAccessLogFilter Bean,记录 API 请求日志 - */ - @Bean - public FilterRegistrationBean apiAccessLogFilter(WebProperties webProperties, - @Value("${spring.application.name}") String applicationName, - ApiAccessLogFrameworkService apiAccessLogFrameworkService) { - ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogFrameworkService); - return createFilterBean(filter, FilterOrderEnum.API_ACCESS_LOG_FILTER); - } - - private static FilterRegistrationBean createFilterBean(T filter, Integer order) { - FilterRegistrationBean bean = new FilterRegistrationBean<>(filter); - bean.setOrder(order); - return bean; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java deleted file mode 100644 index 4381a7c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java +++ /dev/null @@ -1,112 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.apilog.core.filter; - -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.map.MapUtil; -import cn.hutool.extra.servlet.ServletUtil; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiAccessLogFrameworkService; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiAccessLogCreateDTO; -import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; -import cn.iocoder.dashboard.framework.web.config.WebProperties; -import cn.iocoder.dashboard.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.framework.util.date.DateUtils; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -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; -import java.util.Date; -import java.util.Map; - -/** - * API 访问日志 Filter - * - * @author 芋道源码 - */ -@RequiredArgsConstructor -@Slf4j -public class ApiAccessLogFilter extends OncePerRequestFilter { - - private final WebProperties webProperties; - private final String applicationName; - - private final ApiAccessLogFrameworkService apiAccessLogFrameworkService; - - @Override - protected boolean shouldNotFilter(HttpServletRequest request) { - // 只过滤 API 请求的地址 - return !request.getRequestURI().startsWith(webProperties.getApiPrefix()); - } - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - // 获得开始时间 - Date beginTim = new Date(); - // 提前获得参数,避免 XssFilter 过滤处理 - Map queryString = ServletUtil.getParamMap(request); - String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtil.getBody(request) : null; - - try { - // 继续过滤器 - filterChain.doFilter(request, response); - // 正常执行,记录日志 - createApiAccessLog(request, beginTim, queryString, requestBody, null); - } catch (Exception ex) { - // 异常执行,记录日志 - createApiAccessLog(request, beginTim, queryString, requestBody, ex); - throw ex; - } - } - - private void createApiAccessLog(HttpServletRequest request, Date beginTime, - Map queryString, String requestBody, Exception ex) { - ApiAccessLogCreateDTO accessLog = new ApiAccessLogCreateDTO(); - try { - this.buildApiAccessLogDTO(accessLog, request, beginTime, queryString, requestBody, ex); - apiAccessLogFrameworkService.createApiAccessLogAsync(accessLog); - } catch (Throwable th) { - log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), JsonUtils.toJsonString(accessLog), th); - } - } - - private void buildApiAccessLogDTO(ApiAccessLogCreateDTO accessLog, HttpServletRequest request, Date beginTime, - Map queryString, String requestBody, Exception ex) { - // 处理用户信息 - accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); - accessLog.setUserType(WebFrameworkUtils.getUserType(request)); - // 设置访问结果 - CommonResult result = WebFrameworkUtils.getCommonResult(request); - if (result != null) { - accessLog.setResultCode(result.getCode()); - accessLog.setResultMsg(result.getMsg()); - } else if (ex != null) { - accessLog.setResultCode(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode()); - accessLog.setResultMsg(ExceptionUtil.getRootCauseMessage(ex)); - } else { - accessLog.setResultCode(0); - accessLog.setResultMsg(""); - } - // 设置其它字段 - accessLog.setTraceId(TracerUtils.getTraceId()); - accessLog.setApplicationName(applicationName); - accessLog.setRequestUrl(request.getRequestURI()); - Map requestParams = MapUtil.builder().put("query", queryString).put("body", requestBody).build(); - accessLog.setRequestParams(JsonUtils.toJsonString(requestParams)); - accessLog.setRequestMethod(request.getMethod()); - accessLog.setUserAgent(ServletUtils.getUserAgent(request)); - accessLog.setUserIp(ServletUtil.getClientIP(request)); - // 持续时间 - accessLog.setBeginTime(beginTime); - accessLog.setEndTime(new Date()); - accessLog.setDuration((int) DateUtils.diff(accessLog.getEndTime(), accessLog.getBeginTime())); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java deleted file mode 100644 index ecafe55..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.apilog.core.service; - -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiAccessLogCreateDTO; - -import javax.validation.Valid; -import java.util.concurrent.Future; - -/** - * API 访问日志 Framework Service 接口 - * - * @author 芋道源码 - */ -public interface ApiAccessLogFrameworkService { - - /** - * 创建 API 访问日志 - * - * @param createDTO 创建信息 - * @return 是否创建成功 - */ - Future createApiAccessLogAsync(@Valid ApiAccessLogCreateDTO createDTO); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java deleted file mode 100644 index 763db3a..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.apilog.core.service; - -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; - -import javax.validation.Valid; -import java.util.concurrent.Future; - -/** - * API 错误日志 Framework Service 接口 - * - * @author 芋道源码 - */ -public interface ApiErrorLogFrameworkService { - - /** - * 创建 API 错误日志 - * - * @param createDTO 创建信息 - * @return 是否创建成功 - */ - Future createApiErrorLogAsync(@Valid ApiErrorLogCreateDTO createDTO); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiAccessLogCreateDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiAccessLogCreateDTO.java deleted file mode 100644 index e288d9b..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiAccessLogCreateDTO.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.apilog.core.service.dto; - -import lombok.Data; - -import javax.validation.constraints.NotNull; -import java.util.Date; - -/** - * API 访问日志创建 DTO - * - * @author 芋道源码 - */ -@Data -public class ApiAccessLogCreateDTO { - - /** - * 链路追踪编号 - */ - private String traceId; - /** - * 用户编号 - */ - private Long userId; - /** - * 用户类型 - */ - private Integer userType; - /** - * 应用名 - */ - @NotNull(message = "应用名不能为空") - private String applicationName; - - /** - * 请求方法名 - */ - @NotNull(message = "http 请求方法不能为空") - private String requestMethod; - /** - * 访问地址 - */ - @NotNull(message = "访问地址不能为空") - private String requestUrl; - /** - * 请求参数 - */ - @NotNull(message = "请求参数不能为空") - private String requestParams; - /** - * 用户 IP - */ - @NotNull(message = "ip 不能为空") - private String userIp; - /** - * 浏览器 UA - */ - @NotNull(message = "User-Agent 不能为空") - private String userAgent; - - /** - * 开始请求时间 - */ - @NotNull(message = "开始请求时间不能为空") - private Date beginTime; - /** - * 结束请求时间 - */ - @NotNull(message = "结束请求时间不能为空") - private Date endTime; - /** - * 执行时长,单位:毫秒 - */ - @NotNull(message = "执行时长不能为空") - private Integer duration; - /** - * 结果码 - */ - @NotNull(message = "错误码不能为空") - private Integer resultCode; - /** - * 结果提示 - */ - private String resultMsg; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiErrorLogCreateDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiErrorLogCreateDTO.java deleted file mode 100644 index b351acf..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/dto/ApiErrorLogCreateDTO.java +++ /dev/null @@ -1,109 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.apilog.core.service.dto; - -import lombok.Data; -import lombok.experimental.Accessors; - -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.Date; - -/** - * API 错误日志创建 DTO - * - * @author 芋道源码 - */ -@Data -@Accessors(chain = true) -public class ApiErrorLogCreateDTO implements Serializable { - - /** - * 链路编号 - */ - private String traceId; - /** - * 账号编号 - */ - private Long userId; - /** - * 用户类型 - */ - private Integer userType; - /** - * 应用名 - */ - @NotNull(message = "应用名不能为空") - private String applicationName; - - /** - * 请求方法名 - */ - @NotNull(message = "http 请求方法不能为空") - private String requestMethod; - /** - * 访问地址 - */ - @NotNull(message = "访问地址不能为空") - private String requestUrl; - /** - * 请求参数 - */ - @NotNull(message = "请求参数不能为空") - private String requestParams; - /** - * 用户 IP - */ - @NotNull(message = "ip 不能为空") - private String userIp; - /** - * 浏览器 UA - */ - @NotNull(message = "User-Agent 不能为空") - private String userAgent; - - /** - * 异常时间 - */ - @NotNull(message = "异常时间不能为空") - private Date exceptionTime; - /** - * 异常名 - */ - @NotNull(message = "异常名不能为空") - private String exceptionName; - /** - * 异常发生的类全名 - */ - @NotNull(message = "异常发生的类全名不能为空") - private String exceptionClassName; - /** - * 异常发生的类文件 - */ - @NotNull(message = "异常发生的类文件不能为空") - private String exceptionFileName; - /** - * 异常发生的方法名 - */ - @NotNull(message = "异常发生的方法名不能为空") - private String exceptionMethodName; - /** - * 异常发生的方法所在行 - */ - @NotNull(message = "异常发生的方法所在行不能为空") - private Integer exceptionLineNumber; - /** - * 异常的栈轨迹异常的栈轨迹 - */ - @NotNull(message = "异常的栈轨迹不能为空") - private String exceptionStackTrace; - /** - * 异常导致的根消息 - */ - @NotNull(message = "异常导致的根消息不能为空") - private String exceptionRootCauseMessage; - /** - * 异常导致的消息 - */ - @NotNull(message = "异常导致的消息不能为空") - private String exceptionMessage; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/config/OperateLogConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/config/OperateLogConfiguration.java deleted file mode 100644 index ff9a35a..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/config/OperateLogConfiguration.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.operatelog.config; - -import cn.iocoder.dashboard.framework.logger.operatelog.core.aop.OperateLogAspect; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class OperateLogConfiguration { - - @Bean - public OperateLogAspect operateLogAspect() { - return new OperateLogAspect(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java deleted file mode 100644 index 6dc3c09..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.operatelog.core.annotations; - -import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 操作日志注解 - * - * @author 芋道源码 - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface OperateLog { - - // ========== 模块字段 ========== - - /** - * 操作模块 - * - * 为空时,会尝试读取 {@link Api#value()} 属性 - */ - String module() default ""; - /** - * 操作名 - * - * 为空时,会尝试读取 {@link ApiOperation#value()} 属性 - */ - String name() default ""; - /** - * 操作分类 - * - * 实际并不是数组,因为枚举不能设置 null 作为默认值 - */ - OperateTypeEnum[] type() default {}; - - // ========== 开关字段 ========== - - /** - * 是否记录操作日志 - */ - boolean enable() default true; - /** - * 是否记录方法参数 - */ - boolean logArgs() default true; - /** - * 是否记录方法结果的数据 - */ - boolean logResultData() default true; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java deleted file mode 100644 index da9dc5c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java +++ /dev/null @@ -1,354 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.operatelog.core.aop; - -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.servlet.ServletUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; -import cn.iocoder.dashboard.framework.logger.operatelog.core.dto.OperateLogCreateReqDTO; -import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum; -import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogFrameworkService; -import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import com.google.common.collect.Maps; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.util.*; -import java.util.function.Predicate; -import java.util.stream.IntStream; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; - -/** - * 拦截使用 @OperateLog 注解,如果满足条件,则生成操作日志。 - * 满足如下任一条件,则会进行记录: - * 1. 使用 @ApiOperation + 非 @GetMapping - * 2. 使用 @OperateLog 注解 - * - * 但是,如果声明 @OperateLog 注解时,将 enable 属性设置为 false 时,强制不记录。 - * - * @author 芋道源码 - */ -@Aspect -@Slf4j -public class OperateLogAspect { - - /** - * 用于记录操作内容的上下文 - * - * @see OperateLogCreateReqDTO#getContent() - */ - private static final ThreadLocal CONTENT = new ThreadLocal<>(); - /** - * 用于记录拓展字段的上下文 - * - * @see OperateLogCreateReqDTO#getExts() - */ - private static final ThreadLocal> EXTS = new ThreadLocal<>(); - - @Resource - private OperateLogFrameworkService operateLogFrameworkService; - - @Around("@annotation(apiOperation)") - public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable { - // 可能也添加了 @ApiOperation 注解 - OperateLog operateLog = getMethodAnnotation(joinPoint, OperateLog.class); - return around0(joinPoint, operateLog, apiOperation); - } - - @Around("!@annotation(io.swagger.annotations.ApiOperation) && @annotation(operateLog)") // 兼容处理,只添加 @OperateLog 注解的情况 - public Object around(ProceedingJoinPoint joinPoint, OperateLog operateLog) throws Throwable { - return around0(joinPoint, operateLog, null); - } - - private Object around0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) throws Throwable { - // 记录开始时间 - Date startTime = new Date(); - try { - // 执行原有方法 - Object result = joinPoint.proceed(); - // 记录正常执行时的操作日志 - this.log(joinPoint, operateLog, apiOperation, startTime, result, null); - return result; - } catch (Throwable exception) { - this.log(joinPoint, operateLog, apiOperation, startTime, null, exception); - throw exception; - } finally { - clearThreadLocal(); - } - } - - public static void setContent(String content) { - CONTENT.set(content); - } - - public static void addExt(String key, Object value) { - if (EXTS.get() == null) { - EXTS.set(new HashMap<>()); - } - EXTS.get().put(key, value); - } - - private static void clearThreadLocal() { - CONTENT.remove(); - EXTS.remove(); - } - - private void log(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, - Date startTime, Object result, Throwable exception) { - try { - // 判断不记录的情况 - if (!isLogEnable(joinPoint, operateLog)) { - return; - } - // 真正记录操作日志 - this.log0(joinPoint, operateLog, apiOperation, startTime, result, exception); - } catch (Throwable ex) { - log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) operateLog({}) apiOperation({}) result({}) exception({}) ]", - joinPoint, operateLog, apiOperation, result, exception, ex); - } - } - - private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, - Date startTime, Object result, Throwable exception) { - OperateLogCreateReqDTO operateLogDTO = new OperateLogCreateReqDTO(); - // 补全通用字段 - operateLogDTO.setTraceId(TracerUtils.getTraceId()); - operateLogDTO.setStartTime(startTime); - // 补充用户信息 - fillUserFields(operateLogDTO); - // 补全模块信息 - fillModuleFields(operateLogDTO, joinPoint, operateLog, apiOperation); - // 补全请求信息 - fillRequestFields(operateLogDTO); - // 补全方法信息 - fillMethodFields(operateLogDTO, joinPoint, operateLog, startTime, result, exception); - - // 异步记录日志 - operateLogFrameworkService.createOperateLogAsync(operateLogDTO); - } - - private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) { - operateLogDTO.setUserId(SecurityFrameworkUtils.getLoginUserId()); - } - - private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO, - ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) { - // module 属性 - if (operateLog != null) { - operateLogDTO.setModule(operateLog.module()); - } - if (StrUtil.isEmpty(operateLogDTO.getModule())) { - Api api = getClassAnnotation(joinPoint, Api.class); - if (api != null) { - // 优先读取 @API 的 name 属性 - if (StrUtil.isNotEmpty(api.value())) { - operateLogDTO.setModule(api.value()); - } - // 没有的话,读取 @API 的 tags 属性 - if (StrUtil.isEmpty(operateLogDTO.getModule()) && ArrayUtil.isNotEmpty(api.tags())) { - operateLogDTO.setModule(api.tags()[0]); - } - } - } - // name 属性 - if (operateLog != null) { - operateLogDTO.setName(operateLog.name()); - } - if (StrUtil.isEmpty(operateLogDTO.getName()) && apiOperation != null) { - operateLogDTO.setName(apiOperation.value()); - } - // type 属性 - if (operateLog != null && ArrayUtil.isNotEmpty(operateLog.type())) { - operateLogDTO.setType(operateLog.type()[0].getType()); - } - if (operateLogDTO.getType() == null) { - RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); - OperateTypeEnum operateLogType = convertOperateLogType(requestMethod); - operateLogDTO.setType(operateLogType != null ? operateLogType.getType() : null); - } - // content 和 exts 属性 - operateLogDTO.setContent(CONTENT.get()); - operateLogDTO.setExts(EXTS.get()); - } - - private static void fillRequestFields(OperateLogCreateReqDTO operateLogDTO) { - // 获得 Request 对象 - HttpServletRequest request = ServletUtils.getRequest(); - if (request == null) { - return; - } - // 补全请求信息 - operateLogDTO.setRequestMethod(request.getMethod()); - operateLogDTO.setRequestUrl(request.getRequestURI()); - operateLogDTO.setUserIp(ServletUtil.getClientIP(request)); - operateLogDTO.setUserAgent(ServletUtils.getUserAgent(request)); - } - - private static void fillMethodFields(OperateLogCreateReqDTO operateLogDTO, - ProceedingJoinPoint joinPoint, OperateLog operateLog, - Date startTime, Object result, Throwable exception) { - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - operateLogDTO.setJavaMethod(methodSignature.toString()); - if (operateLog == null || operateLog.logArgs()) { - operateLogDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); - } - if (operateLog == null || operateLog.logResultData()) { - operateLogDTO.setResultData(obtainResultData(result)); - } - operateLogDTO.setDuration((int) (System.currentTimeMillis() - startTime.getTime())); - // (正常)处理 resultCode 和 resultMsg 字段 - if (result != null) { - if (result instanceof CommonResult) { - CommonResult commonResult = (CommonResult) result; - operateLogDTO.setResultCode(commonResult.getCode()); - operateLogDTO.setResultMsg(commonResult.getMsg()); - } else { - operateLogDTO.setResultCode(SUCCESS.getCode()); - } - } - // (异常)处理 resultCode 和 resultMsg 字段 - if (exception != null) { - operateLogDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); - operateLogDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); - } - } - - private static boolean isLogEnable(ProceedingJoinPoint joinPoint, OperateLog operateLog) { - // 有 @OperateLog 注解的情况下 - if (operateLog != null) { - return operateLog.enable(); - } - // 没有 @ApiOperation 注解的情况下,只记录 POST、PUT、DELETE 的情况 - return obtainFirstLogRequestMethod(obtainRequestMethod(joinPoint)) != null; - } - - private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) { - if (ArrayUtil.isEmpty(requestMethods)) { - return null; - } - return Arrays.stream(requestMethods).filter(requestMethod -> - requestMethod == RequestMethod.POST - || requestMethod == RequestMethod.PUT - || requestMethod == RequestMethod.DELETE) - .findFirst().orElse(null); - } - - private static RequestMethod obtainFirstMatchRequestMethod(RequestMethod[] requestMethods) { - if (ArrayUtil.isEmpty(requestMethods)) { - return null; - } - // 优先,匹配最优的 POST、PUT、DELETE - RequestMethod result = obtainFirstLogRequestMethod(requestMethods); - if (result != null) { - return result; - } - // 然后,匹配次优的 GET - result = Arrays.stream(requestMethods).filter(requestMethod -> requestMethod == RequestMethod.GET) - .findFirst().orElse(null); - if (result != null) { - return result; - } - // 兜底,获得第一个 - return requestMethods[0]; - } - - private static OperateTypeEnum convertOperateLogType(RequestMethod requestMethod) { - if (requestMethod == null) { - return null; - } - switch (requestMethod) { - case GET: - return OperateTypeEnum.GET; - case POST: - return OperateTypeEnum.CREATE; - case PUT: - return OperateTypeEnum.UPDATE; - case DELETE: - return OperateTypeEnum.DELETE; - default: - return OperateTypeEnum.OTHER; - } - } - - private static RequestMethod[] obtainRequestMethod(ProceedingJoinPoint joinPoint) { - RequestMapping requestMapping = AnnotationUtils.getAnnotation( // 使用 Spring 的工具类,可以处理 @RequestMapping 别名注解 - ((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class); - return requestMapping != null ? requestMapping.method() : new RequestMethod[]{}; - } - - @SuppressWarnings("SameParameterValue") - private static T getMethodAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { - return ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(annotationClass); - } - - @SuppressWarnings("SameParameterValue") - private static T getClassAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { - return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass); - } - - private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) { - // TODO 提升:参数脱敏和忽略 - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - String[] argNames = methodSignature.getParameterNames(); - Object[] argValues = joinPoint.getArgs(); - // 拼接参数 - Map args = Maps.newHashMapWithExpectedSize(argValues.length); - for (int i = 0; i < argNames.length; i++) { - String argName = argNames[i]; - Object argValue = argValues[i]; - // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 - args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); - } - return JsonUtils.toJsonString(args); - } - - private static String obtainResultData(Object result) { - // TODO 提升:结果脱敏和忽略 - if (result instanceof CommonResult) { - result = ((CommonResult) result).getData(); - } - return JsonUtils.toJsonString(result); - } - - private static boolean isIgnoreArgs(Object object) { - Class clazz = object.getClass(); - // 处理数组的情况 - if (clazz.isArray()) { - return IntStream.range(0, Array.getLength(object)) - .anyMatch(index -> isIgnoreArgs(Array.get(object, index))); - } - // 递归,处理数组、Collection、Map 的情况 - if (Collection.class.isAssignableFrom(clazz)) { - return ((Collection) object).stream() - .anyMatch((Predicate) o -> isIgnoreArgs(object)); - } - if (Map.class.isAssignableFrom(clazz)) { - return isIgnoreArgs(((Map) object).values()); - } - // obj - return object instanceof MultipartFile - || object instanceof HttpServletRequest - || object instanceof HttpServletResponse; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/dto/OperateLogCreateReqDTO.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/dto/OperateLogCreateReqDTO.java deleted file mode 100644 index 37eeb0c..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/dto/OperateLogCreateReqDTO.java +++ /dev/null @@ -1,84 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.operatelog.core.dto; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.util.Date; -import java.util.Map; - -/** - * 操作日志创建 Request DTO - */ -@Data -public class OperateLogCreateReqDTO { - - @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") - @NotEmpty(message = "链路追踪编号不能为空") - private String traceId; - - @ApiModelProperty(value = "用户编号", required = true, example = "1024") - @NotNull(message = "用户编号不能为空") - private Long userId; - - @ApiModelProperty(value = "操作模块", required = true, example = "订单") - @NotEmpty(message = "操作模块不能为空") - private String module; - - @ApiModelProperty(value = "操作名", required = true, example = "创建订单") - @NotEmpty(message = "操作名") - private String name; - - @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类") - @NotNull(message = "操作分类不能为空") - private Integer type; - - @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") - private String content; - - @ApiModelProperty(value = "拓展字段", example = "{'orderId': 1}") - private Map exts; - - @ApiModelProperty(value = "请求方法名", required = true, example = "GET") - @NotEmpty(message = "请求方法名不能为空") - private String requestMethod; - - @ApiModelProperty(value = "请求地址", required = true, example = "/xxx/yyy") - @NotEmpty(message = "请求地址不能为空") - private String requestUrl; - - @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") - @NotEmpty(message = "用户 IP 不能为空") - private String userIp; - - @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0") - @NotEmpty(message = "浏览器 UserAgent 不能为空") - private String userAgent; - - @ApiModelProperty(value = "Java 方法名", required = true, example = "cn.iocoder.dashboard.UserController.save(...)") - @NotEmpty(message = "Java 方法名不能为空") - private String javaMethod; - - @ApiModelProperty(value = "Java 方法的参数") - private String javaMethodArgs; - - @ApiModelProperty(value = "开始时间", required = true) - @NotNull(message = "开始时间不能为空") - private Date startTime; - - @ApiModelProperty(value = "执行时长,单位:毫秒", required = true) - @NotNull(message = "执行时长不能为空") - private Integer duration; - - @ApiModelProperty(value = "结果码", required = true) - @NotNull(message = "结果码不能为空") - private Integer resultCode; - - @ApiModelProperty(value = "结果提示") - private String resultMsg; - - @ApiModelProperty(value = "结果数据") - private String resultData; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateTypeEnum.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateTypeEnum.java deleted file mode 100644 index 8ce1c40..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateTypeEnum.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.operatelog.core.enums; - -import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 操作日志的操作类型 - * - * @author ruoyi - */ -@Getter -@AllArgsConstructor -public enum OperateTypeEnum { - - /** - * 查询 - * - * 绝大多数情况下,不会记录查询动作,因为过于大量显得没有意义。 - * 在有需要的时候,通过声明 {@link OperateLog} 注解来记录 - */ - GET(1), - /** - * 新增 - */ - CREATE(2), - /** - * 修改 - */ - UPDATE(3), - /** - * 删除 - */ - DELETE(4), - /** - * 导出 - */ - EXPORT(5), - /** - * 导入 - */ - IMPORT(6), - /** - * 其它 - * - * 在无法归类时,可以选择使用其它。因为还有操作名可以进一步标识 - */ - OTHER(0); - - /** - * 类型 - */ - private final Integer type; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/package-info.java deleted file mode 100644 index 88d69c2..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.operatelog.core; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java deleted file mode 100644 index 02489e8..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.operatelog.core.service; - -import cn.iocoder.dashboard.framework.logger.operatelog.core.dto.OperateLogCreateReqDTO; - -import java.util.concurrent.Future; - -public interface OperateLogFrameworkService { - - /** - * 异步记录操作日志 - * - * @param reqVO 操作日志请求 - * @return true: 记录成功,false: 记录失败 - */ - Future createOperateLogAsync(OperateLogCreateReqDTO reqVO); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/util/OperateLogUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/util/OperateLogUtils.java deleted file mode 100644 index 71135eb..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/util/OperateLogUtils.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.dashboard.framework.logger.operatelog.core.util; - -import cn.iocoder.dashboard.framework.logger.operatelog.core.aop.OperateLogAspect; - -/** - * 操作日志工具类 - * 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段 - * - * @author 芋道源码 - */ -public class OperateLogUtils { - - public static void setContent(String content) { - OperateLogAspect.setContent(content); - } - - public static void addExt(String key, Object value) { - OperateLogAspect.addExt(key, value); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/package-info.java deleted file mode 100644 index 258db8a..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/logger/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/** - * 日志组件,包括: - * - * 1. 用户操作日志:记录用户的操作,用于对用户的操作的审计与追溯,永久保存。 - * 2. API 日志:包含两类 - * 2.1 API 访问日志:记录用户访问 API 的访问日志,定期归档历史日志。 - * 2.2 API 异常日志:记录用户访问 API 的系统异常,方便日常排查问题与告警。 - * 3. 通用 Logger 日志:将 {@link org.slf4j.Logger} 打印的日志,只满足大于等于配置的 {@link org.slf4j.event.Level} 进行持久化,可以理解成简易的“日志中心”。 - */ -package cn.iocoder.dashboard.framework.logger; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityConfiguration.java deleted file mode 100644 index 80b9084..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityConfiguration.java +++ /dev/null @@ -1,166 +0,0 @@ -package cn.iocoder.dashboard.framework.security.config; - -import cn.iocoder.dashboard.framework.security.core.filter.JwtAuthenticationTokenFilter; -import cn.iocoder.dashboard.framework.security.core.handler.LogoutSuccessHandlerImpl; -import cn.iocoder.dashboard.framework.web.config.WebProperties; -import de.codecentric.boot.admin.server.config.AdminServerProperties; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.AuthenticationManager; -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.http.SessionCreationPolicy; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - -import javax.annotation.Resource; - -/** - * spring security配置 - * - * @author 芋道源码 - */ -@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) -@EnableConfigurationProperties(SecurityProperties.class) -public class SecurityConfiguration extends WebSecurityConfigurerAdapter { - - /** - * 自定义用户认证逻辑 - */ - @Resource - private UserDetailsService userDetailsService; - - /** - * 认证失败处理类 - */ - @Resource - private AuthenticationEntryPoint unauthorizedHandler; - /** - * 权限不够处理器 - */ - @Resource - private AccessDeniedHandler accessDeniedHandler; - /** - * 退出处理类 - */ - @Resource - private LogoutSuccessHandlerImpl logoutSuccessHandler; - - /** - * Token 认证过滤器 - */ - @Resource - private JwtAuthenticationTokenFilter authenticationTokenFilter; - - @Resource - private WebProperties webProperties; - @Resource - private AdminServerProperties adminServerProperties; - - /** - * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 - * 通过覆写父类的该方法,添加 @Bean 注解,解决该问题 - */ - @Override - @Bean - @ConditionalOnMissingBean(AuthenticationManager.class) - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } - - /** - * Spring Security 加密器 - * 考虑到安全性,这里采用 BCryptPasswordEncoder 加密器 - * - * @see Password Encoding with Spring Security - */ - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - /** - * 身份认证接口 - */ - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(userDetailsService) - .passwordEncoder(passwordEncoder()); - } - - /** - * 配置 URL 的安全配置 - * - * anyRequest | 匹配所有请求路径 - * access | SpringEl表达式结果为true时可以访问 - * anonymous | 匿名可以访问 - * denyAll | 用户不能访问 - * fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录) - * hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问 - * hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问 - * hasAuthority | 如果有参数,参数表示权限,则其权限可以访问 - * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 - * hasRole | 如果有参数,参数表示角色,则其角色可以访问 - * permitAll | 用户可以任意访问 - * rememberMe | 允许通过remember-me登录的用户访问 - * authenticated | 用户登录后可访问 - */ - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { - httpSecurity - // 开启跨域 - .cors().and() - // CSRF 禁用,因为不使用 Session - .csrf().disable() - // 基于 token 机制,所以不需要 Session - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() - // 一堆自定义的 Spring Security 处理器 - .exceptionHandling().authenticationEntryPoint(unauthorizedHandler) - .accessDeniedHandler(accessDeniedHandler).and() - // 设置每个请求的权限 - .authorizeRequests() - // 登陆的接口,可匿名访问 - .antMatchers(api("/login")).anonymous() - // 通用的接口,可匿名访问 - .antMatchers(api("/system/captcha/**")).anonymous() - // 静态资源,可匿名访问 - .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() - // 文件的获取接口,可匿名访问 - .antMatchers(api("/infra/file/get/**")).anonymous() - // Swagger 接口文档 - .antMatchers("/swagger-ui.html").anonymous() - .antMatchers("/swagger-resources/**").anonymous() - .antMatchers("/webjars/**").anonymous() - .antMatchers("/*/api-docs").anonymous() - // Spring Boot Admin Server 的安全配置 - .antMatchers(adminServerProperties.getContextPath()).anonymous() - .antMatchers(adminServerProperties.getContextPath() + "/**").anonymous() - // Spring Boot Actuator 的安全配置 - .antMatchers("/actuator").anonymous() - .antMatchers("/actuator/**").anonymous() - // Druid 监控 - .antMatchers("/druid/**").anonymous() - // 短信回调 API - .antMatchers(api("/system/sms/callback/**")).anonymous() - // 除上面外的所有请求全部需要鉴权认证 - .anyRequest().authenticated() - .and() - .headers().frameOptions().disable(); - httpSecurity.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); - // 添加 JWT Filter - httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); - } - - private String api(String url) { - return webProperties.getApiPrefix() + url; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityProperties.java deleted file mode 100644 index 6aa83bf..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/config/SecurityProperties.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.dashboard.framework.security.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.time.Duration; - -@ConfigurationProperties(prefix = "yudao.security") -@Validated -@Data -public class SecurityProperties { - - /** - * HTTP 请求时,访问令牌的请求 Header - */ - @NotEmpty(message = "Token Header 不能为空") - private String tokenHeader; - /** - * Token 过期时间 - */ - @NotNull(message = "Token 过期时间不能为空") - private Duration tokenTimeout; - /** - * Token 秘钥 - */ - @NotEmpty(message = "Token 秘钥不能为空") - private String tokenSecret; - /** - * Session 过期时间 - * - * 当 User 用户超过当前时间未操作,则 Session 会过期 - */ - @NotNull(message = "Session 过期时间不能为空") - private Duration sessionTimeout; - - /** - * mock 模式的开关 - */ - @NotNull(message = "mock 模式的开关不能为空") - private Boolean mockEnable; - /** - * mock 模式的秘钥 - * 一定要配置秘钥,保证安全性 - */ - @NotEmpty(message = "mock 模式的秘钥不能为空") // 这里设置了一个默认值,因为实际上只有 mockEnable 为 true 时才需要配置。 - private String mockSecret = "yudaoyuanma"; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java deleted file mode 100644 index ea73eef..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java +++ /dev/null @@ -1,93 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Data; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -import java.util.Collection; -import java.util.Date; -import java.util.Set; - -/** - * 登陆用户信息 - * - * @author 芋道源码 - */ -@Data -public class LoginUser implements UserDetails { - - /** - * 用户编号 - */ - private Long id; - /** - * 科室编号 - */ - private Long deptId; - /** - * 角色编号数组 - */ - private Set roleIds; - /** - * 最后更新时间 - */ - private Date updateTime; - - /** - * 用户名 - */ - private String username; - /** - * 密码 - */ - private String password; - /** - * 状态 - */ - private Integer status; - - @Override - @JsonIgnore// 避免序列化 - public String getPassword() { - return password; - } - - @Override - @JsonIgnore - public String getUsername() { - return username; - } - - @Override - @JsonIgnore// 避免序列化 - public boolean isEnabled() { - return CommonStatusEnum.ENABLE.getStatus().equals(status); - } - - @Override - @JsonIgnore// 避免序列化 - public Collection getAuthorities() { - return null; - } - - @Override - @JsonIgnore// 避免序列化 - public boolean isAccountNonExpired() { - return true; // 返回 true,不依赖 Spring Security 判断 - } - - @Override - @JsonIgnore// 避免序列化 - public boolean isAccountNonLocked() { - return true; // 返回 true,不依赖 Spring Security 判断 - } - - @Override - @JsonIgnore// 避免序列化 - public boolean isCredentialsNonExpired() { - return true; // 返回 true,不依赖 Spring Security 判断 - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/enums/DataScopeEnum.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/enums/DataScopeEnum.java deleted file mode 100644 index 7af847d..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/enums/DataScopeEnum.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 数据范围枚举类 - * - * 用于实现数据级别的权限 - * - * @author 芋道源码 - */ -@Getter -@AllArgsConstructor -public enum DataScopeEnum { - - ALL(1), // 全部数据权限 - DEPT_CUSTOM(2), // 指定部门数据权限 - DEPT_ONLY(3), // 部门数据权限 - DEPT_AND_CHILD(4), // 部门及以下数据权限 - DEPT_SELF(5); // 仅本人数据权限 - - /** - * 范围 - */ - private final Integer score; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/filter/JwtAuthenticationTokenFilter.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/filter/JwtAuthenticationTokenFilter.java deleted file mode 100644 index 512ffac..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/filter/JwtAuthenticationTokenFilter.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core.filter; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.security.config.SecurityProperties; -import cn.iocoder.dashboard.framework.security.core.LoginUser; -import cn.iocoder.dashboard.framework.security.core.service.SecurityAuthFrameworkService; -import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.dashboard.framework.web.core.handler.GlobalExceptionHandler; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.annotation.Resource; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * JWT 过滤器,验证 token 的有效性 - * 验证通过后,获得 {@link LoginUser} 信息,并加入到 Spring Security 上下文 - * - * @author ruoyi - */ -@Component -public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { - - @Resource - private SecurityProperties securityProperties; - @Resource - private SecurityAuthFrameworkService authService; - @Resource - private GlobalExceptionHandler globalExceptionHandler; - - @Override - @SuppressWarnings("NullableProblems") - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) - throws ServletException, IOException { - String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); - if (StrUtil.isNotEmpty(token)) { - try { - // 验证 token 有效性 - LoginUser loginUser = authService.verifyTokenAndRefresh(token); - // 模拟 Login 功能,方便日常开发调试 - if (loginUser == null) { - loginUser = this.mockLoginUser(token); - } - // 设置当前用户 - if (loginUser != null) { - SecurityFrameworkUtils.setLoginUser(loginUser, request); - } - } catch (Throwable ex) { - CommonResult result = globalExceptionHandler.allExceptionHandler(request, ex); - ServletUtils.writeJSON(response, result); - return; - } - } - - // 继续过滤链 - chain.doFilter(request, response); - } - - /** - * 模拟登陆用户,方便日常开发调试 - * - * 注意,在线上环境下,一定要关闭该功能!!! - * - * @param token 模拟的 token,格式为 {@link SecurityProperties#getTokenSecret()} + 用户编号 - * @return 模拟的 LoginUser - */ - private LoginUser mockLoginUser(String token) { - if (!securityProperties.getMockEnable()) { - return null; - } - // 必须以 mockSecret 开头 - if (!token.startsWith(securityProperties.getMockSecret())) { - return null; - } - Long userId = Long.valueOf(token.substring(securityProperties.getMockSecret().length())); - return authService.mockLogin(userId); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java deleted file mode 100644 index 9f4acbd..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AccessDeniedHandlerImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core.handler; - -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.security.web.access.ExceptionTranslationFilter; -import org.springframework.stereotype.Component; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED; - -/** - * 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。 - * - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#handleAccessDeniedException(HttpServletRequest, HttpServletResponse, FilterChain, AccessDeniedException)} 方法,调用当前类 - * - * @author 芋道源码 - */ -@Component -@Slf4j -@SuppressWarnings("JavadocReference") -public class AccessDeniedHandlerImpl implements AccessDeniedHandler { - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) - throws IOException, ServletException { - // 打印 warn 的原因是,不定期合并 warn,看看有没恶意破坏 - log.warn("[commence][访问 URL({}) 时,用户({}) 权限不够]", request.getRequestURI(), - SecurityFrameworkUtils.getLoginUser().getId(), e); - // 返回 403 - ServletUtils.writeJSON(response, CommonResult.error(UNAUTHORIZED)); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AuthenticationEntryPointImpl.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AuthenticationEntryPointImpl.java deleted file mode 100644 index 66013c0..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/AuthenticationEntryPointImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core.handler; - -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.access.ExceptionTranslationFilter; -import org.springframework.stereotype.Component; - -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED; - -/** - * 访问一个需要认证的 URL 资源,但是此时自己尚未认证(登录)的情况下,返回 {@link GlobalErrorCodeConstants#UNAUTHORIZED} 错误码,从而使前端重定向到登录页 - * - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#sendStartAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, AuthenticationException)} 方法,调用当前类 - * - * @author ruoyi - */ -@Component -@Slf4j -@SuppressWarnings("JavadocReference") // 忽略文档引用报错 -public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { - - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { - log.debug("[commence][访问 URL({}) 时,没有登录]", request.getRequestURI(), e); - // 返回 401 - ServletUtils.writeJSON(response, CommonResult.error(UNAUTHORIZED)); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/LogoutSuccessHandlerImpl.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/LogoutSuccessHandlerImpl.java deleted file mode 100644 index d408648..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/handler/LogoutSuccessHandlerImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core.handler; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.security.config.SecurityProperties; -import cn.iocoder.dashboard.framework.security.core.service.SecurityAuthFrameworkService; -import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - - -/** - * 自定义退出处理器 - * - * @author ruoyi - */ -@Component -public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler { - - @Resource - private SecurityProperties securityProperties; - - @Resource - private SecurityAuthFrameworkService securityFrameworkService; - - @Override - public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { - // 执行退出 - String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); - if (StrUtil.isNotBlank(token)) { - securityFrameworkService.logout(token); - } - // 返回成功 - ServletUtils.writeJSON(response, CommonResult.success(null)); - } -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityAuthFrameworkService.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityAuthFrameworkService.java deleted file mode 100644 index e387935..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityAuthFrameworkService.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core.service; - -import cn.iocoder.dashboard.framework.security.core.LoginUser; -import org.springframework.security.core.userdetails.UserDetailsService; - -/** - * Security 框架 Auth Service 接口,定义 security 组件需要的功能 - * - * @author 芋道源码 - */ -public interface SecurityAuthFrameworkService extends UserDetailsService { - - /** - * 校验 token 的有效性,并获取用户信息 - * 通过后,刷新 token 的过期时间 - * - * @param token token - * @return 用户信息 - */ - LoginUser verifyTokenAndRefresh(String token); - - /** - * 模拟指定用户编号的 LoginUser - * - * @param userId 用户编号 - * @return 登录用户 - */ - LoginUser mockLogin(Long userId); - - /** - * 基于 token 退出登录 - * - * @param token token - */ - void logout(String token); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityPermissionFrameworkService.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityPermissionFrameworkService.java deleted file mode 100644 index 2209871..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/service/SecurityPermissionFrameworkService.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core.service; - -/** - * Security 框架 Permission Service 接口,定义 security 组件需要的功能 - * - * @author 芋道源码 - */ -public interface SecurityPermissionFrameworkService { - - /** - * 判断是否有权限 - * - * @param permission 权限 - * @return 是否 - */ - boolean hasPermission(String permission); - - /** - * 判断是否有权限,任一一个即可 - * - * @param permissions 权限 - * @return 是否 - */ - boolean hasAnyPermissions(String... permissions); - - /** - * 判断是否有角色 - * - * 注意,角色使用的是 SysRoleDO 的 code 标识 - * - * @param role 角色 - * @return 是否 - */ - boolean hasRole(String role); - - /** - * 判断是否有角色,任一一个即可 - * - * @param roles 角色数组 - * @return 是否 - */ - boolean hasAnyRoles(String... roles); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityFrameworkUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityFrameworkUtils.java deleted file mode 100644 index da0032e..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityFrameworkUtils.java +++ /dev/null @@ -1,102 +0,0 @@ -package cn.iocoder.dashboard.framework.security.core.util; - -import cn.iocoder.dashboard.framework.security.core.LoginUser; -import cn.iocoder.dashboard.framework.web.core.util.WebFrameworkUtils; -import org.springframework.lang.Nullable; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.util.StringUtils; - -import javax.servlet.http.HttpServletRequest; -import java.util.Set; - -/** - * 安全服务工具类 - * - * @author 芋道源码 - */ -public class SecurityFrameworkUtils { - - private SecurityFrameworkUtils() {} - - /** - * 从请求中,获得认证 Token - * - * @param request 请求 - * @param header 认证 Token 对应的 Header 名字 - * @return 认证 Token - */ - public static String obtainAuthorization(HttpServletRequest request, String header) { - String authorization = request.getHeader(header); - if (!StringUtils.hasText(authorization)) { - return null; - } - int index = authorization.indexOf("Bearer "); - if (index == -1) { // 未找到 - return null; - } - return authorization.substring(index + 7).trim(); - } - - /** - * 获取当前用户 - * - * @return 当前用户 - */ - @Nullable - public static LoginUser getLoginUser() { - SecurityContext context = SecurityContextHolder.getContext(); - if (context == null) { - return null; - } - Authentication authentication = context.getAuthentication(); - if (authentication == null) { - return null; - } - return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null; - } - - /** - * 获得当前用户的编号,从上下文中 - * - * @return 用户编号 - */ - @Nullable - public static Long getLoginUserId() { - LoginUser loginUser = getLoginUser(); - return loginUser != null ? loginUser.getId() : null; - } - - /** - * 获得当前用户的角色编号数组 - * - * @return 角色编号数组 - */ - @Nullable - public static Set getLoginUserRoleIds() { - LoginUser loginUser = getLoginUser(); - return loginUser != null ? loginUser.getRoleIds() : null; - } - - /** - * 设置当前用户 - * - * @param loginUser 登陆用户 - * @param request 请求 - */ - public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) { - // 创建 UsernamePasswordAuthenticationToken 对象 - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( - loginUser, null, null); - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - // 设置到上下文 - SecurityContextHolder.getContext().setAuthentication(authenticationToken); - // 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号; - // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息 - WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/package-info.java deleted file mode 100644 index bc44516..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * 基于 Spring Security 框架 - * 实现安全认证功能 - * - * @author 芋道源码 - */ -package cn.iocoder.dashboard.framework.security; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md deleted file mode 100644 index b8a8931..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md +++ /dev/null @@ -1,2 +0,0 @@ -* 芋道 Spring Security 入门: -* Spring Security 基本概念: diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerAutoConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerAutoConfiguration.java deleted file mode 100644 index 21511c3..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerAutoConfiguration.java +++ /dev/null @@ -1,105 +0,0 @@ -package cn.iocoder.dashboard.framework.swagger.config; - -import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpHeaders; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.Contact; -import springfox.documentation.service.SecurityReference; -import springfox.documentation.service.SecurityScheme; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -import java.util.Collections; -import java.util.List; - -import static springfox.documentation.builders.RequestHandlerSelectors.basePackage; - -/** - * Swagger2 自动配置类 - * - * @author 芋道源码 - */ -@Configuration -@EnableSwagger2 -@EnableKnife4j -@ConditionalOnClass({Docket.class, ApiInfoBuilder.class}) -@ConditionalOnProperty(prefix = "yudao.swagger", value = "enable", matchIfMissing = true) -// 允许使用 swagger.enable=false 禁用 Swagger -@EnableConfigurationProperties(SwaggerProperties.class) -public class SwaggerAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public SwaggerProperties swaggerProperties() { - return new SwaggerProperties(); - } - - @Bean - public Docket createRestApi() { - SwaggerProperties properties = swaggerProperties(); - // 创建 Docket 对象 - return new Docket(DocumentationType.SWAGGER_2) - // 用来创建该 API 的基本信息,展示在文档的页面中(自定义展示的信息) - .apiInfo(apiInfo(properties)) - // 设置扫描指定 package 包下的 - .select() - .apis(basePackage(properties.getBasePackage())) - .paths(PathSelectors.any()) - .build() - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()); - } - - /** - * API 摘要信息 - */ - private static ApiInfo apiInfo(SwaggerProperties properties) { - return new ApiInfoBuilder() - .title(properties.getTitle()) - .description(properties.getDescription()) - .contact(new Contact(properties.getAuthor(), null, null)) - .version(properties.getVersion()) - .build(); - } - - /** - * 安全模式,这里配置通过请求头 Authorization 传递 token 参数 - */ - private static List securitySchemes() { - return Collections.singletonList(new ApiKey(HttpHeaders.AUTHORIZATION, "Authorization", "header")); - } - - /** - * 安全上下文 - * - * @see #securitySchemes() - * @see #authorizationScopes() - */ - private static List securityContexts() { - return Collections.singletonList(SecurityContext.builder() - .securityReferences(securityReferences()) - .forPaths(PathSelectors.regex("^(?!auth).*$")) - .build()); - } - - private static List securityReferences() { - return Collections.singletonList(new SecurityReference(HttpHeaders.AUTHORIZATION, authorizationScopes())); - } - - private static AuthorizationScope[] authorizationScopes() { - return new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")}; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerProperties.java deleted file mode 100644 index 6ee40c7..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/config/SwaggerProperties.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.dashboard.framework.swagger.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; - -import javax.validation.constraints.NotEmpty; - -/** - * Swagger 配置属性 - * - * @author 芋道源码 - */ -@ConfigurationProperties("yudao.swagger") -@Data -public class SwaggerProperties { - - /** - * 标题 - */ - @NotEmpty(message = "标题不能为空") - private String title; - /** - * 描述 - */ - @NotEmpty(message = "描述不能为空") - private String description; - /** - * 作者 - */ - @NotEmpty(message = "作者不能为空") - private String author; - /** - * 版本 - */ - @NotEmpty(message = "版本不能为空") - private String version; - /** - * 扫描的包 - */ - @NotEmpty(message = "扫描的 package 不能为空") - private String basePackage; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/package-info.java deleted file mode 100644 index 2bce74a..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 基于 Swagger + Knife4j 实现 API 接口文档 - * - * @author 芋道源码 - */ -package cn.iocoder.dashboard.framework.swagger; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/《芋道 Spring Boot API 接口文档 Swagger 入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/《芋道 Spring Boot API 接口文档 Swagger 入门》.md deleted file mode 100644 index 7ed5ebd..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/swagger/《芋道 Spring Boot API 接口文档 Swagger 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java index aeb90af..7918c8c 100644 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java +++ b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/config/TracerAutoConfiguration.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.framework.tracer.config; import cn.iocoder.dashboard.framework.tracer.core.aop.BizTraceAspect; import cn.iocoder.dashboard.framework.tracer.core.filter.TraceFilter; -import cn.iocoder.dashboard.framework.web.core.enums.FilterOrderEnum; +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import io.opentracing.Tracer; import org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -49,7 +49,7 @@ public class TracerAutoConfiguration { public FilterRegistrationBean traceFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new TraceFilter()); - registrationBean.setOrder(FilterOrderEnum.TRACE_FILTER); + registrationBean.setOrder(WebFilterOrderEnum.TRACE_FILTER); return registrationBean; } diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java index bedd528..49294cc 100644 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java +++ b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/filter/TraceFilter.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.framework.tracer.core.filter; -import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; +import cn.iocoder.yudao.framework.util.monitor.TracerUtils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java deleted file mode 100644 index e8af904..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/tracer/core/util/TracerUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.dashboard.framework.tracer.core.util; - -import org.apache.skywalking.apm.toolkit.trace.TraceContext; - -/** - * 链路追踪工具类 - * - * @author 芋道源码 - */ -public class TracerUtils { - - /** - * 私有化构造方法 - */ - private TracerUtils() { - } - - /** - * 获得链路追踪编号,直接返回 SkyWalking 的 TraceId。 - * 如果不存在的话为空字符串!!! - * - * @return 链路追踪编号 - */ - public static String getTraceId() { - return TraceContext.traceId(); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java deleted file mode 100644 index 2f4e7a3..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java +++ /dev/null @@ -1,88 +0,0 @@ -package cn.iocoder.dashboard.framework.web.config; - -import cn.iocoder.dashboard.framework.web.core.enums.FilterOrderEnum; -import cn.iocoder.dashboard.framework.web.core.filter.CacheRequestBodyFilter; -import cn.iocoder.dashboard.framework.web.core.filter.DemoFilter; -import cn.iocoder.dashboard.framework.web.core.filter.XssFilter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.util.PathMatcher; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import org.springframework.web.filter.CorsFilter; -import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import javax.annotation.Resource; -import javax.servlet.Filter; - -@Configuration -@EnableConfigurationProperties({WebProperties.class, XssProperties.class}) -public class WebConfiguration implements WebMvcConfigurer { - - @Resource - private WebProperties webProperties; - - @Override - public void configurePathMatch(PathMatchConfigurer configurer) { - // 设置 API 前缀,仅仅匹配 controller 包下的 - configurer.addPathPrefix(webProperties.getApiPrefix(), clazz -> - clazz.isAnnotationPresent(RestController.class) - && clazz.getPackage().getName().startsWith(webProperties.getControllerPackage())); // 仅仅匹配 controller 包 - } - - // ========== Filter 相关 ========== - - /** - * 创建 CorsFilter Bean,解决跨域问题 - */ - @Bean - public FilterRegistrationBean corsFilterBean() { - // 创建 CorsConfiguration 对象 - CorsConfiguration config = new CorsConfiguration(); - config.setAllowCredentials(true); - config.addAllowedOriginPattern("*"); // 设置访问源地址 - config.addAllowedHeader("*"); // 设置访问源请求头 - config.addAllowedMethod("*"); // 设置访问源请求方法 - // 创建 UrlBasedCorsConfigurationSource 对象 - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", config); // 对接口配置跨域设置 - return createFilterBean(new CorsFilter(source), FilterOrderEnum.CORS_FILTER); - } - - /** - * 创建 RequestBodyCacheFilter Bean,可重复读取请求内容 - */ - @Bean - public FilterRegistrationBean requestBodyCacheFilter() { - return createFilterBean(new CacheRequestBodyFilter(), FilterOrderEnum.REQUEST_BODY_CACHE_FILTER); - } - - /** - * 创建 XssFilter Bean,解决 Xss 安全问题 - */ - @Bean - public FilterRegistrationBean xssFilter(XssProperties properties, PathMatcher pathMatcher) { - return createFilterBean(new XssFilter(properties, pathMatcher), FilterOrderEnum.XSS_FILTER); - } - - /** - * 创建 DemoFilter Bean,演示模式 - */ - @Bean - @ConditionalOnProperty(value = "yudao.demo", havingValue = "true") - public FilterRegistrationBean demoFilter() { - return createFilterBean(new DemoFilter(), FilterOrderEnum.DEMO_FILTER); - } - - private static FilterRegistrationBean createFilterBean(T filter, Integer order) { - FilterRegistrationBean bean = new FilterRegistrationBean<>(filter); - bean.setOrder(order); - return bean; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java deleted file mode 100644 index 93479bc..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.dashboard.framework.web.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; - -import javax.validation.constraints.NotNull; - -@ConfigurationProperties(prefix = "yudao.web") -@Validated -@Data -public class WebProperties { - - /** - * API 前缀,实现所有 Controller 提供的 RESTFul API 的统一前缀 - * - * - * 意义:通过该前缀,避免 Swagger、Actuator 意外通过 Nginx 暴露出来给外部,带来安全性问题 - * 这样,Nginx 只需要配置转发到 /api/* 的所有接口即可。 - * - * @see WebConfiguration#configurePathMatch(PathMatchConfigurer) - */ - @NotNull(message = "API 前缀不能为空") - private String apiPrefix; - - /** - * Controller 所在包 - * - * 主要目的是,给该 Controller 设置指定的 {@link #apiPrefix} - * - * 因为我们有多个 modules 包里会包含 Controller,所以只需要写到 cn.iocoder.dashboard 这样的层级 - */ - @NotNull(message = "Controller 所在包不能为空") - private String controllerPackage; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/XssProperties.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/XssProperties.java deleted file mode 100644 index a232f4a..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/config/XssProperties.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.dashboard.framework.web.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -import java.util.Collections; -import java.util.List; - -/** - * Xss 配置属性 - * - * @author 芋道源码 - */ -@ConfigurationProperties(prefix = "yudao.xss") -@Validated -@Data -public class XssProperties { - - /** - * 是否开启,默认为 true - */ - private boolean enable = true; - /** - * 需要排除的 URL,默认为空 - */ - private List excludeUrls = Collections.emptyList(); - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java deleted file mode 100644 index 93bdb03..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/enums/FilterOrderEnum.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.enums; - -/** - * 过滤器顺序的枚举类,保证过滤器按照符合我们的预期 - * - * @author 芋道源码 - */ -public interface FilterOrderEnum { - - int CORS_FILTER = Integer.MIN_VALUE; - - int TRACE_FILTER = CORS_FILTER + 1; - - int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500; - - // OrderedRequestContextFilter 默认为 -105,用于国际化上下文等等 - - int API_ACCESS_LOG_FILTER = -104; // 需要保证在 RequestBodyCacheFilter 后面 - - int XSS_FILTER = -103; // 需要保证在 RequestBodyCacheFilter 后面 - - // Spring Security Filter 默认为 -100,可见 SecurityProperties 配置属性类 - - int DEMO_FILTER = Integer.MAX_VALUE; - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyFilter.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyFilter.java deleted file mode 100644 index 023e234..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyFilter.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.filter; - -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -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; - -/** - * Request Body 缓存 Filter,实现它的可重复读取 - * - * @author 芋道源码 - */ -public class CacheRequestBodyFilter extends OncePerRequestFilter { - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws IOException, ServletException { - filterChain.doFilter(new CacheRequestBodyWrapper(request), response); - } - - @Override - protected boolean shouldNotFilter(HttpServletRequest request) { - // 只处理 json 请求内容 - return !ServletUtils.isJsonRequest(request); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyWrapper.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyWrapper.java deleted file mode 100644 index 6d1e991..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/CacheRequestBodyWrapper.java +++ /dev/null @@ -1,63 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.filter; - -import cn.hutool.extra.servlet.ServletUtil; - -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * Request Body 缓存 Wrapper - * - * @author 芋道源码 - */ -public class CacheRequestBodyWrapper extends HttpServletRequestWrapper { - - /** - * 缓存的内容 - */ - private final byte[] body; - - public CacheRequestBodyWrapper(HttpServletRequest request) { - super(request); - body = ServletUtil.getBodyBytes(request); - } - - @Override - public BufferedReader getReader() throws IOException { - return new BufferedReader(new InputStreamReader(this.getInputStream())); - } - - @Override - public ServletInputStream getInputStream() throws IOException { - final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); - // 返回 ServletInputStream - return new ServletInputStream() { - - @Override - public int read() { - return inputStream.read(); - } - - @Override - public boolean isFinished() { - return true; - } - - @Override - public boolean isReady() { - return true; - } - - @Override - public void setReadListener(ReadListener readListener) {} - - }; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/DemoFilter.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/DemoFilter.java deleted file mode 100644 index aad9ebd..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/DemoFilter.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.filter; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.DEMO_DENY; - -/** - * 演示 Filter,禁止用户发起写操作,避免影响测试数据 - * - * @author 芋道源码 - */ -public class DemoFilter extends OncePerRequestFilter { - - @Override - protected boolean shouldNotFilter(HttpServletRequest request) { - String method = request.getMethod(); - return !StrUtil.equalsAnyIgnoreCase(method, "POST", "PUT", "DELETE") // 写操作时,不进行过滤率 - || SecurityFrameworkUtils.getLoginUser() == null; // 非登陆用户时,不进行过滤 - } - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { - // 直接返回 DEMO_DENY 的结果。即,请求不继续 - ServletUtils.writeJSON(response, CommonResult.error(DEMO_DENY)); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssFilter.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssFilter.java deleted file mode 100644 index f486402..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssFilter.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.filter; - -import cn.iocoder.dashboard.framework.web.config.XssProperties; -import lombok.AllArgsConstructor; -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; - -/** - * Xss 过滤器 - * - * 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/ - * - * @author 芋道源码 - */ -@AllArgsConstructor -public class XssFilter extends OncePerRequestFilter { - - /** - * 属性 - */ - private final XssProperties properties; - /** - * 路径匹配器 - */ - private final PathMatcher pathMatcher; - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws IOException, ServletException { - filterChain.doFilter(new XssRequestWrapper(request), response); - } - - @Override - protected boolean shouldNotFilter(HttpServletRequest request) { - // 如果关闭,则不过滤 - if (!properties.isEnable()) { - return true; - } - - // 如果匹配到无需过滤,则不过滤 - String uri = request.getRequestURI(); - return properties.getExcludeUrls().stream().anyMatch(excludeUrl -> pathMatcher.match(excludeUrl, uri)); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java deleted file mode 100644 index 15570d8..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/filter/XssRequestWrapper.java +++ /dev/null @@ -1,136 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.filter; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ReflectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.http.HTMLFilter; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; - -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Map; - -/** - * Xss 请求 Wrapper - * - * @author 芋道源码 - */ -public class XssRequestWrapper extends HttpServletRequestWrapper { - - /** - * 基于线程级别的 HTMLFilter 对象,因为它线程非安全 - */ - private static final ThreadLocal HTML_FILTER = ThreadLocal.withInitial(() -> { - HTMLFilter htmlFilter = new HTMLFilter(); - // 反射修改 encodeQuotes 属性为 false,避免 " 被转移成 " 字符 - ReflectUtil.setFieldValue(htmlFilter, "encodeQuotes", false); - return htmlFilter; - }); - - public XssRequestWrapper(HttpServletRequest request) { - super(request); - } - - private static String filterXss(String content) { - if (StrUtil.isEmpty(content)) { - return content; - } - return HTML_FILTER.get().filter(content); - } - - // ========== IO 流相关 ========== - - @Override - public BufferedReader getReader() throws IOException { - return new BufferedReader(new InputStreamReader(this.getInputStream())); - } - - @Override - public ServletInputStream getInputStream() throws IOException { - // 如果非 json 请求,不进行 Xss 处理 - if (!ServletUtils.isJsonRequest(this)) { - return super.getInputStream(); - } - - // 读取内容,并过滤 - String content = IoUtil.readUtf8(super.getInputStream()); - content = filterXss(content); - final ByteArrayInputStream newInputStream = new ByteArrayInputStream(content.getBytes()); - // 返回 ServletInputStream - return new ServletInputStream() { - - @Override - public int read() { - return newInputStream.read(); - } - - @Override - public boolean isFinished() { - return true; - } - - @Override - public boolean isReady() { - return true; - } - - @Override - public void setReadListener(ReadListener readListener) {} - - }; - } - - // ========== Param 相关 ========== - - @Override - public String getParameter(String name) { - String value = super.getParameter(name); - return filterXss(value); - } - - @Override - public String[] getParameterValues(String name) { - String[] values = super.getParameterValues(name); - if (ArrayUtil.isEmpty(values)) { - return values; - } - // 过滤处理 - for (int i = 0; i < values.length; i++) { - values[i] = filterXss(values[i]); - } - return values; - } - - @Override - public Map getParameterMap() { - Map valueMap = super.getParameterMap(); - if (CollUtil.isEmpty(valueMap)) { - return valueMap; - } - // 过滤处理 - for (Map.Entry entry : valueMap.entrySet()) { - String[] values = entry.getValue(); - for (int i = 0; i < values.length; i++) { - values[i] = filterXss(values[i]); - } - } - return valueMap; - } - - // ========== Header 相关 ========== - - @Override - public String getHeader(String name) { - String value = super.getHeader(name); - return filterXss(value); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java deleted file mode 100644 index 5df9927..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java +++ /dev/null @@ -1,276 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.handler; - -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.map.MapUtil; -import cn.hutool.extra.servlet.ServletUtil; -import cn.iocoder.yudao.framework.common.exception.ServiceException; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService; -import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; -import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; -import cn.iocoder.dashboard.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.framework.util.json.JsonUtils; -import cn.iocoder.yudao.framework.util.servlet.ServletUtils; -import io.github.resilience4j.ratelimiter.RequestNotPermitted; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.util.Assert; -import org.springframework.validation.BindException; -import org.springframework.validation.FieldError; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.MissingServletRequestParameterException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; -import org.springframework.web.servlet.NoHandlerFoundException; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; -import javax.validation.ValidationException; -import java.util.Date; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*; - -/** - * 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号 - * - * @author 芋道源码 - */ -@RestControllerAdvice -@Slf4j -public class GlobalExceptionHandler { - - @Value("${spring.application.name}") - private String applicationName; - - @Resource - private ApiErrorLogFrameworkService apiErrorLogFrameworkService; - - /** - * 处理所有异常,主要是提供给 Filter 使用 - * 因为 Filter 不走 SpringMVC 的流程,但是我们又需要兜底处理异常,所以这里提供一个全量的异常处理过程,保持逻辑统一。 - * - * @param request 请求 - * @param ex 异常 - * @return 通用返回 - */ - public CommonResult allExceptionHandler(HttpServletRequest request, Throwable ex) { - if (ex instanceof MissingServletRequestParameterException) { - return missingServletRequestParameterExceptionHandler((MissingServletRequestParameterException) ex); - } - if (ex instanceof MethodArgumentTypeMismatchException) { - return methodArgumentTypeMismatchExceptionHandler((MethodArgumentTypeMismatchException) ex); - } - if (ex instanceof MethodArgumentNotValidException) { - return methodArgumentNotValidExceptionExceptionHandler((MethodArgumentNotValidException) ex); - } - if (ex instanceof BindException) { - return bindExceptionHandler((BindException) ex); - } - if (ex instanceof ConstraintViolationException) { - return constraintViolationExceptionHandler((ConstraintViolationException) ex); - } - if (ex instanceof ValidationException) { - return validationException((ValidationException) ex); - } - if (ex instanceof NoHandlerFoundException) { - return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex); - } - if (ex instanceof HttpRequestMethodNotSupportedException) { - return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); - } - if (ex instanceof RequestNotPermitted) { - return requestNotPermittedExceptionHandler(request, (RequestNotPermitted) ex); - } - if (ex instanceof ServiceException) { - return serviceExceptionHandler((ServiceException) ex); - } - if (ex instanceof AccessDeniedException) { - return accessDeniedExceptionHandler(request, (AccessDeniedException) ex); - } - return defaultExceptionHandler(request, ex); - } - - /** - * 处理 SpringMVC 请求参数缺失 - * - * 例如说,接口上设置了 @RequestParam("xx") 参数,结果并未传递 xx 参数 - */ - @ExceptionHandler(value = MissingServletRequestParameterException.class) - public CommonResult missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException ex) { - log.warn("[missingServletRequestParameterExceptionHandler]", ex); - return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数缺失:%s", ex.getParameterName())); - } - - /** - * 处理 SpringMVC 请求参数类型错误 - * - * 例如说,接口上设置了 @RequestParam("xx") 参数为 Integer,结果传递 xx 参数类型为 String - */ - @ExceptionHandler(MethodArgumentTypeMismatchException.class) - public CommonResult methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException ex) { - log.warn("[missingServletRequestParameterExceptionHandler]", ex); - return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", ex.getMessage())); - } - - /** - * 处理 SpringMVC 参数校验不正确 - */ - @ExceptionHandler(MethodArgumentNotValidException.class) - public CommonResult methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException ex) { - log.warn("[methodArgumentNotValidExceptionExceptionHandler]", ex); - FieldError fieldError = ex.getBindingResult().getFieldError(); - assert fieldError != null; // 断言,避免告警 - return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage())); - } - - /** - * 处理 SpringMVC 参数绑定不正确,本质上也是通过 Validator 校验 - */ - @ExceptionHandler(BindException.class) - public CommonResult bindExceptionHandler(BindException ex) { - log.warn("[handleBindException]", ex); - FieldError fieldError = ex.getFieldError(); - assert fieldError != null; // 断言,避免告警 - return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage())); - } - - /** - * 处理 Validator 校验不通过产生的异常 - */ - @ExceptionHandler(value = ConstraintViolationException.class) - public CommonResult constraintViolationExceptionHandler(ConstraintViolationException ex) { - log.warn("[constraintViolationExceptionHandler]", ex); - ConstraintViolation constraintViolation = ex.getConstraintViolations().iterator().next(); - return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", constraintViolation.getMessage())); - } - - /** - * 处理 Dubbo Consumer 本地参数校验时,抛出的 ValidationException 异常 - */ - @ExceptionHandler(value = ValidationException.class) - public CommonResult validationException(ValidationException ex) { - log.warn("[constraintViolationExceptionHandler]", ex); - // 无法拼接明细的错误信息,因为 Dubbo Consumer 抛出 ValidationException 异常时,是直接的字符串信息,且人类不可读 - return CommonResult.error(BAD_REQUEST); - } - - /** - * 处理 SpringMVC 请求地址不存在 - * - * 注意,它需要设置如下两个配置项: - * 1. spring.mvc.throw-exception-if-no-handler-found 为 true - * 2. spring.mvc.static-path-pattern 为 /statics/** - */ - @ExceptionHandler(NoHandlerFoundException.class) - public CommonResult noHandlerFoundExceptionHandler(NoHandlerFoundException ex) { - log.warn("[noHandlerFoundExceptionHandler]", ex); - return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL())); - } - - /** - * 处理 SpringMVC 请求方法不正确 - * - * 例如说,A 接口的方法为 GET 方式,结果请求方法为 POST 方式,导致不匹配 - */ - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public CommonResult httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) { - log.warn("[httpRequestMethodNotSupportedExceptionHandler]", ex); - return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage())); - } - - /** - * 处理 Resilience4j 限流抛出的异常 - */ - @ExceptionHandler(value = RequestNotPermitted.class) - public CommonResult requestNotPermittedExceptionHandler(HttpServletRequest req, RequestNotPermitted ex) { - log.warn("[requestNotPermittedExceptionHandler][url({}) 访问过于频繁]", req.getRequestURL(), ex); - return CommonResult.error(TOO_MANY_REQUESTS); - } - - /** - * 处理 Spring Security 权限不足的异常 - * - * 来源是,使用 @PreAuthorize 注解,AOP 进行权限拦截 - */ - @ExceptionHandler(value = AccessDeniedException.class) - public CommonResult accessDeniedExceptionHandler(HttpServletRequest req, AccessDeniedException ex) { - log.warn("[accessDeniedExceptionHandler][userId({}) 无法访问 url({})]", SecurityFrameworkUtils.getLoginUserId(), - req.getRequestURL(), ex); - return CommonResult.error(FORBIDDEN); - } - - /** - * 处理业务异常 ServiceException - * - * 例如说,商品库存不足,用户手机号已存在。 - */ - @ExceptionHandler(value = ServiceException.class) - public CommonResult serviceExceptionHandler(ServiceException ex) { - log.info("[serviceExceptionHandler]", ex); - return CommonResult.error(ex.getCode(), ex.getMessage()); - } - - /** - * 处理系统异常,兜底处理所有的一切 - */ - @ExceptionHandler(value = Exception.class) - public CommonResult defaultExceptionHandler(HttpServletRequest req, Throwable ex) { - log.error("[defaultExceptionHandler]", ex); - // 插入异常日志 - this.createExceptionLog(req, ex); - // 返回 ERROR CommonResult - return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); - } - - private void createExceptionLog(HttpServletRequest req, Throwable e) { - // 插入错误日志 - ApiErrorLogCreateDTO errorLog = new ApiErrorLogCreateDTO(); - try { - // 初始化 errorLog - initExceptionLog(errorLog, req, e); - // 执行插入 errorLog - apiErrorLogFrameworkService.createApiErrorLogAsync(errorLog); - } catch (Throwable th) { - log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(), JsonUtils.toJsonString(errorLog), th); - } - } - - private void initExceptionLog(ApiErrorLogCreateDTO errorLog, HttpServletRequest request, Throwable e) { - // 处理用户信息 - errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); - errorLog.setUserType(WebFrameworkUtils.getUserType(request)); - // 设置异常字段 - errorLog.setExceptionName(e.getClass().getName()); - errorLog.setExceptionMessage(ExceptionUtil.getMessage(e)); - errorLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e)); - errorLog.setExceptionStackTrace(ExceptionUtils.getStackTrace(e)); - StackTraceElement[] stackTraceElements = e.getStackTrace(); - Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空"); - StackTraceElement stackTraceElement = stackTraceElements[0]; - errorLog.setExceptionClassName(stackTraceElement.getClassName()); - errorLog.setExceptionFileName(stackTraceElement.getFileName()); - errorLog.setExceptionMethodName(stackTraceElement.getMethodName()); - errorLog.setExceptionLineNumber(stackTraceElement.getLineNumber()); - // 设置其它字段 - errorLog.setTraceId(TracerUtils.getTraceId()); - errorLog.setApplicationName(applicationName); - errorLog.setRequestUrl(request.getRequestURI()); - Map requestParams = MapUtil.builder() - .put("query", ServletUtil.getParamMap(request)) - .put("body", ServletUtil.getBody(request)).build(); - errorLog.setRequestParams(JsonUtils.toJsonString(requestParams)); - errorLog.setRequestMethod(request.getMethod()); - errorLog.setUserAgent(ServletUtils.getUserAgent(request)); - errorLog.setUserIp(ServletUtil.getClientIP(request)); - errorLog.setExceptionTime(new Date()); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalResponseBodyHandler.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalResponseBodyHandler.java deleted file mode 100644 index ddd0542..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalResponseBodyHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.handler; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.web.core.util.WebFrameworkUtils; -import org.springframework.core.MethodParameter; -import org.springframework.http.MediaType; -import org.springframework.http.server.ServerHttpRequest; -import org.springframework.http.server.ServerHttpResponse; -import org.springframework.http.server.ServletServerHttpRequest; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; - -/** - * 全局响应结果(ResponseBody)处理器 - * - * 不同于在网上看到的很多文章,会选择自动将 Controller 返回结果包上 {@link CommonResult}, - * 在 onemall 中,是 Controller 在返回时,主动自己包上 {@link CommonResult}。 - * 原因是,GlobalResponseBodyHandler 本质上是 AOP,它不应该改变 Controller 返回的数据结构 - * - * 目前,GlobalResponseBodyHandler 的主要作用是,记录 Controller 的返回结果, - * 方便 {@link cn.iocoder.dashboard.framework.logger.apilog.core.filter.ApiAccessLogFilter} 记录访问日志 - */ -@ControllerAdvice -public class GlobalResponseBodyHandler implements ResponseBodyAdvice { - - @Override - @SuppressWarnings("NullableProblems") // 避免 IDEA 警告 - public boolean supports(MethodParameter returnType, Class converterType) { - if (returnType.getMethod() == null) { - return false; - } - // 只拦截返回结果为 CommonResult 类型 - return returnType.getMethod().getReturnType() == CommonResult.class; - } - - @Override - @SuppressWarnings("NullableProblems") // 避免 IDEA 警告 - public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, - ServerHttpRequest request, ServerHttpResponse response) { - // 记录 Controller 结果 - WebFrameworkUtils.setCommonResult(((ServletServerHttpRequest) request).getServletRequest(), (CommonResult) body); - return body; - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java deleted file mode 100644 index 6ef4eac..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.dashboard.framework.web.core.util; - -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; - -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; - -/** - * 专属于 web 包的工具类 - * - * @author 芋道源码 - */ -public class WebFrameworkUtils { - - private static final String REQUEST_ATTRIBUTE_LOGIN_USER_ID = "login_user_id"; - - private static final String REQUEST_ATTRIBUTE_COMMON_RESULT = "common_result"; - - public static void setLoginUserId(ServletRequest request, Long userId) { - request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID, userId); - } - - /** - * 获得当前用户的编号,从请求中 - * - * @param request 请求 - * @return 用户编号 - */ - public static Long getLoginUserId(HttpServletRequest request) { - return (Long) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID); - } - - public static Integer getUserType(HttpServletRequest request) { - return UserTypeEnum.ADMIN.getValue(); // TODO 芋艿:等后续优化 - } - - public static void setCommonResult(ServletRequest request, CommonResult result) { - request.setAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT, result); - } - - public static CommonResult getCommonResult(ServletRequest request) { - return (CommonResult) request.getAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT); - } - -} diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/package-info.java b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/package-info.java deleted file mode 100644 index f4b8100..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 针对 SpringMVC 的基础封装 - */ -package cn.iocoder.dashboard.framework.web; diff --git a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/《芋道 Spring Boot SpringMVC 入门》.md b/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/《芋道 Spring Boot SpringMVC 入门》.md deleted file mode 100644 index 7c36a15..0000000 --- a/yudao-framework/yudao-framework-all/src/main/java/cn/iocoder/dashboard/framework/web/《芋道 Spring Boot SpringMVC 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml new file mode 100644 index 0000000..7f9b9f6 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml @@ -0,0 +1,18 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-monitor + jar + + ${artifactId} + 服务监控,提供链路追踪、日志服务、指标收集等等功能 + https://github.com/YunaiV/ruoyi-vue-pro + + diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index b3feb9d..73753ff 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -28,16 +28,16 @@ - org.springframework - spring-web + cn.iocoder.boot + yudao-spring-boot-starter-web provided - - jakarta.servlet - jakarta.servlet-api - provided - + + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java index 6343885..65910b1 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.framework.mybatis.core.handler; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.dashboard.framework.security.core.LoginUser; -import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; @@ -21,10 +20,9 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) { - LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); BaseDO baseDO = (BaseDO) metaObject.getOriginalObject(); - Date current = new Date(); + Date current = new Date(); // 创建时间为空,则以当前时间为插入时间 if (Objects.isNull(baseDO.getCreateTime())) { baseDO.setCreateTime(current); @@ -33,31 +31,32 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { if (Objects.isNull(baseDO.getUpdateTime())) { baseDO.setUpdateTime(current); } + + Long userId = WebFrameworkUtils.getLoginUserId(); // 当前登录用户不为空,创建人为空,则当前登录用户为创建人 - if (Objects.nonNull(loginUser) && Objects.isNull(baseDO.getCreator())) { - baseDO.setCreator(loginUser.getId().toString()); + if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) { + baseDO.setCreator(userId.toString()); } // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 - if (Objects.nonNull(loginUser) && Objects.isNull(baseDO.getUpdater())) { - baseDO.setUpdater(loginUser.getId().toString()); + if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) { + baseDO.setUpdater(userId.toString()); } } } @Override public void updateFill(MetaObject metaObject) { - Object modifyTime = getFieldValByName("updateTime", metaObject); - Object modifier = getFieldValByName("updater", metaObject); - // 获取登录用户信息 - LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); - // 更新时间为空,则以当前时间为更新时间 + Object modifyTime = getFieldValByName("updateTime", metaObject); if (Objects.isNull(modifyTime)) { setFieldValByName("updateTime", new Date(), metaObject); } + // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 - if (Objects.nonNull(loginUser) && Objects.isNull(modifier)) { - setFieldValByName("updater", loginUser.getId().toString(), metaObject); + Object modifier = getFieldValByName("updater", metaObject); + Long userId = WebFrameworkUtils.getLoginUserId(); + if (Objects.nonNull(userId) && Objects.isNull(modifier)) { + setFieldValByName("updater", userId.toString(), metaObject); } } } diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml b/yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml new file mode 100644 index 0000000..3c0486c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/pom.xml @@ -0,0 +1,44 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-operatelog + jar + + ${artifactId} + 操作日志 + https://github.com/YunaiV/ruoyi-vue-pro + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + provided + + + + + com.google.guava + guava + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java new file mode 100644 index 0000000..c4e784b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.framework.operatelog.config; + +import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class YudaoOperateLogAutoConfiguration { + + @Bean + public OperateLogAspect operateLogAspect() { + return new OperateLogAspect(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java new file mode 100644 index 0000000..2f9ecaf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/annotations/OperateLog.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.framework.operatelog.core.annotations; + +import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 操作日志注解 + * + * @author 芋道源码 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface OperateLog { + + // ========== 模块字段 ========== + + /** + * 操作模块 + * + * 为空时,会尝试读取 {@link Api#value()} 属性 + */ + String module() default ""; + /** + * 操作名 + * + * 为空时,会尝试读取 {@link ApiOperation#value()} 属性 + */ + String name() default ""; + /** + * 操作分类 + * + * 实际并不是数组,因为枚举不能设置 null 作为默认值 + */ + OperateTypeEnum[] type() default {}; + + // ========== 开关字段 ========== + + /** + * 是否记录操作日志 + */ + boolean enable() default true; + /** + * 是否记录方法参数 + */ + boolean logArgs() default true; + /** + * 是否记录方法结果的数据 + */ + boolean logResultData() default true; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java new file mode 100644 index 0000000..b6a6cd2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java @@ -0,0 +1,354 @@ +package cn.iocoder.yudao.framework.operatelog.core.aop; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; +import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.util.json.JsonUtils; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import com.google.common.collect.Maps; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.IntStream; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; + +/** + * 拦截使用 @OperateLog 注解,如果满足条件,则生成操作日志。 + * 满足如下任一条件,则会进行记录: + * 1. 使用 @ApiOperation + 非 @GetMapping + * 2. 使用 @OperateLog 注解 + * + * 但是,如果声明 @OperateLog 注解时,将 enable 属性设置为 false 时,强制不记录。 + * + * @author 芋道源码 + */ +@Aspect +@Slf4j +public class OperateLogAspect { + + /** + * 用于记录操作内容的上下文 + * + * @see OperateLogCreateReqDTO#getContent() + */ + private static final ThreadLocal CONTENT = new ThreadLocal<>(); + /** + * 用于记录拓展字段的上下文 + * + * @see OperateLogCreateReqDTO#getExts() + */ + private static final ThreadLocal> EXTS = new ThreadLocal<>(); + + @Resource + private OperateLogFrameworkService operateLogFrameworkService; + + @Around("@annotation(apiOperation)") + public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable { + // 可能也添加了 @ApiOperation 注解 + OperateLog operateLog = getMethodAnnotation(joinPoint, OperateLog.class); + return around0(joinPoint, operateLog, apiOperation); + } + + @Around("!@annotation(io.swagger.annotations.ApiOperation) && @annotation(operateLog)") // 兼容处理,只添加 @OperateLog 注解的情况 + public Object around(ProceedingJoinPoint joinPoint, OperateLog operateLog) throws Throwable { + return around0(joinPoint, operateLog, null); + } + + private Object around0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) throws Throwable { + // 记录开始时间 + Date startTime = new Date(); + try { + // 执行原有方法 + Object result = joinPoint.proceed(); + // 记录正常执行时的操作日志 + this.log(joinPoint, operateLog, apiOperation, startTime, result, null); + return result; + } catch (Throwable exception) { + this.log(joinPoint, operateLog, apiOperation, startTime, null, exception); + throw exception; + } finally { + clearThreadLocal(); + } + } + + public static void setContent(String content) { + CONTENT.set(content); + } + + public static void addExt(String key, Object value) { + if (EXTS.get() == null) { + EXTS.set(new HashMap<>()); + } + EXTS.get().put(key, value); + } + + private static void clearThreadLocal() { + CONTENT.remove(); + EXTS.remove(); + } + + private void log(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, + Date startTime, Object result, Throwable exception) { + try { + // 判断不记录的情况 + if (!isLogEnable(joinPoint, operateLog)) { + return; + } + // 真正记录操作日志 + this.log0(joinPoint, operateLog, apiOperation, startTime, result, exception); + } catch (Throwable ex) { + log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) operateLog({}) apiOperation({}) result({}) exception({}) ]", + joinPoint, operateLog, apiOperation, result, exception, ex); + } + } + + private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation, + Date startTime, Object result, Throwable exception) { + OperateLogCreateReqDTO operateLogDTO = new OperateLogCreateReqDTO(); + // 补全通用字段 + operateLogDTO.setTraceId(TracerUtils.getTraceId()); + operateLogDTO.setStartTime(startTime); + // 补充用户信息 + fillUserFields(operateLogDTO); + // 补全模块信息 + fillModuleFields(operateLogDTO, joinPoint, operateLog, apiOperation); + // 补全请求信息 + fillRequestFields(operateLogDTO); + // 补全方法信息 + fillMethodFields(operateLogDTO, joinPoint, operateLog, startTime, result, exception); + + // 异步记录日志 + operateLogFrameworkService.createOperateLogAsync(operateLogDTO); + } + + private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) { + operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId()); + } + + private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO, + ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) { + // module 属性 + if (operateLog != null) { + operateLogDTO.setModule(operateLog.module()); + } + if (StrUtil.isEmpty(operateLogDTO.getModule())) { + Api api = getClassAnnotation(joinPoint, Api.class); + if (api != null) { + // 优先读取 @API 的 name 属性 + if (StrUtil.isNotEmpty(api.value())) { + operateLogDTO.setModule(api.value()); + } + // 没有的话,读取 @API 的 tags 属性 + if (StrUtil.isEmpty(operateLogDTO.getModule()) && ArrayUtil.isNotEmpty(api.tags())) { + operateLogDTO.setModule(api.tags()[0]); + } + } + } + // name 属性 + if (operateLog != null) { + operateLogDTO.setName(operateLog.name()); + } + if (StrUtil.isEmpty(operateLogDTO.getName()) && apiOperation != null) { + operateLogDTO.setName(apiOperation.value()); + } + // type 属性 + if (operateLog != null && ArrayUtil.isNotEmpty(operateLog.type())) { + operateLogDTO.setType(operateLog.type()[0].getType()); + } + if (operateLogDTO.getType() == null) { + RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); + OperateTypeEnum operateLogType = convertOperateLogType(requestMethod); + operateLogDTO.setType(operateLogType != null ? operateLogType.getType() : null); + } + // content 和 exts 属性 + operateLogDTO.setContent(CONTENT.get()); + operateLogDTO.setExts(EXTS.get()); + } + + private static void fillRequestFields(OperateLogCreateReqDTO operateLogDTO) { + // 获得 Request 对象 + HttpServletRequest request = ServletUtils.getRequest(); + if (request == null) { + return; + } + // 补全请求信息 + operateLogDTO.setRequestMethod(request.getMethod()); + operateLogDTO.setRequestUrl(request.getRequestURI()); + operateLogDTO.setUserIp(ServletUtil.getClientIP(request)); + operateLogDTO.setUserAgent(ServletUtils.getUserAgent(request)); + } + + private static void fillMethodFields(OperateLogCreateReqDTO operateLogDTO, + ProceedingJoinPoint joinPoint, OperateLog operateLog, + Date startTime, Object result, Throwable exception) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + operateLogDTO.setJavaMethod(methodSignature.toString()); + if (operateLog == null || operateLog.logArgs()) { + operateLogDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); + } + if (operateLog == null || operateLog.logResultData()) { + operateLogDTO.setResultData(obtainResultData(result)); + } + operateLogDTO.setDuration((int) (System.currentTimeMillis() - startTime.getTime())); + // (正常)处理 resultCode 和 resultMsg 字段 + if (result != null) { + if (result instanceof CommonResult) { + CommonResult commonResult = (CommonResult) result; + operateLogDTO.setResultCode(commonResult.getCode()); + operateLogDTO.setResultMsg(commonResult.getMsg()); + } else { + operateLogDTO.setResultCode(SUCCESS.getCode()); + } + } + // (异常)处理 resultCode 和 resultMsg 字段 + if (exception != null) { + operateLogDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); + operateLogDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); + } + } + + private static boolean isLogEnable(ProceedingJoinPoint joinPoint, OperateLog operateLog) { + // 有 @OperateLog 注解的情况下 + if (operateLog != null) { + return operateLog.enable(); + } + // 没有 @ApiOperation 注解的情况下,只记录 POST、PUT、DELETE 的情况 + return obtainFirstLogRequestMethod(obtainRequestMethod(joinPoint)) != null; + } + + private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) { + if (ArrayUtil.isEmpty(requestMethods)) { + return null; + } + return Arrays.stream(requestMethods).filter(requestMethod -> + requestMethod == RequestMethod.POST + || requestMethod == RequestMethod.PUT + || requestMethod == RequestMethod.DELETE) + .findFirst().orElse(null); + } + + private static RequestMethod obtainFirstMatchRequestMethod(RequestMethod[] requestMethods) { + if (ArrayUtil.isEmpty(requestMethods)) { + return null; + } + // 优先,匹配最优的 POST、PUT、DELETE + RequestMethod result = obtainFirstLogRequestMethod(requestMethods); + if (result != null) { + return result; + } + // 然后,匹配次优的 GET + result = Arrays.stream(requestMethods).filter(requestMethod -> requestMethod == RequestMethod.GET) + .findFirst().orElse(null); + if (result != null) { + return result; + } + // 兜底,获得第一个 + return requestMethods[0]; + } + + private static OperateTypeEnum convertOperateLogType(RequestMethod requestMethod) { + if (requestMethod == null) { + return null; + } + switch (requestMethod) { + case GET: + return OperateTypeEnum.GET; + case POST: + return OperateTypeEnum.CREATE; + case PUT: + return OperateTypeEnum.UPDATE; + case DELETE: + return OperateTypeEnum.DELETE; + default: + return OperateTypeEnum.OTHER; + } + } + + private static RequestMethod[] obtainRequestMethod(ProceedingJoinPoint joinPoint) { + RequestMapping requestMapping = AnnotationUtils.getAnnotation( // 使用 Spring 的工具类,可以处理 @RequestMapping 别名注解 + ((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class); + return requestMapping != null ? requestMapping.method() : new RequestMethod[]{}; + } + + @SuppressWarnings("SameParameterValue") + private static T getMethodAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { + return ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(annotationClass); + } + + @SuppressWarnings("SameParameterValue") + private static T getClassAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { + return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass); + } + + private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) { + // TODO 提升:参数脱敏和忽略 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + String[] argNames = methodSignature.getParameterNames(); + Object[] argValues = joinPoint.getArgs(); + // 拼接参数 + Map args = Maps.newHashMapWithExpectedSize(argValues.length); + for (int i = 0; i < argNames.length; i++) { + String argName = argNames[i]; + Object argValue = argValues[i]; + // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 + args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); + } + return JsonUtils.toJsonString(args); + } + + private static String obtainResultData(Object result) { + // TODO 提升:结果脱敏和忽略 + if (result instanceof CommonResult) { + result = ((CommonResult) result).getData(); + } + return JsonUtils.toJsonString(result); + } + + private static boolean isIgnoreArgs(Object object) { + Class clazz = object.getClass(); + // 处理数组的情况 + if (clazz.isArray()) { + return IntStream.range(0, Array.getLength(object)) + .anyMatch(index -> isIgnoreArgs(Array.get(object, index))); + } + // 递归,处理数组、Collection、Map 的情况 + if (Collection.class.isAssignableFrom(clazz)) { + return ((Collection) object).stream() + .anyMatch((Predicate) o -> isIgnoreArgs(object)); + } + if (Map.class.isAssignableFrom(clazz)) { + return isIgnoreArgs(((Map) object).values()); + } + // obj + return object instanceof MultipartFile + || object instanceof HttpServletRequest + || object instanceof HttpServletResponse; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java new file mode 100644 index 0000000..8dd98d4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.framework.operatelog.core.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.Map; + +/** + * 操作日志创建 Request DTO + */ +@Data +public class OperateLogCreateReqDTO { + + @ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab") + @NotEmpty(message = "链路追踪编号不能为空") + private String traceId; + + @ApiModelProperty(value = "用户编号", required = true, example = "1024") + @NotNull(message = "用户编号不能为空") + private Long userId; + + @ApiModelProperty(value = "操作模块", required = true, example = "订单") + @NotEmpty(message = "操作模块不能为空") + private String module; + + @ApiModelProperty(value = "操作名", required = true, example = "创建订单") + @NotEmpty(message = "操作名") + private String name; + + @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类") + @NotNull(message = "操作分类不能为空") + private Integer type; + + @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") + private String content; + + @ApiModelProperty(value = "拓展字段", example = "{'orderId': 1}") + private Map exts; + + @ApiModelProperty(value = "请求方法名", required = true, example = "GET") + @NotEmpty(message = "请求方法名不能为空") + private String requestMethod; + + @ApiModelProperty(value = "请求地址", required = true, example = "/xxx/yyy") + @NotEmpty(message = "请求地址不能为空") + private String requestUrl; + + @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") + @NotEmpty(message = "用户 IP 不能为空") + private String userIp; + + @ApiModelProperty(value = "浏览器 UserAgent", required = true, example = "Mozilla/5.0") + @NotEmpty(message = "浏览器 UserAgent 不能为空") + private String userAgent; + + @ApiModelProperty(value = "Java 方法名", required = true, example = "cn.iocoder.dashboard.UserController.save(...)") + @NotEmpty(message = "Java 方法名不能为空") + private String javaMethod; + + @ApiModelProperty(value = "Java 方法的参数") + private String javaMethodArgs; + + @ApiModelProperty(value = "开始时间", required = true) + @NotNull(message = "开始时间不能为空") + private Date startTime; + + @ApiModelProperty(value = "执行时长,单位:毫秒", required = true) + @NotNull(message = "执行时长不能为空") + private Integer duration; + + @ApiModelProperty(value = "结果码", required = true) + @NotNull(message = "结果码不能为空") + private Integer resultCode; + + @ApiModelProperty(value = "结果提示") + private String resultMsg; + + @ApiModelProperty(value = "结果数据") + private String resultData; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java new file mode 100644 index 0000000..65ee26d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/enums/OperateTypeEnum.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.framework.operatelog.core.enums; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 操作日志的操作类型 + * + * @author ruoyi + */ +@Getter +@AllArgsConstructor +public enum OperateTypeEnum { + + /** + * 查询 + * + * 绝大多数情况下,不会记录查询动作,因为过于大量显得没有意义。 + * 在有需要的时候,通过声明 {@link OperateLog} 注解来记录 + */ + GET(1), + /** + * 新增 + */ + CREATE(2), + /** + * 修改 + */ + UPDATE(3), + /** + * 删除 + */ + DELETE(4), + /** + * 导出 + */ + EXPORT(5), + /** + * 导入 + */ + IMPORT(6), + /** + * 其它 + * + * 在无法归类时,可以选择使用其它。因为还有操作名可以进一步标识 + */ + OTHER(0); + + /** + * 类型 + */ + private final Integer type; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java new file mode 100644 index 0000000..58aa3d5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.operatelog.core; diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java new file mode 100644 index 0000000..ef20e2e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkService.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.framework.operatelog.core.service; + +import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO; + +import java.util.concurrent.Future; + +public interface OperateLogFrameworkService { + + /** + * 异步记录操作日志 + * + * @param reqVO 操作日志请求 + * @return true: 记录成功,false: 记录失败 + */ + Future createOperateLogAsync(OperateLogCreateReqDTO reqVO); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java new file mode 100644 index 0000000..a9801e5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/util/OperateLogUtils.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.operatelog.core.util; + +import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; + +/** + * 操作日志工具类 + * 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段 + * + * @author 芋道源码 + */ +public class OperateLogUtils { + + public static void setContent(String content) { + OperateLogAspect.setContent(content); + } + + public static void addExt(String key, Object value) { + OperateLogAspect.addExt(key, value); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java new file mode 100644 index 0000000..d272b53 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java @@ -0,0 +1,6 @@ +/** + * 用户操作日志:记录用户的操作,用于对用户的操作的审计与追溯,永久保存。 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.framework.operatelog; diff --git a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml new file mode 100644 index 0000000..0933bf9 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml @@ -0,0 +1,18 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-protection + jar + + ${artifactId} + 服务保证,提供分布式锁、幂等、限流、熔断等等功能 + https://github.com/YunaiV/ruoyi-vue-pro + + diff --git a/yudao-framework/yudao-spring-boot-starter-security/pom.xml b/yudao-framework/yudao-spring-boot-starter-security/pom.xml new file mode 100644 index 0000000..c62863b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/pom.xml @@ -0,0 +1,38 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-security + jar + + ${artifactId} + 用户的认证、权限的校验 + https://github.com/YunaiV/ruoyi-vue-pro + + + + cn.iocoder.boot + yudao-common + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-security + + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java new file mode 100644 index 0000000..d45c948 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.framework.security.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.time.Duration; + +@ConfigurationProperties(prefix = "yudao.security") +@Validated +@Data +public class SecurityProperties { + + /** + * HTTP 请求时,访问令牌的请求 Header + */ + @NotEmpty(message = "Token Header 不能为空") + private String tokenHeader; + /** + * Token 过期时间 + */ + @NotNull(message = "Token 过期时间不能为空") + private Duration tokenTimeout; + /** + * Token 秘钥 + */ + @NotEmpty(message = "Token 秘钥不能为空") + private String tokenSecret; + /** + * Session 过期时间 + * + * 当 User 用户超过当前时间未操作,则 Session 会过期 + */ + @NotNull(message = "Session 过期时间不能为空") + private Duration sessionTimeout; + + /** + * mock 模式的开关 + */ + @NotNull(message = "mock 模式的开关不能为空") + private Boolean mockEnable; + /** + * mock 模式的秘钥 + * 一定要配置秘钥,保证安全性 + */ + @NotEmpty(message = "mock 模式的秘钥不能为空") // 这里设置了一个默认值,因为实际上只有 mockEnable 为 true 时才需要配置。 + private String mockSecret = "yudaoyuanma"; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityConfiguration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityConfiguration.java new file mode 100644 index 0000000..d095e90 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityConfiguration.java @@ -0,0 +1,167 @@ +package cn.iocoder.yudao.framework.security.config; + +import cn.iocoder.yudao.framework.security.core.filter.JwtAuthenticationTokenFilter; +import cn.iocoder.yudao.framework.security.core.handler.LogoutSuccessHandlerImpl; +import cn.iocoder.yudao.framework.web.config.WebProperties; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +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.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import javax.annotation.Resource; + +/** + * spring security配置 + * + * @author 芋道源码 + */ +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +@EnableConfigurationProperties(SecurityProperties.class) +public class YudaoSecurityConfiguration extends WebSecurityConfigurerAdapter { + + /** + * 自定义用户认证逻辑 + */ + @Resource + private UserDetailsService userDetailsService; + + /** + * 认证失败处理类 + */ + @Resource + private AuthenticationEntryPoint unauthorizedHandler; + /** + * 权限不够处理器 + */ + @Resource + private AccessDeniedHandler accessDeniedHandler; + /** + * 退出处理类 + */ + @Resource + private LogoutSuccessHandlerImpl logoutSuccessHandler; + + /** + * Token 认证过滤器 + */ + @Resource + private JwtAuthenticationTokenFilter authenticationTokenFilter; + + @Resource + private WebProperties webProperties; + + @Value("${spring.boot.admin.context-path:''}") + private String adminSeverContextPath; + + /** + * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 + * 通过覆写父类的该方法,添加 @Bean 注解,解决该问题 + */ + @Override + @Bean + @ConditionalOnMissingBean(AuthenticationManager.class) + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + /** + * Spring Security 加密器 + * 考虑到安全性,这里采用 BCryptPasswordEncoder 加密器 + * + * @see Password Encoding with Spring Security + */ + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + /** + * 身份认证接口 + */ + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService) + .passwordEncoder(passwordEncoder()); + } + + /** + * 配置 URL 的安全配置 + * + * anyRequest | 匹配所有请求路径 + * access | SpringEl表达式结果为true时可以访问 + * anonymous | 匿名可以访问 + * denyAll | 用户不能访问 + * fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录) + * hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问 + * hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问 + * hasAuthority | 如果有参数,参数表示权限,则其权限可以访问 + * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 + * hasRole | 如果有参数,参数表示角色,则其角色可以访问 + * permitAll | 用户可以任意访问 + * rememberMe | 允许通过remember-me登录的用户访问 + * authenticated | 用户登录后可访问 + */ + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + httpSecurity + // 开启跨域 + .cors().and() + // CSRF 禁用,因为不使用 Session + .csrf().disable() + // 基于 token 机制,所以不需要 Session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + // 一堆自定义的 Spring Security 处理器 + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler) + .accessDeniedHandler(accessDeniedHandler).and() + // 设置每个请求的权限 + .authorizeRequests() + // 登陆的接口,可匿名访问 + .antMatchers(api("/login")).anonymous() + // 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去 + .antMatchers(api("/system/captcha/**")).anonymous() + // 静态资源,可匿名访问 + .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() + // 文件的获取接口,可匿名访问 + .antMatchers(api("/infra/file/get/**")).anonymous() + // Swagger 接口文档 + .antMatchers("/swagger-ui.html").anonymous() + .antMatchers("/swagger-resources/**").anonymous() + .antMatchers("/webjars/**").anonymous() + .antMatchers("/*/api-docs").anonymous() + // Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去 + .antMatchers(adminSeverContextPath).anonymous() + .antMatchers(adminSeverContextPath + "/**").anonymous() + // Spring Boot Actuator 的安全配置 + .antMatchers("/actuator").anonymous() + .antMatchers("/actuator/**").anonymous() + // Druid 监控 TODO 芋艿:需要抽象出去 + .antMatchers("/druid/**").anonymous() + // 短信回调 API TODO 芋艿:需要抽象出去 + .antMatchers(api("/system/sms/callback/**")).anonymous() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated() + .and() + .headers().frameOptions().disable(); + httpSecurity.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); + // 添加 JWT Filter + httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + } + + private String api(String url) { + return webProperties.getApiPrefix() + url; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java new file mode 100644 index 0000000..2c2ff89 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.framework.security.core; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Date; +import java.util.Set; + +/** + * 登陆用户信息 + * + * @author 芋道源码 + */ +@Data +public class LoginUser implements UserDetails { + + /** + * 用户编号 + */ + private Long id; + /** + * 科室编号 + */ + private Long deptId; + /** + * 角色编号数组 + */ + private Set roleIds; + /** + * 最后更新时间 + */ + private Date updateTime; + + /** + * 用户名 + */ + private String username; + /** + * 密码 + */ + private String password; + /** + * 状态 + */ + private Integer status; + + @Override + @JsonIgnore// 避免序列化 + public String getPassword() { + return password; + } + + @Override + @JsonIgnore + public String getUsername() { + return username; + } + + @Override + @JsonIgnore// 避免序列化 + public boolean isEnabled() { + return CommonStatusEnum.ENABLE.getStatus().equals(status); + } + + @Override + @JsonIgnore// 避免序列化 + public Collection getAuthorities() { + return null; + } + + @Override + @JsonIgnore// 避免序列化 + public boolean isAccountNonExpired() { + return true; // 返回 true,不依赖 Spring Security 判断 + } + + @Override + @JsonIgnore// 避免序列化 + public boolean isAccountNonLocked() { + return true; // 返回 true,不依赖 Spring Security 判断 + } + + @Override + @JsonIgnore// 避免序列化 + public boolean isCredentialsNonExpired() { + return true; // 返回 true,不依赖 Spring Security 判断 + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/enums/DataScopeEnum.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/enums/DataScopeEnum.java new file mode 100644 index 0000000..ac3396c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/enums/DataScopeEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.security.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 数据范围枚举类 + * + * 用于实现数据级别的权限 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum DataScopeEnum { + + ALL(1), // 全部数据权限 + DEPT_CUSTOM(2), // 指定部门数据权限 + DEPT_ONLY(3), // 部门数据权限 + DEPT_AND_CHILD(4), // 部门及以下数据权限 + DEPT_SELF(5); // 仅本人数据权限 + + /** + * 范围 + */ + private final Integer score; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..cde7662 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.framework.security.core.filter; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.annotation.Resource; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * JWT 过滤器,验证 token 的有效性 + * 验证通过后,获得 {@link LoginUser} 信息,并加入到 Spring Security 上下文 + * + * @author ruoyi + */ +@Component +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + @Resource + private SecurityProperties securityProperties; + @Resource + private SecurityAuthFrameworkService authService; + @Resource + private GlobalExceptionHandler globalExceptionHandler; + + @Override + @SuppressWarnings("NullableProblems") + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException { + String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); + if (StrUtil.isNotEmpty(token)) { + try { + // 验证 token 有效性 + LoginUser loginUser = authService.verifyTokenAndRefresh(token); + // 模拟 Login 功能,方便日常开发调试 + if (loginUser == null) { + loginUser = this.mockLoginUser(token); + } + // 设置当前用户 + if (loginUser != null) { + SecurityFrameworkUtils.setLoginUser(loginUser, request); + } + } catch (Throwable ex) { + CommonResult result = globalExceptionHandler.allExceptionHandler(request, ex); + ServletUtils.writeJSON(response, result); + return; + } + } + + // 继续过滤链 + chain.doFilter(request, response); + } + + /** + * 模拟登陆用户,方便日常开发调试 + * + * 注意,在线上环境下,一定要关闭该功能!!! + * + * @param token 模拟的 token,格式为 {@link SecurityProperties#getTokenSecret()} + 用户编号 + * @return 模拟的 LoginUser + */ + private LoginUser mockLoginUser(String token) { + if (!securityProperties.getMockEnable()) { + return null; + } + // 必须以 mockSecret 开头 + if (!token.startsWith(securityProperties.getMockSecret())) { + return null; + } + Long userId = Long.valueOf(token.substring(securityProperties.getMockSecret().length())); + return authService.mockLogin(userId); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java new file mode 100644 index 0000000..b2fd4a5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.framework.security.core.handler; + +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.access.ExceptionTranslationFilter; +import org.springframework.stereotype.Component; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED; + +/** + * 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。 + * + * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#handleAccessDeniedException(HttpServletRequest, HttpServletResponse, FilterChain, AccessDeniedException)} 方法,调用当前类 + * + * @author 芋道源码 + */ +@Component +@Slf4j +@SuppressWarnings("JavadocReference") +public class AccessDeniedHandlerImpl implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) + throws IOException, ServletException { + // 打印 warn 的原因是,不定期合并 warn,看看有没恶意破坏 + log.warn("[commence][访问 URL({}) 时,用户({}) 权限不够]", request.getRequestURI(), + SecurityFrameworkUtils.getLoginUser().getId(), e); + // 返回 403 + ServletUtils.writeJSON(response, CommonResult.error(UNAUTHORIZED)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java new file mode 100644 index 0000000..1c71ed0 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.security.core.handler; + +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.ExceptionTranslationFilter; +import org.springframework.stereotype.Component; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED; + +/** + * 访问一个需要认证的 URL 资源,但是此时自己尚未认证(登录)的情况下,返回 {@link GlobalErrorCodeConstants#UNAUTHORIZED} 错误码,从而使前端重定向到登录页 + * + * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#sendStartAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, AuthenticationException)} 方法,调用当前类 + * + * @author ruoyi + */ +@Component +@Slf4j +@SuppressWarnings("JavadocReference") // 忽略文档引用报错 +public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { + log.debug("[commence][访问 URL({}) 时,没有登录]", request.getRequestURI(), e); + // 返回 401 + ServletUtils.writeJSON(response, CommonResult.error(UNAUTHORIZED)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java new file mode 100644 index 0000000..3b099bf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.framework.security.core.handler; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +/** + * 自定义退出处理器 + * + * @author ruoyi + */ +@Component +public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler { + + @Resource + private SecurityProperties securityProperties; + + @Resource + private SecurityAuthFrameworkService securityFrameworkService; + + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + // 执行退出 + String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); + if (StrUtil.isNotBlank(token)) { + securityFrameworkService.logout(token); + } + // 返回成功 + ServletUtils.writeJSON(response, CommonResult.success(null)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java new file mode 100644 index 0000000..28c8f6d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.security.core.service; + +import cn.iocoder.yudao.framework.security.core.LoginUser; +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * Security 框架 Auth Service 接口,定义 security 组件需要的功能 + * + * @author 芋道源码 + */ +public interface SecurityAuthFrameworkService extends UserDetailsService { + + /** + * 校验 token 的有效性,并获取用户信息 + * 通过后,刷新 token 的过期时间 + * + * @param token token + * @return 用户信息 + */ + LoginUser verifyTokenAndRefresh(String token); + + /** + * 模拟指定用户编号的 LoginUser + * + * @param userId 用户编号 + * @return 登录用户 + */ + LoginUser mockLogin(Long userId); + + /** + * 基于 token 退出登录 + * + * @param token token + */ + void logout(String token); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java new file mode 100644 index 0000000..75f11b1 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityPermissionFrameworkService.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.framework.security.core.service; + +/** + * Security 框架 Permission Service 接口,定义 security 组件需要的功能 + * + * @author 芋道源码 + */ +public interface SecurityPermissionFrameworkService { + + /** + * 判断是否有权限 + * + * @param permission 权限 + * @return 是否 + */ + boolean hasPermission(String permission); + + /** + * 判断是否有权限,任一一个即可 + * + * @param permissions 权限 + * @return 是否 + */ + boolean hasAnyPermissions(String... permissions); + + /** + * 判断是否有角色 + * + * 注意,角色使用的是 SysRoleDO 的 code 标识 + * + * @param role 角色 + * @return 是否 + */ + boolean hasRole(String role); + + /** + * 判断是否有角色,任一一个即可 + * + * @param roles 角色数组 + * @return 是否 + */ + boolean hasAnyRoles(String... roles); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java new file mode 100644 index 0000000..a8360c4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.framework.security.core.util; + +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import org.springframework.lang.Nullable; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import java.util.Set; + +/** + * 安全服务工具类 + * + * @author 芋道源码 + */ +public class SecurityFrameworkUtils { + + private SecurityFrameworkUtils() {} + + /** + * 从请求中,获得认证 Token + * + * @param request 请求 + * @param header 认证 Token 对应的 Header 名字 + * @return 认证 Token + */ + public static String obtainAuthorization(HttpServletRequest request, String header) { + String authorization = request.getHeader(header); + if (!StringUtils.hasText(authorization)) { + return null; + } + int index = authorization.indexOf("Bearer "); + if (index == -1) { // 未找到 + return null; + } + return authorization.substring(index + 7).trim(); + } + + /** + * 获取当前用户 + * + * @return 当前用户 + */ + @Nullable + public static LoginUser getLoginUser() { + SecurityContext context = SecurityContextHolder.getContext(); + if (context == null) { + return null; + } + Authentication authentication = context.getAuthentication(); + if (authentication == null) { + return null; + } + return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null; + } + + /** + * 获得当前用户的编号,从上下文中 + * + * @return 用户编号 + */ + @Nullable + public static Long getLoginUserId() { + LoginUser loginUser = getLoginUser(); + return loginUser != null ? loginUser.getId() : null; + } + + /** + * 获得当前用户的角色编号数组 + * + * @return 角色编号数组 + */ + @Nullable + public static Set getLoginUserRoleIds() { + LoginUser loginUser = getLoginUser(); + return loginUser != null ? loginUser.getRoleIds() : null; + } + + /** + * 设置当前用户 + * + * @param loginUser 登陆用户 + * @param request 请求 + */ + public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) { + // 创建 UsernamePasswordAuthenticationToken 对象 + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( + loginUser, null, null); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + // 设置到上下文 + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + // 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号; + // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息 + WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/package-info.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/package-info.java new file mode 100644 index 0000000..dc95b4e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/package-info.java @@ -0,0 +1,7 @@ +/** + * 基于 Spring Security 框架 + * 实现安全认证功能 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.framework.security; diff --git a/yudao-framework/yudao-spring-boot-starter-security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md b/yudao-framework/yudao-spring-boot-starter-security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md new file mode 100644 index 0000000..b8a8931 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md @@ -0,0 +1,2 @@ +* 芋道 Spring Security 入门: +* Spring Security 基本概念: diff --git a/yudao-framework/yudao-spring-boot-starter-web/pom.xml b/yudao-framework/yudao-spring-boot-starter-web/pom.xml new file mode 100644 index 0000000..a49d707 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/pom.xml @@ -0,0 +1,59 @@ + + + + cn.iocoder.boot + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-web + jar + + ${artifactId} + 用户的认证、权限的校验 + https://github.com/YunaiV/ruoyi-vue-pro + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.github.xiaoymin + knife4j-spring-boot-starter + + + io.swagger + swagger-annotations + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.security + spring-security-core + provided + + + + + io.github.resilience4j + resilience4j-ratelimiter + provided + + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java new file mode 100644 index 0000000..7dc78c4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.apilog.config; + +import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter; +import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; +import cn.iocoder.yudao.framework.web.config.WebProperties; +import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration; +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.Filter; + +@Configuration +@AutoConfigureAfter(YudaoWebAutoConfiguration.class) +public class YudaoApiLogAutoConfiguration { + + /** + * 创建 ApiAccessLogFilter Bean,记录 API 请求日志 + */ + @Bean + public FilterRegistrationBean apiAccessLogFilter(WebProperties webProperties, + @Value("${spring.application.name}") String applicationName, + ApiAccessLogFrameworkService apiAccessLogFrameworkService) { + ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogFrameworkService); + return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER); + } + + private static FilterRegistrationBean createFilterBean(T filter, Integer order) { + FilterRegistrationBean bean = new FilterRegistrationBean<>(filter); + bean.setOrder(order); + return bean; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java new file mode 100644 index 0000000..422ab7c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.framework.apilog.core.filter; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO; +import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.web.config.WebProperties; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.framework.util.date.DateUtils; +import cn.iocoder.yudao.framework.util.json.JsonUtils; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +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; +import java.util.Date; +import java.util.Map; + +/** + * API 访问日志 Filter + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Slf4j +public class ApiAccessLogFilter extends OncePerRequestFilter { + + private final WebProperties webProperties; + private final String applicationName; + + private final ApiAccessLogFrameworkService apiAccessLogFrameworkService; + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + // 只过滤 API 请求的地址 + return !request.getRequestURI().startsWith(webProperties.getApiPrefix()); + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + // 获得开始时间 + Date beginTim = new Date(); + // 提前获得参数,避免 XssFilter 过滤处理 + Map queryString = ServletUtil.getParamMap(request); + String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtil.getBody(request) : null; + + try { + // 继续过滤器 + filterChain.doFilter(request, response); + // 正常执行,记录日志 + createApiAccessLog(request, beginTim, queryString, requestBody, null); + } catch (Exception ex) { + // 异常执行,记录日志 + createApiAccessLog(request, beginTim, queryString, requestBody, ex); + throw ex; + } + } + + private void createApiAccessLog(HttpServletRequest request, Date beginTime, + Map queryString, String requestBody, Exception ex) { + ApiAccessLogCreateDTO accessLog = new ApiAccessLogCreateDTO(); + try { + this.buildApiAccessLogDTO(accessLog, request, beginTime, queryString, requestBody, ex); + apiAccessLogFrameworkService.createApiAccessLogAsync(accessLog); + } catch (Throwable th) { + log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), JsonUtils.toJsonString(accessLog), th); + } + } + + private void buildApiAccessLogDTO(ApiAccessLogCreateDTO accessLog, HttpServletRequest request, Date beginTime, + Map queryString, String requestBody, Exception ex) { + // 处理用户信息 + accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); + accessLog.setUserType(WebFrameworkUtils.getUserType(request)); + // 设置访问结果 + CommonResult result = WebFrameworkUtils.getCommonResult(request); + if (result != null) { + accessLog.setResultCode(result.getCode()); + accessLog.setResultMsg(result.getMsg()); + } else if (ex != null) { + accessLog.setResultCode(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode()); + accessLog.setResultMsg(ExceptionUtil.getRootCauseMessage(ex)); + } else { + accessLog.setResultCode(0); + accessLog.setResultMsg(""); + } + // 设置其它字段 + accessLog.setTraceId(TracerUtils.getTraceId()); + accessLog.setApplicationName(applicationName); + accessLog.setRequestUrl(request.getRequestURI()); + Map requestParams = MapUtil.builder().put("query", queryString).put("body", requestBody).build(); + accessLog.setRequestParams(JsonUtils.toJsonString(requestParams)); + accessLog.setRequestMethod(request.getMethod()); + accessLog.setUserAgent(ServletUtils.getUserAgent(request)); + accessLog.setUserIp(ServletUtil.getClientIP(request)); + // 持续时间 + accessLog.setBeginTime(beginTime); + accessLog.setEndTime(new Date()); + accessLog.setDuration((int) DateUtils.diff(accessLog.getEndTime(), accessLog.getBeginTime())); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java new file mode 100644 index 0000000..fd7c22e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.framework.apilog.core.service; + +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO; + +import javax.validation.Valid; +import java.util.concurrent.Future; + +/** + * API 访问日志 Framework Service 接口 + * + * @author 芋道源码 + */ +public interface ApiAccessLogFrameworkService { + + /** + * 创建 API 访问日志 + * + * @param createDTO 创建信息 + * @return 是否创建成功 + */ + Future createApiAccessLogAsync(@Valid ApiAccessLogCreateDTO createDTO); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java new file mode 100644 index 0000000..1c55adb --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.framework.apilog.core.service; + +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO; + +import javax.validation.Valid; +import java.util.concurrent.Future; + +/** + * API 错误日志 Framework Service 接口 + * + * @author 芋道源码 + */ +public interface ApiErrorLogFrameworkService { + + /** + * 创建 API 错误日志 + * + * @param createDTO 创建信息 + * @return 是否创建成功 + */ + Future createApiErrorLogAsync(@Valid ApiErrorLogCreateDTO createDTO); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiAccessLogCreateDTO.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiAccessLogCreateDTO.java new file mode 100644 index 0000000..c665853 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiAccessLogCreateDTO.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.framework.apilog.core.service.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + * API 访问日志创建 DTO + * + * @author 芋道源码 + */ +@Data +public class ApiAccessLogCreateDTO { + + /** + * 链路追踪编号 + */ + private String traceId; + /** + * 用户编号 + */ + private Long userId; + /** + * 用户类型 + */ + private Integer userType; + /** + * 应用名 + */ + @NotNull(message = "应用名不能为空") + private String applicationName; + + /** + * 请求方法名 + */ + @NotNull(message = "http 请求方法不能为空") + private String requestMethod; + /** + * 访问地址 + */ + @NotNull(message = "访问地址不能为空") + private String requestUrl; + /** + * 请求参数 + */ + @NotNull(message = "请求参数不能为空") + private String requestParams; + /** + * 用户 IP + */ + @NotNull(message = "ip 不能为空") + private String userIp; + /** + * 浏览器 UA + */ + @NotNull(message = "User-Agent 不能为空") + private String userAgent; + + /** + * 开始请求时间 + */ + @NotNull(message = "开始请求时间不能为空") + private Date beginTime; + /** + * 结束请求时间 + */ + @NotNull(message = "结束请求时间不能为空") + private Date endTime; + /** + * 执行时长,单位:毫秒 + */ + @NotNull(message = "执行时长不能为空") + private Integer duration; + /** + * 结果码 + */ + @NotNull(message = "错误码不能为空") + private Integer resultCode; + /** + * 结果提示 + */ + private String resultMsg; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java new file mode 100644 index 0000000..51258d7 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.framework.apilog.core.service.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Date; + +/** + * API 错误日志创建 DTO + * + * @author 芋道源码 + */ +@Data +@Accessors(chain = true) +public class ApiErrorLogCreateDTO implements Serializable { + + /** + * 链路编号 + */ + private String traceId; + /** + * 账号编号 + */ + private Long userId; + /** + * 用户类型 + */ + private Integer userType; + /** + * 应用名 + */ + @NotNull(message = "应用名不能为空") + private String applicationName; + + /** + * 请求方法名 + */ + @NotNull(message = "http 请求方法不能为空") + private String requestMethod; + /** + * 访问地址 + */ + @NotNull(message = "访问地址不能为空") + private String requestUrl; + /** + * 请求参数 + */ + @NotNull(message = "请求参数不能为空") + private String requestParams; + /** + * 用户 IP + */ + @NotNull(message = "ip 不能为空") + private String userIp; + /** + * 浏览器 UA + */ + @NotNull(message = "User-Agent 不能为空") + private String userAgent; + + /** + * 异常时间 + */ + @NotNull(message = "异常时间不能为空") + private Date exceptionTime; + /** + * 异常名 + */ + @NotNull(message = "异常名不能为空") + private String exceptionName; + /** + * 异常发生的类全名 + */ + @NotNull(message = "异常发生的类全名不能为空") + private String exceptionClassName; + /** + * 异常发生的类文件 + */ + @NotNull(message = "异常发生的类文件不能为空") + private String exceptionFileName; + /** + * 异常发生的方法名 + */ + @NotNull(message = "异常发生的方法名不能为空") + private String exceptionMethodName; + /** + * 异常发生的方法所在行 + */ + @NotNull(message = "异常发生的方法所在行不能为空") + private Integer exceptionLineNumber; + /** + * 异常的栈轨迹异常的栈轨迹 + */ + @NotNull(message = "异常的栈轨迹不能为空") + private String exceptionStackTrace; + /** + * 异常导致的根消息 + */ + @NotNull(message = "异常导致的根消息不能为空") + private String exceptionRootCauseMessage; + /** + * 异常导致的消息 + */ + @NotNull(message = "异常导致的消息不能为空") + private String exceptionMessage; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/package-info.java new file mode 100644 index 0000000..cb93f3d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/package-info.java @@ -0,0 +1,8 @@ +/** + * API 日志:包含两类 + * 1. API 访问日志:记录用户访问 API 的访问日志,定期归档历史日志。 + * 2. 异常日志:记录用户访问 API 的系统异常,方便日常排查问题与告警。 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.framework.apilog; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java new file mode 100644 index 0000000..f21d33c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.jackson.config; + +import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer; +import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer; +import cn.iocoder.yudao.framework.util.json.JsonUtils; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.LocalDateTime; + +@Configuration +public class YudaoJacksonAutoConfiguration { + + @Bean + @SuppressWarnings("InstantiationOfUtilityClass") + public JsonUtils jsonUtils(ObjectMapper objectMapper) { + SimpleModule simpleModule = new SimpleModule(); + /* + * 1. 新增Long类型序列化规则,数值超过2^53-1,在JS会出现精度丢失问题,因此Long自动序列化为字符串类型 + * 2. 新增LocalDateTime序列化、反序列化规则 + */ + simpleModule +// .addSerializer(Long.class, ToStringSerializer.instance) +// .addSerializer(Long.TYPE, ToStringSerializer.instance) + .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE) + .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE); + + objectMapper.registerModules(simpleModule); + + JsonUtils.init(objectMapper); + return new JsonUtils(); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java new file mode 100644 index 0000000..f4cb713 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeDeserializer.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.framework.jackson.core.databind; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; + +/** + * LocalDateTime反序列化规则 + *

+ * 会将毫秒级时间戳反序列化为LocalDateTime + */ +public class LocalDateTimeDeserializer extends JsonDeserializer { + + public static final LocalDateTimeDeserializer INSTANCE = new LocalDateTimeDeserializer(); + + @Override + public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault()); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeSerializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeSerializer.java new file mode 100644 index 0000000..286fb73 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalDateTimeSerializer.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.jackson.core.databind; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneId; + +/** + * LocalDateTime序列化规则 + *

+ * 会将LocalDateTime序列化为毫秒级时间戳 + */ +public class LocalDateTimeSerializer extends JsonSerializer { + + public static final LocalDateTimeSerializer INSTANCE = new LocalDateTimeSerializer(); + + @Override + public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/package-info.java new file mode 100644 index 0000000..261b508 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.jackson.core; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java new file mode 100644 index 0000000..8c69219 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java new file mode 100644 index 0000000..d1008ed --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.framework.swagger.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import javax.validation.constraints.NotEmpty; + +/** + * Swagger 配置属性 + * + * @author 芋道源码 + */ +@ConfigurationProperties("yudao.swagger") +@Data +public class SwaggerProperties { + + /** + * 标题 + */ + @NotEmpty(message = "标题不能为空") + private String title; + /** + * 描述 + */ + @NotEmpty(message = "描述不能为空") + private String description; + /** + * 作者 + */ + @NotEmpty(message = "作者不能为空") + private String author; + /** + * 版本 + */ + @NotEmpty(message = "版本不能为空") + private String version; + /** + * 扫描的包 + */ + @NotEmpty(message = "扫描的 package 不能为空") + private String basePackage; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java new file mode 100644 index 0000000..d1376fd --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.framework.swagger.config; + +import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.Contact; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.service.SecurityScheme; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.Collections; +import java.util.List; + +import static springfox.documentation.builders.RequestHandlerSelectors.basePackage; + +/** + * Swagger2 自动配置类 + * + * @author 芋道源码 + */ +@Configuration +@EnableSwagger2 +@EnableKnife4j +@ConditionalOnClass({Docket.class, ApiInfoBuilder.class}) +@ConditionalOnProperty(prefix = "yudao.swagger", value = "enable", matchIfMissing = true) +// 允许使用 swagger.enable=false 禁用 Swagger +@EnableConfigurationProperties(SwaggerProperties.class) +public class YudaoSwaggerAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public SwaggerProperties swaggerProperties() { + return new SwaggerProperties(); + } + + @Bean + public Docket createRestApi() { + SwaggerProperties properties = swaggerProperties(); + // 创建 Docket 对象 + return new Docket(DocumentationType.SWAGGER_2) + // 用来创建该 API 的基本信息,展示在文档的页面中(自定义展示的信息) + .apiInfo(apiInfo(properties)) + // 设置扫描指定 package 包下的 + .select() + .apis(basePackage(properties.getBasePackage())) + .paths(PathSelectors.any()) + .build() + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()); + } + + /** + * API 摘要信息 + */ + private static ApiInfo apiInfo(SwaggerProperties properties) { + return new ApiInfoBuilder() + .title(properties.getTitle()) + .description(properties.getDescription()) + .contact(new Contact(properties.getAuthor(), null, null)) + .version(properties.getVersion()) + .build(); + } + + /** + * 安全模式,这里配置通过请求头 Authorization 传递 token 参数 + */ + private static List securitySchemes() { + return Collections.singletonList(new ApiKey(HttpHeaders.AUTHORIZATION, "Authorization", "header")); + } + + /** + * 安全上下文 + * + * @see #securitySchemes() + * @see #authorizationScopes() + */ + private static List securityContexts() { + return Collections.singletonList(SecurityContext.builder() + .securityReferences(securityReferences()) + .forPaths(PathSelectors.regex("^(?!auth).*$")) + .build()); + } + + private static List securityReferences() { + return Collections.singletonList(new SecurityReference(HttpHeaders.AUTHORIZATION, authorizationScopes())); + } + + private static AuthorizationScope[] authorizationScopes() { + return new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")}; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/package-info.java new file mode 100644 index 0000000..5eb7822 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/package-info.java @@ -0,0 +1,6 @@ +/** + * 基于 Swagger + Knife4j 实现 API 接口文档 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.framework.swagger; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java new file mode 100644 index 0000000..d4444da --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.web.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; + +import javax.validation.constraints.NotNull; + +@ConfigurationProperties(prefix = "yudao.web") +@Validated +@Data +public class WebProperties { + + /** + * API 前缀,实现所有 Controller 提供的 RESTFul API 的统一前缀 + * + * + * 意义:通过该前缀,避免 Swagger、Actuator 意外通过 Nginx 暴露出来给外部,带来安全性问题 + * 这样,Nginx 只需要配置转发到 /api/* 的所有接口即可。 + * + * @see YudaoWebAutoConfiguration#configurePathMatch(PathMatchConfigurer) + */ + @NotNull(message = "API 前缀不能为空") + private String apiPrefix; + + /** + * Controller 所在包 + * + * 主要目的是,给该 Controller 设置指定的 {@link #apiPrefix} + * + * 因为我们有多个 modules 包里会包含 Controller,所以只需要写到 cn.iocoder.dashboard 这样的层级 + */ + @NotNull(message = "Controller 所在包不能为空") + private String controllerPackage; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java new file mode 100644 index 0000000..e4d1230 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.framework.web.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import java.util.Collections; +import java.util.List; + +/** + * Xss 配置属性 + * + * @author 芋道源码 + */ +@ConfigurationProperties(prefix = "yudao.xss") +@Validated +@Data +public class XssProperties { + + /** + * 是否开启,默认为 true + */ + private boolean enable = true; + /** + * 需要排除的 URL,默认为空 + */ + private List excludeUrls = Collections.emptyList(); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java new file mode 100644 index 0000000..90773f8 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.framework.web.config; + +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; +import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; +import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; +import cn.iocoder.yudao.framework.web.core.filter.XssFilter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.PathMatcher; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import javax.annotation.Resource; +import javax.servlet.Filter; + +@Configuration +@EnableConfigurationProperties({WebProperties.class, XssProperties.class}) +public class YudaoWebAutoConfiguration implements WebMvcConfigurer { + + @Resource + private WebProperties webProperties; + + @Override + public void configurePathMatch(PathMatchConfigurer configurer) { + // 设置 API 前缀,仅仅匹配 controller 包下的 + configurer.addPathPrefix(webProperties.getApiPrefix(), clazz -> + clazz.isAnnotationPresent(RestController.class) + && clazz.getPackage().getName().startsWith(webProperties.getControllerPackage())); // 仅仅匹配 controller 包 + } + + // ========== Filter 相关 ========== + + /** + * 创建 CorsFilter Bean,解决跨域问题 + */ + @Bean + public FilterRegistrationBean corsFilterBean() { + // 创建 CorsConfiguration 对象 + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + config.addAllowedOriginPattern("*"); // 设置访问源地址 + config.addAllowedHeader("*"); // 设置访问源请求头 + config.addAllowedMethod("*"); // 设置访问源请求方法 + // 创建 UrlBasedCorsConfigurationSource 对象 + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); // 对接口配置跨域设置 + return createFilterBean(new CorsFilter(source), WebFilterOrderEnum.CORS_FILTER); + } + + /** + * 创建 RequestBodyCacheFilter Bean,可重复读取请求内容 + */ + @Bean + public FilterRegistrationBean requestBodyCacheFilter() { + return createFilterBean(new CacheRequestBodyFilter(), WebFilterOrderEnum.REQUEST_BODY_CACHE_FILTER); + } + + /** + * 创建 XssFilter Bean,解决 Xss 安全问题 + */ + @Bean + public FilterRegistrationBean xssFilter(XssProperties properties, PathMatcher pathMatcher) { + return createFilterBean(new XssFilter(properties, pathMatcher), WebFilterOrderEnum.XSS_FILTER); + } + + /** + * 创建 DemoFilter Bean,演示模式 + */ + @Bean + @ConditionalOnProperty(value = "yudao.demo", havingValue = "true") + public FilterRegistrationBean demoFilter() { + return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER); + } + + private static FilterRegistrationBean createFilterBean(T filter, Integer order) { + FilterRegistrationBean bean = new FilterRegistrationBean<>(filter); + bean.setOrder(order); + return bean; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java new file mode 100644 index 0000000..31b8ba1 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.framework.web.core.filter; + +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +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; + +/** + * Request Body 缓存 Filter,实现它的可重复读取 + * + * @author 芋道源码 + */ +public class CacheRequestBodyFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws IOException, ServletException { + filterChain.doFilter(new CacheRequestBodyWrapper(request), response); + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + // 只处理 json 请求内容 + return !ServletUtils.isJsonRequest(request); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java new file mode 100644 index 0000000..f02ba5e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.framework.web.core.filter; + +import cn.hutool.extra.servlet.ServletUtil; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Request Body 缓存 Wrapper + * + * @author 芋道源码 + */ +public class CacheRequestBodyWrapper extends HttpServletRequestWrapper { + + /** + * 缓存的内容 + */ + private final byte[] body; + + public CacheRequestBodyWrapper(HttpServletRequest request) { + super(request); + body = ServletUtil.getBodyBytes(request); + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); + // 返回 ServletInputStream + return new ServletInputStream() { + + @Override + public int read() { + return inputStream.read(); + } + + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) {} + + }; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java new file mode 100644 index 0000000..2c2e3f0 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.web.core.filter; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.DEMO_DENY; + +/** + * 演示 Filter,禁止用户发起写操作,避免影响测试数据 + * + * @author 芋道源码 + */ +public class DemoFilter extends OncePerRequestFilter { + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + String method = request.getMethod(); + return !StrUtil.equalsAnyIgnoreCase(method, "POST", "PUT", "DELETE") // 写操作时,不进行过滤率 + || WebFrameworkUtils.getLoginUserId(request) == null; // 非登陆用户时,不进行过滤 + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { + // 直接返回 DEMO_DENY 的结果。即,请求不继续 + ServletUtils.writeJSON(response, CommonResult.error(DEMO_DENY)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java new file mode 100644 index 0000000..050a86c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.framework.web.core.filter; + +import cn.iocoder.yudao.framework.web.config.XssProperties; +import lombok.AllArgsConstructor; +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; + +/** + * Xss 过滤器 + * + * 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/ + * + * @author 芋道源码 + */ +@AllArgsConstructor +public class XssFilter extends OncePerRequestFilter { + + /** + * 属性 + */ + private final XssProperties properties; + /** + * 路径匹配器 + */ + private final PathMatcher pathMatcher; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws IOException, ServletException { + filterChain.doFilter(new XssRequestWrapper(request), response); + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + // 如果关闭,则不过滤 + if (!properties.isEnable()) { + return true; + } + + // 如果匹配到无需过滤,则不过滤 + String uri = request.getRequestURI(); + return properties.getExcludeUrls().stream().anyMatch(excludeUrl -> pathMatcher.match(excludeUrl, uri)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java new file mode 100644 index 0000000..991cad4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java @@ -0,0 +1,136 @@ +package cn.iocoder.yudao.framework.web.core.filter; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HTMLFilter; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Map; + +/** + * Xss 请求 Wrapper + * + * @author 芋道源码 + */ +public class XssRequestWrapper extends HttpServletRequestWrapper { + + /** + * 基于线程级别的 HTMLFilter 对象,因为它线程非安全 + */ + private static final ThreadLocal HTML_FILTER = ThreadLocal.withInitial(() -> { + HTMLFilter htmlFilter = new HTMLFilter(); + // 反射修改 encodeQuotes 属性为 false,避免 " 被转移成 " 字符 + ReflectUtil.setFieldValue(htmlFilter, "encodeQuotes", false); + return htmlFilter; + }); + + public XssRequestWrapper(HttpServletRequest request) { + super(request); + } + + private static String filterXss(String content) { + if (StrUtil.isEmpty(content)) { + return content; + } + return HTML_FILTER.get().filter(content); + } + + // ========== IO 流相关 ========== + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // 如果非 json 请求,不进行 Xss 处理 + if (!ServletUtils.isJsonRequest(this)) { + return super.getInputStream(); + } + + // 读取内容,并过滤 + String content = IoUtil.readUtf8(super.getInputStream()); + content = filterXss(content); + final ByteArrayInputStream newInputStream = new ByteArrayInputStream(content.getBytes()); + // 返回 ServletInputStream + return new ServletInputStream() { + + @Override + public int read() { + return newInputStream.read(); + } + + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) {} + + }; + } + + // ========== Param 相关 ========== + + @Override + public String getParameter(String name) { + String value = super.getParameter(name); + return filterXss(value); + } + + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (ArrayUtil.isEmpty(values)) { + return values; + } + // 过滤处理 + for (int i = 0; i < values.length; i++) { + values[i] = filterXss(values[i]); + } + return values; + } + + @Override + public Map getParameterMap() { + Map valueMap = super.getParameterMap(); + if (CollUtil.isEmpty(valueMap)) { + return valueMap; + } + // 过滤处理 + for (Map.Entry entry : valueMap.entrySet()) { + String[] values = entry.getValue(); + for (int i = 0; i < values.length; i++) { + values[i] = filterXss(values[i]); + } + } + return valueMap; + } + + // ========== Header 相关 ========== + + @Override + public String getHeader(String name) { + String value = super.getHeader(name); + return filterXss(value); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..ca15c40 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -0,0 +1,275 @@ +package cn.iocoder.yudao.framework.web.core.handler; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO; +import cn.iocoder.yudao.framework.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.framework.util.json.JsonUtils; +import cn.iocoder.yudao.framework.util.servlet.ServletUtils; +import io.github.resilience4j.ratelimiter.RequestNotPermitted; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.util.Assert; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +import org.springframework.web.servlet.NoHandlerFoundException; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.ValidationException; +import java.util.Date; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*; + +/** + * 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号 + * + * @author 芋道源码 + */ +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + @Value("${spring.application.name}") + private String applicationName; + + @Resource + private ApiErrorLogFrameworkService apiErrorLogFrameworkService; + + /** + * 处理所有异常,主要是提供给 Filter 使用 + * 因为 Filter 不走 SpringMVC 的流程,但是我们又需要兜底处理异常,所以这里提供一个全量的异常处理过程,保持逻辑统一。 + * + * @param request 请求 + * @param ex 异常 + * @return 通用返回 + */ + public CommonResult allExceptionHandler(HttpServletRequest request, Throwable ex) { + if (ex instanceof MissingServletRequestParameterException) { + return missingServletRequestParameterExceptionHandler((MissingServletRequestParameterException) ex); + } + if (ex instanceof MethodArgumentTypeMismatchException) { + return methodArgumentTypeMismatchExceptionHandler((MethodArgumentTypeMismatchException) ex); + } + if (ex instanceof MethodArgumentNotValidException) { + return methodArgumentNotValidExceptionExceptionHandler((MethodArgumentNotValidException) ex); + } + if (ex instanceof BindException) { + return bindExceptionHandler((BindException) ex); + } + if (ex instanceof ConstraintViolationException) { + return constraintViolationExceptionHandler((ConstraintViolationException) ex); + } + if (ex instanceof ValidationException) { + return validationException((ValidationException) ex); + } + if (ex instanceof NoHandlerFoundException) { + return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex); + } + if (ex instanceof HttpRequestMethodNotSupportedException) { + return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); + } + if (ex instanceof RequestNotPermitted) { + return requestNotPermittedExceptionHandler(request, (RequestNotPermitted) ex); + } + if (ex instanceof ServiceException) { + return serviceExceptionHandler((ServiceException) ex); + } + if (ex instanceof AccessDeniedException) { + return accessDeniedExceptionHandler(request, (AccessDeniedException) ex); + } + return defaultExceptionHandler(request, ex); + } + + /** + * 处理 SpringMVC 请求参数缺失 + * + * 例如说,接口上设置了 @RequestParam("xx") 参数,结果并未传递 xx 参数 + */ + @ExceptionHandler(value = MissingServletRequestParameterException.class) + public CommonResult missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException ex) { + log.warn("[missingServletRequestParameterExceptionHandler]", ex); + return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数缺失:%s", ex.getParameterName())); + } + + /** + * 处理 SpringMVC 请求参数类型错误 + * + * 例如说,接口上设置了 @RequestParam("xx") 参数为 Integer,结果传递 xx 参数类型为 String + */ + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + public CommonResult methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException ex) { + log.warn("[missingServletRequestParameterExceptionHandler]", ex); + return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", ex.getMessage())); + } + + /** + * 处理 SpringMVC 参数校验不正确 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public CommonResult methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException ex) { + log.warn("[methodArgumentNotValidExceptionExceptionHandler]", ex); + FieldError fieldError = ex.getBindingResult().getFieldError(); + assert fieldError != null; // 断言,避免告警 + return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage())); + } + + /** + * 处理 SpringMVC 参数绑定不正确,本质上也是通过 Validator 校验 + */ + @ExceptionHandler(BindException.class) + public CommonResult bindExceptionHandler(BindException ex) { + log.warn("[handleBindException]", ex); + FieldError fieldError = ex.getFieldError(); + assert fieldError != null; // 断言,避免告警 + return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage())); + } + + /** + * 处理 Validator 校验不通过产生的异常 + */ + @ExceptionHandler(value = ConstraintViolationException.class) + public CommonResult constraintViolationExceptionHandler(ConstraintViolationException ex) { + log.warn("[constraintViolationExceptionHandler]", ex); + ConstraintViolation constraintViolation = ex.getConstraintViolations().iterator().next(); + return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", constraintViolation.getMessage())); + } + + /** + * 处理 Dubbo Consumer 本地参数校验时,抛出的 ValidationException 异常 + */ + @ExceptionHandler(value = ValidationException.class) + public CommonResult validationException(ValidationException ex) { + log.warn("[constraintViolationExceptionHandler]", ex); + // 无法拼接明细的错误信息,因为 Dubbo Consumer 抛出 ValidationException 异常时,是直接的字符串信息,且人类不可读 + return CommonResult.error(BAD_REQUEST); + } + + /** + * 处理 SpringMVC 请求地址不存在 + * + * 注意,它需要设置如下两个配置项: + * 1. spring.mvc.throw-exception-if-no-handler-found 为 true + * 2. spring.mvc.static-path-pattern 为 /statics/** + */ + @ExceptionHandler(NoHandlerFoundException.class) + public CommonResult noHandlerFoundExceptionHandler(NoHandlerFoundException ex) { + log.warn("[noHandlerFoundExceptionHandler]", ex); + return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL())); + } + + /** + * 处理 SpringMVC 请求方法不正确 + * + * 例如说,A 接口的方法为 GET 方式,结果请求方法为 POST 方式,导致不匹配 + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public CommonResult httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) { + log.warn("[httpRequestMethodNotSupportedExceptionHandler]", ex); + return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage())); + } + + /** + * 处理 Resilience4j 限流抛出的异常 + */ + @ExceptionHandler(value = RequestNotPermitted.class) + public CommonResult requestNotPermittedExceptionHandler(HttpServletRequest req, RequestNotPermitted ex) { + log.warn("[requestNotPermittedExceptionHandler][url({}) 访问过于频繁]", req.getRequestURL(), ex); + return CommonResult.error(TOO_MANY_REQUESTS); + } + + /** + * 处理 Spring Security 权限不足的异常 + * + * 来源是,使用 @PreAuthorize 注解,AOP 进行权限拦截 + */ + @ExceptionHandler(value = AccessDeniedException.class) + public CommonResult accessDeniedExceptionHandler(HttpServletRequest req, AccessDeniedException ex) { + log.warn("[accessDeniedExceptionHandler][userId({}) 无法访问 url({})]", WebFrameworkUtils.getLoginUserId(req), + req.getRequestURL(), ex); + return CommonResult.error(FORBIDDEN); + } + + /** + * 处理业务异常 ServiceException + * + * 例如说,商品库存不足,用户手机号已存在。 + */ + @ExceptionHandler(value = ServiceException.class) + public CommonResult serviceExceptionHandler(ServiceException ex) { + log.info("[serviceExceptionHandler]", ex); + return CommonResult.error(ex.getCode(), ex.getMessage()); + } + + /** + * 处理系统异常,兜底处理所有的一切 + */ + @ExceptionHandler(value = Exception.class) + public CommonResult defaultExceptionHandler(HttpServletRequest req, Throwable ex) { + log.error("[defaultExceptionHandler]", ex); + // 插入异常日志 + this.createExceptionLog(req, ex); + // 返回 ERROR CommonResult + return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); + } + + private void createExceptionLog(HttpServletRequest req, Throwable e) { + // 插入错误日志 + ApiErrorLogCreateDTO errorLog = new ApiErrorLogCreateDTO(); + try { + // 初始化 errorLog + initExceptionLog(errorLog, req, e); + // 执行插入 errorLog + apiErrorLogFrameworkService.createApiErrorLogAsync(errorLog); + } catch (Throwable th) { + log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(), JsonUtils.toJsonString(errorLog), th); + } + } + + private void initExceptionLog(ApiErrorLogCreateDTO errorLog, HttpServletRequest request, Throwable e) { + // 处理用户信息 + errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request)); + errorLog.setUserType(WebFrameworkUtils.getUserType(request)); + // 设置异常字段 + errorLog.setExceptionName(e.getClass().getName()); + errorLog.setExceptionMessage(ExceptionUtil.getMessage(e)); + errorLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e)); + errorLog.setExceptionStackTrace(ExceptionUtils.getStackTrace(e)); + StackTraceElement[] stackTraceElements = e.getStackTrace(); + Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空"); + StackTraceElement stackTraceElement = stackTraceElements[0]; + errorLog.setExceptionClassName(stackTraceElement.getClassName()); + errorLog.setExceptionFileName(stackTraceElement.getFileName()); + errorLog.setExceptionMethodName(stackTraceElement.getMethodName()); + errorLog.setExceptionLineNumber(stackTraceElement.getLineNumber()); + // 设置其它字段 + errorLog.setTraceId(TracerUtils.getTraceId()); + errorLog.setApplicationName(applicationName); + errorLog.setRequestUrl(request.getRequestURI()); + Map requestParams = MapUtil.builder() + .put("query", ServletUtil.getParamMap(request)) + .put("body", ServletUtil.getBody(request)).build(); + errorLog.setRequestParams(JsonUtils.toJsonString(requestParams)); + errorLog.setRequestMethod(request.getMethod()); + errorLog.setUserAgent(ServletUtils.getUserAgent(request)); + errorLog.setUserIp(ServletUtil.getClientIP(request)); + errorLog.setExceptionTime(new Date()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalResponseBodyHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalResponseBodyHandler.java new file mode 100644 index 0000000..90da742 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalResponseBodyHandler.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.framework.web.core.handler; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.http.server.ServletServerHttpRequest; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +/** + * 全局响应结果(ResponseBody)处理器 + * + * 不同于在网上看到的很多文章,会选择自动将 Controller 返回结果包上 {@link CommonResult}, + * 在 onemall 中,是 Controller 在返回时,主动自己包上 {@link CommonResult}。 + * 原因是,GlobalResponseBodyHandler 本质上是 AOP,它不应该改变 Controller 返回的数据结构 + * + * 目前,GlobalResponseBodyHandler 的主要作用是,记录 Controller 的返回结果, + * 方便 {@link cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter} 记录访问日志 + */ +@ControllerAdvice +public class GlobalResponseBodyHandler implements ResponseBodyAdvice { + + @Override + @SuppressWarnings("NullableProblems") // 避免 IDEA 警告 + public boolean supports(MethodParameter returnType, Class converterType) { + if (returnType.getMethod() == null) { + return false; + } + // 只拦截返回结果为 CommonResult 类型 + return returnType.getMethod().getReturnType() == CommonResult.class; + } + + @Override + @SuppressWarnings("NullableProblems") // 避免 IDEA 警告 + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, + ServerHttpRequest request, ServerHttpResponse response) { + // 记录 Controller 结果 + WebFrameworkUtils.setCommonResult(((ServletServerHttpRequest) request).getServletRequest(), (CommonResult) body); + return body; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java new file mode 100644 index 0000000..2bf5c2f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.framework.web.core.util; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; + +/** + * 专属于 web 包的工具类 + * + * @author 芋道源码 + */ +public class WebFrameworkUtils { + + private static final String REQUEST_ATTRIBUTE_LOGIN_USER_ID = "login_user_id"; + + private static final String REQUEST_ATTRIBUTE_COMMON_RESULT = "common_result"; + + public static void setLoginUserId(ServletRequest request, Long userId) { + request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID, userId); + } + + /** + * 获得当前用户的编号,从请求中 + * + * @param request 请求 + * @return 用户编号 + */ + public static Long getLoginUserId(HttpServletRequest request) { + if (request == null) { + return null; + } + return (Long) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID); + } + + public static Long getLoginUserId() { + HttpServletRequest request = getRequest(); + return getLoginUserId(request); + } + + public static Integer getUserType(HttpServletRequest request) { + return UserTypeEnum.ADMIN.getValue(); // TODO 芋艿:等后续优化 + } + + public static void setCommonResult(ServletRequest request, CommonResult result) { + request.setAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT, result); + } + + public static CommonResult getCommonResult(ServletRequest request) { + return (CommonResult) request.getAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT); + } + + private static HttpServletRequest getRequest() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + if (!(requestAttributes instanceof ServletRequestAttributes)) { + return null; + } + ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes; + return servletRequestAttributes.getRequest(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/package-info.java new file mode 100644 index 0000000..43b70eb --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/package-info.java @@ -0,0 +1,4 @@ +/** + * 针对 SpringMVC 的基础封装 + */ +package cn.iocoder.yudao.framework.web; diff --git a/yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot API 接口文档 Swagger 入门》.md b/yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot API 接口文档 Swagger 入门》.md new file mode 100644 index 0000000..7ed5ebd --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot API 接口文档 Swagger 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot SpringMVC 入门》.md b/yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot SpringMVC 入门》.md new file mode 100644 index 0000000..7c36a15 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/《芋道 Spring Boot SpringMVC 入门》.md @@ -0,0 +1 @@ + -- libgit2 0.21.4