From 17ddb8750e09d8138916823ddcb7f327c535ccc0 Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Thu, 16 May 2024 08:36:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E4=BF=AE=E6=94=B9):=20:rocket:=20?= =?UTF-8?q?=E4=B8=8D=E6=8E=A8=E9=80=81logs=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- common/common-generator/pom.xml | 75 ++++++++++++ .../cn/bunny/common/generator/NewCodeGet.java | 84 +++++++++++++ .../cn/bunny/common/generator/OldCodeGet.java | 57 +++++++++ .../constant/CommonMessageConstant.java | 41 +++++++ .../result/constant/ExceptionConstant.java | 16 +++ .../constant/LocalDateTimeConstant.java | 11 ++ .../result/constant/MailMessageConstant.java | 14 +++ .../result/constant/MinioMessageConstant.java | 19 +++ .../result/constant/PasswordConstant.java | 18 +++ .../result/constant/RedisUserConstant.java | 11 ++ .../result/constant/SQLAutoFillConstant.java | 14 +++ .../result/constant/SecurityConstant.java | 12 ++ .../result/constant/StatusConstant.java | 14 +++ .../common/result/constant/UserConstant.java | 8 ++ .../properties/SnowflakeProperties.java | 25 ++++ .../src/main/java/cn/bunny/dto/LoginDto.java | 16 +++ .../java/cn/bunny/entity/system/User.java | 68 +++++++++++ .../entity/system/UserIntegralRecord.java | 46 +++++++ .../java/cn/bunny/entity/system/UserRole.java | 47 ++++++++ .../cn/bunny/vo/system/ValidateCodeVo.java | 20 +++ module/spring-security/pom.xml | 37 ++++++ .../security/config/WebSecurityConfig.java | 86 +++++++++++++ .../custom/CustomPasswordEncoder.java | 28 +++++ .../cn/bunny/security/custom/CustomUser.java | 22 ++++ .../filter/TokenAuthenticationFilter.java | 74 ++++++++++++ .../filter/TokenLoginFilterService.java | 84 +++++++++++++ .../handelr/SecurityAccessDeniedHandler.java | 26 ++++ .../SecurityAuthenticationEntryPoint.java | 39 ++++++ .../SecurityAuthenticationFailureHandler.java | 26 ++++ .../SecurityAuthenticationSuccessHandler.java | 26 ++++ .../CustomAuthorizationManagerService.java | 7 ++ .../service/CustomUserDetailsService.java | 23 ++++ .../service/gateway/task/TemplateTask.java | 14 +++ service/service-admin/Dockerfile | 21 ++++ service/service-admin/pom.xml | 101 ++++++++++++++++ .../admin/ServiceAdminApplication.java | 22 ++++ .../src/main/resources/application-dev.yml | 19 +++ .../src/main/resources/application.yml | 63 ++++++++++ .../src/main/resources/banner.txt | 16 +++ .../src/main/resources/favicon.ico | Bin 0 -> 17014 bytes .../src/main/resources/logback.xml | 61 ++++++++++ service/service-web/Dockerfile | 21 ++++ service/service-web/pom.xml | 114 ++++++++++++++++++ .../service/web/ServiceWebApplication.java | 20 +++ .../service/web/aop/annotation/AutoFill.java | 15 +++ .../web/aop/aspect/AutoFillAspect.java | 27 +++++ .../web/controller/LoginController.java | 33 +++++ .../web/controller/UserController.java | 18 +++ .../UserIntegralRecordController.java | 18 +++ .../web/controller/UserRoleController.java | 18 +++ .../web/mapper/UserIntegralRecordMapper.java | 18 +++ .../bunny/service/web/mapper/UserMapper.java | 27 +++++ .../service/web/mapper/UserRoleMapper.java | 18 +++ ...CustomAuthorizationManagerServiceImpl.java | 36 ++++++ .../security/CustomUserDetailsService.java | 58 +++++++++ .../service/web/service/LoginService.java | 24 ++++ .../service/UserIntegralRecordService.java | 16 +++ .../service/web/service/UserRoleService.java | 16 +++ .../service/web/service/UserService.java | 16 +++ .../web/service/impl/LoginServiceImpl.java | 69 +++++++++++ .../impl/UserIntegralRecordServiceImpl.java | 20 +++ .../web/service/impl/UserRoleServiceImpl.java | 20 +++ .../web/service/impl/UserServiceImpl.java | 20 +++ .../src/main/resources/application-dev.yml | 24 ++++ .../src/main/resources/application.yml | 71 +++++++++++ .../service-web/src/main/resources/banner.txt | 16 +++ .../src/main/resources/favicon.ico | Bin 0 -> 17014 bytes .../src/main/resources/logback.xml | 61 ++++++++++ .../mapper/UserIntegralRecordMapper.xml | 19 +++ .../src/main/resources/mapper/UserMapper.xml | 19 +++ .../main/resources/mapper/UserRoleMapper.xml | 21 ++++ 72 files changed, 2287 insertions(+), 2 deletions(-) create mode 100644 common/common-generator/pom.xml create mode 100644 common/common-generator/src/main/java/cn/bunny/common/generator/NewCodeGet.java create mode 100644 common/common-generator/src/main/java/cn/bunny/common/generator/OldCodeGet.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/CommonMessageConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/ExceptionConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/LocalDateTimeConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/MailMessageConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/MinioMessageConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/PasswordConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/RedisUserConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/SQLAutoFillConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/SecurityConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/StatusConstant.java create mode 100644 common/common-result/src/main/java/cn/bunny/common/result/constant/UserConstant.java create mode 100644 common/service-utils/src/main/java/cn/bunny/common/service/properties/SnowflakeProperties.java create mode 100644 model/src/main/java/cn/bunny/dto/LoginDto.java create mode 100644 model/src/main/java/cn/bunny/entity/system/User.java create mode 100644 model/src/main/java/cn/bunny/entity/system/UserIntegralRecord.java create mode 100644 model/src/main/java/cn/bunny/entity/system/UserRole.java create mode 100644 model/src/main/java/cn/bunny/vo/system/ValidateCodeVo.java create mode 100644 module/spring-security/pom.xml create mode 100644 module/spring-security/src/main/java/cn/bunny/security/config/WebSecurityConfig.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/custom/CustomPasswordEncoder.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/custom/CustomUser.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/filter/TokenAuthenticationFilter.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/filter/TokenLoginFilterService.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAccessDeniedHandler.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationEntryPoint.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationFailureHandler.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationSuccessHandler.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/service/CustomAuthorizationManagerService.java create mode 100644 module/spring-security/src/main/java/cn/bunny/security/service/CustomUserDetailsService.java create mode 100644 server-gateway/src/main/java/cn/bunny/service/gateway/task/TemplateTask.java create mode 100644 service/service-admin/Dockerfile create mode 100644 service/service-admin/pom.xml create mode 100644 service/service-admin/src/main/java/cn/bunny/service/admin/ServiceAdminApplication.java create mode 100644 service/service-admin/src/main/resources/application-dev.yml create mode 100644 service/service-admin/src/main/resources/application.yml create mode 100644 service/service-admin/src/main/resources/banner.txt create mode 100644 service/service-admin/src/main/resources/favicon.ico create mode 100644 service/service-admin/src/main/resources/logback.xml create mode 100644 service/service-web/Dockerfile create mode 100644 service/service-web/pom.xml create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/ServiceWebApplication.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/aop/annotation/AutoFill.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoFillAspect.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/controller/LoginController.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/controller/UserController.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/controller/UserIntegralRecordController.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/controller/UserRoleController.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/mapper/UserIntegralRecordMapper.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/mapper/UserMapper.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/mapper/UserRoleMapper.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/security/CustomAuthorizationManagerServiceImpl.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/security/CustomUserDetailsService.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/service/LoginService.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/service/UserIntegralRecordService.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/service/UserRoleService.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/service/UserService.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/service/impl/LoginServiceImpl.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserIntegralRecordServiceImpl.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserRoleServiceImpl.java create mode 100644 service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserServiceImpl.java create mode 100644 service/service-web/src/main/resources/application-dev.yml create mode 100644 service/service-web/src/main/resources/application.yml create mode 100644 service/service-web/src/main/resources/banner.txt create mode 100644 service/service-web/src/main/resources/favicon.ico create mode 100644 service/service-web/src/main/resources/logback.xml create mode 100644 service/service-web/src/main/resources/mapper/UserIntegralRecordMapper.xml create mode 100644 service/service-web/src/main/resources/mapper/UserMapper.xml create mode 100644 service/service-web/src/main/resources/mapper/UserRoleMapper.xml diff --git a/.gitignore b/.gitignore index a23d6d0..17710db 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,8 @@ target/ *.iws *.iml *.ipr +logs +logs/** ### NetBeans ### /nbproject/private/ @@ -30,5 +32,4 @@ build/ !**/src/test/**/build/ ### VS Code ### -.vscode/ -logs \ No newline at end of file +.vscode/ \ No newline at end of file diff --git a/common/common-generator/pom.xml b/common/common-generator/pom.xml new file mode 100644 index 0000000..a08a8a6 --- /dev/null +++ b/common/common-generator/pom.xml @@ -0,0 +1,75 @@ + + 4.0.0 + + cn.bunny + common + 0.0.1-SNAPSHOT + + + common-generator + jar + + common-utils + https://maven.apache.org + + + UTF-8 + + + + + org.projectlombok + lombok + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + javax.xml.bind + jaxb-api + 2.1 + + + + mysql + mysql-connector-java + + + + com.zaxxer + HikariCP + 5.1.0 + + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + + com.baomidou + mybatis-plus-generator + 3.5.6 + + + org.apache.velocity + velocity-engine-core + 2.3 + + + + + + + + + + + + + + + diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/NewCodeGet.java b/common/common-generator/src/main/java/cn/bunny/common/generator/NewCodeGet.java new file mode 100644 index 0000000..5ec7256 --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/NewCodeGet.java @@ -0,0 +1,84 @@ +package cn.bunny.common.generator; + + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.generator.FastAutoGenerator; +import com.baomidou.mybatisplus.generator.config.OutputFile; +import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collections; + +public class NewCodeGet { + // 数据连接 + public static final String sqlHost = "jdbc:mysql://106.15.251.123:3305/bunny_docs?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true"; + // 作者名称 + public static final String author = "Bunny"; + // 公共路径 + public static final String outputDir = "F:\\web项目\\PC\\BunnyNote\\bunny-server\\service\\service-admin"; + // 实体类名称 + public static final String entity = "Bunny"; + + public static void main(String[] args) { + Generation("email_users"); + } + + /** + * 根据表名生成相应结构代码 + * + * @param tableName 表名 + */ + public static void Generation(String... tableName) { + // TODO 修改数据库路径、账户、密码 + FastAutoGenerator.create(sqlHost, "root", "02120212") + .globalConfig(builder -> { + // 添加作者名称 + builder.author(author) + // 启用swagger + .enableSwagger() + // 指定输出目录 + .outputDir(outputDir + "/src/main/java"); + }) + .packageConfig(builder -> { + builder.entity(entity)// 实体类包名 + // TODO 父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名 + .parent("cn.bunny.service.admin") + .controller("controller")// 控制层包名 + .mapper("mapper")// mapper层包名 + .service("service")// service层包名 + .serviceImpl("service.impl")// service实现类包名 + // 自定义mapper.xml文件输出目录 + .pathInfo(Collections.singletonMap(OutputFile.xml, outputDir + "/src/main/resources/mapper")); + }) + .strategyConfig(builder -> { + // 设置要生成的表名 + builder.addInclude(tableName) + //.addTablePrefix("sys_")// TODO 设置表前缀过滤 + .entityBuilder() + .enableLombok() + .enableChainModel() + .naming(NamingStrategy.underline_to_camel)// 数据表映射实体命名策略:默认下划线转驼峰underline_to_camel + .columnNaming(NamingStrategy.underline_to_camel)// 表字段映射实体属性命名规则:默认null,不指定按照naming执行 + .idType(IdType.AUTO)// TODO 添加全局主键类型 + .formatFileName("%s")// 格式化实体名称,%s取消首字母I, + .mapperBuilder() + .mapperAnnotation(Mapper.class)// 开启mapper注解 + .enableBaseResultMap()// 启用xml文件中的BaseResultMap 生成 + .enableBaseColumnList()// 启用xml文件中的BaseColumnList + .formatMapperFileName("%sMapper")// 格式化Dao类名称 + .formatXmlFileName("%sMapper")// 格式化xml文件名称 + .serviceBuilder() + .formatServiceFileName("%sService")// 格式化 service 接口文件名称 + .formatServiceImplFileName("%sServiceImpl")// 格式化 service 接口文件名称 + .controllerBuilder() + .enableRestStyle(); + }) + // .injectionConfig(consumer -> { + // Map customFile = new HashMap<>(); + // // 配置DTO(需要的话)但是需要有能配置Dto的模板引擎,比如freemarker,但是这里我们用的VelocityEngine,因此不多作介绍 + // customFile.put(outputDir, "/src/main/resources/templates/entityDTO.java.ftl"); + // consumer.customFile(customFile); + // }) + .execute(); + } +} diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/OldCodeGet.java b/common/common-generator/src/main/java/cn/bunny/common/generator/OldCodeGet.java new file mode 100644 index 0000000..d43819c --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/OldCodeGet.java @@ -0,0 +1,57 @@ +package cn.bunny.common.generator; + +public class OldCodeGet { + public static void main(String[] args) { + // // 1、创建代码生成器 + // AutoGenerator mpg = new AutoGenerator(); + // + // // 2、全局配置 + // // 全局配置 + // GlobalConfig gc = new GlobalConfig(); + // // TODO 需要修改路径名称 + // gc.setOutputDir("F:\\web项目\\Bunny-Cli\\Java\\java-template\\service" + "/src/main/java"); + // gc.setServiceName("%sService"); // 去掉Service接口的首字母I + // gc.setAuthor("bunny"); + // gc.setOpen(false); + // mpg.setGlobalConfig(gc); + // + // // 3、数据源配置 + // DataSourceConfig dsc = new DataSourceConfig(); + // // TODO 需要修改数据库 + // dsc.setUrl("jdbc:mysql://106.15.251.123:3305/guigu-oa?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true"); + // dsc.setDriverName("com.mysql.cj.jdbc.Driver"); + // dsc.setUsername("root"); + // dsc.setPassword("02120212"); + // dsc.setDbType(DbType.MYSQL); + // mpg.setDataSource(dsc); + // + // // 4、包配置 + // PackageConfig pc = new PackageConfig(); + // pc.setParent("cn.bunny"); + // // TODO 需要修改模块名 + // pc.setModuleName("service"); + // pc.setController("controller"); + // pc.setService("service"); + // pc.setMapper("mapper"); + // mpg.setPackageInfo(pc); + // + // // 5、策略配置 + // StrategyConfig strategy = getStrategyConfig(); + // mpg.setStrategy(strategy); + // + // // 6、执行 + // mpg.execute(); + // } + // + // private static StrategyConfig getStrategyConfig() { + // StrategyConfig strategy = new StrategyConfig(); + // // TODO 要生成的表 + // strategy.setInclude("sys_menu", "sys_role_menu"); + // strategy.setNaming(NamingStrategy.underline_to_camel);// 数据库表映射到实体的命名策略 + // strategy.setColumnNaming(NamingStrategy.underline_to_camel);// 数据库表字段映射到实体的命名策略 + // strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作 + // strategy.setRestControllerStyle(true); // restful api风格控制器 + // strategy.setControllerMappingHyphenStyle(true); // url中驼峰转连字符 + // return strategy; + } +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/CommonMessageConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/CommonMessageConstant.java new file mode 100644 index 0000000..9f1a1be --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/CommonMessageConstant.java @@ -0,0 +1,41 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +/** + * 信息提示常量类 + */ +@Data +public class CommonMessageConstant { + public static final String PASSWORD_ERROR = "密码错误"; + public static final String OLD_PASSWORD_ERROR = "旧密码不匹配"; + public static final String OLD_PASSWORD_SAME_NEW_PASSWORD = "旧密码与新密码相同"; + public static final String ACCOUNT_NOT_FOUND = "账号不存在"; + public static final String ACCOUNT_LOCKED = "账号被锁定"; + public static final String UNKNOWN_ERROR = "未知错误"; + public static final String USER_NOT_LOGIN = "用户未登录"; + public static final String USER_TOKEN_OUT_OF_DATE = "用户登录过期"; + public static final String LOGIN_FAILED = "登录失败"; + public static final String UPLOAD_FAILED = "文件上传失败"; + public static final String PASSWORD_EDIT_FAILED = "密码修改失败"; + public static final String ALREADY_EXISTS = "已存在"; + public static final String REQUEST_NOT_EMPTY = "请求不为空"; + public static final String UPDATE_ID_IS_NOT_EMPTY = "删除id不能为空"; + public static final String DELETE_ID_IS_NOT_EMPTY = "修改id不能为空"; + public static final String MENU_IS_NOT_EXIST = "菜单不存在"; + public static final String SAVE_DTO_IS_NULL = "添加参数不能为空"; + public static final String UPDATE_DTO_IS_NULL = "修改参数不能为空"; + public static final String FIND_ID_IS_NOT_EMPTY = "查询ID不能为空"; + public static final String MESSAGE_CODE_NOT_PASS = "短信验证码未过期"; + public static final String MESSAGE_CODE_UNAUTHORIZED = "短信验证码未授权,请联系管理员"; + public static final String VERIFICATION_CODE_ERROR = "验证码错误"; + public static final String USER_DOES_NOT_EXIST = "用户不存在"; + public static final String USER_DOES_IS_EXIST = "用户已存在"; + public static final String VERIFICATION_CODE_IS_EMPTY = "请先发送验证码"; + public static final String LOGIN_DTO_IS_EMPTY = "登录参数不能为空"; + public static final String TOKEN_IS_EMPTY = "token为空"; + public static final String DATA_IS_EMPTY = "数据为空"; + public static final String USERNAME_NOT_EMPTY = "用户名不能为空"; + public static final String PASSWORD_NOT_EMPTY = "密码不能为空"; + public static final String SERVER_ERROR = "密码不能为空"; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/ExceptionConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/ExceptionConstant.java new file mode 100644 index 0000000..7a8c533 --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/ExceptionConstant.java @@ -0,0 +1,16 @@ +package cn.bunny.common.result.constant; + + +import lombok.Data; + +@Data +public class ExceptionConstant { + public static final String USER_NOT_FOUND = "用户不存在"; + public static final String USERNAME_IS_EMPTY = "用户名不能为空"; + public static final String PASSWORD_ERROR = "密码错误"; + public static final String PASSWORD_IS_EMPTY = "密码不能为空"; + public static final String CAPTCHA_IS_EMPTY = "提交验证码不能为空"; + public static final String KEY_IS_EMPTY = "验证码key不能为空"; + public static final String VERIFICATION_CODE_DOES_NOT_MATCH = "验证码不匹配"; + public static final String VERIFICATION_CODE_IS_EMPTY = "验证码失效或不存在"; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/LocalDateTimeConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/LocalDateTimeConstant.java new file mode 100644 index 0000000..ee3c13e --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/LocalDateTimeConstant.java @@ -0,0 +1,11 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +@Data +public class LocalDateTimeConstant { + public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; + public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm"; + public static final String DEFAULT_DATE_TIME_SECOND_FORMAT = "yyyy-MM-dd HH:mm:ss"; + public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss"; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/MailMessageConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/MailMessageConstant.java new file mode 100644 index 0000000..202d7ba --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/MailMessageConstant.java @@ -0,0 +1,14 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +/** + * 邮箱消息 + */ +@Data +public class MailMessageConstant { + public static final String EMPTY_SEND_OBJECT = "空发送对象"; + public static final String ADDRESS_NOT_NULL = "收件人不能为空"; + public static final String TITLE_NOT_NULL = "标题不能为空"; + public static final String SEND_MESSAGE_NOT_NULL = "发送消息不能为空"; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/MinioMessageConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/MinioMessageConstant.java new file mode 100644 index 0000000..f2aee77 --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/MinioMessageConstant.java @@ -0,0 +1,19 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +@Data +public class MinioMessageConstant { + public static final String BUCKET_EXISTS_EXCEPTION = "查询文化部对象失败"; + public static final String DELETE_BUCKET_EXCEPTION = "删除文件对象失败"; + public static final String GET_BUCKET_EXCEPTION = "获取文件信息失败"; + public static final String QUERY_BUCKET_EXCEPTION = "查询文件信息失败"; + public static final String CREATE_BUCKET_EXCEPTION = "创建文件对象失败"; + public static final String UPDATE_BUCKET_EXCEPTION = "更新文件对象失败"; + public static final String COMPOSE_OBJECT_EXCEPTION = "对象错误"; + public static final String COPY_BUCKET_EXCEPTION = "复制文件内容失败"; + public static final String DISABLE_BUCKET_EXCEPTION = "禁用文件失败"; + public static final String ENABLE_BUCKET_EXCEPTION = "启用文件失败"; + public static final String DOWNLOAD_BUCKET_EXCEPTION = "下载文件失败"; + public static final String UPLOAD_BUCKET_EXCEPTION = "上传文件失败"; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/PasswordConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/PasswordConstant.java new file mode 100644 index 0000000..86109f3 --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/PasswordConstant.java @@ -0,0 +1,18 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +/** + * 密码常量 + */ +@Data +public class PasswordConstant { + // 默认密码 + public static final String DEFAULT_PASSWORD = "123456"; + // JWT密码 + public static final String DEFAULT_JWT_PASSWORD = "123456"; + // 默认头像 + public static final String AVTAR = "https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg"; + // 设置token过期时间 + public static final long TOKEN_EXPIRATION = 365L * 24 * 60 * 60 * 1000; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/RedisUserConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/RedisUserConstant.java new file mode 100644 index 0000000..b2e70ff --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/RedisUserConstant.java @@ -0,0 +1,11 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +/** + * Redis用户前缀设置 + */ +@Data +public class RedisUserConstant { + public static final String REDIS_CART_KEY = "user::"; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/SQLAutoFillConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/SQLAutoFillConstant.java new file mode 100644 index 0000000..07614cd --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/SQLAutoFillConstant.java @@ -0,0 +1,14 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +/** + * 数据库中自动填充字段 + */ +@Data +public class SQLAutoFillConstant { + public static final String SET_CREATE_TIME = "setCreateTime"; + public static final String SET_UPDATE_TIME = "setUpdateTime"; + public static final String SET_CREATE_USER = "setCreateUser"; + public static final String SET_UPDATE_USER = "setUpdateUser"; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/SecurityConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/SecurityConstant.java new file mode 100644 index 0000000..b0df3f3 --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/SecurityConstant.java @@ -0,0 +1,12 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +import java.util.Arrays; +import java.util.List; + +@Data +public class SecurityConstant { + public static String[] annotations = {"/", "/test/**", "/diagram-viewer/**", "/editor-app/**", "/*.html", "/admin/system/index/login", "/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v3/**", "/swagger-ui.html/**", "/doc.html"}; + public static List annotationsList = Arrays.asList(annotations); +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/StatusConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/StatusConstant.java new file mode 100644 index 0000000..e8e8372 --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/StatusConstant.java @@ -0,0 +1,14 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +/** + * 状态常量,启用或者禁用 + */ +@Data +public class StatusConstant { + // 启用为1 + public static final Integer ENABLE = 1; + // 禁用为0 + public static final Integer DISABLE = 0; +} diff --git a/common/common-result/src/main/java/cn/bunny/common/result/constant/UserConstant.java b/common/common-result/src/main/java/cn/bunny/common/result/constant/UserConstant.java new file mode 100644 index 0000000..3e57b10 --- /dev/null +++ b/common/common-result/src/main/java/cn/bunny/common/result/constant/UserConstant.java @@ -0,0 +1,8 @@ +package cn.bunny.common.result.constant; + +import lombok.Data; + +@Data +public class UserConstant { + public static final String USER_AVATAR = "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132"; +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/properties/SnowflakeProperties.java b/common/service-utils/src/main/java/cn/bunny/common/service/properties/SnowflakeProperties.java new file mode 100644 index 0000000..19b0057 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/properties/SnowflakeProperties.java @@ -0,0 +1,25 @@ +package cn.bunny.common.service.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "bunny.snowflake") +@Data +public class SnowflakeProperties { + // 数据中心id + private Long datacenterId; + // 数据中心id位数 + private Long datacenterBits; + // 机器id + private Long workerId; + // 机器id位数 + private Long workerBits; + // 序列id所占位数 + private Long sequenceBits; + // 时间戳起始点(毫秒) + private Long twepoch; + // 单次批量生成id的最大数量 + private Integer maxBatchCount; +} \ No newline at end of file diff --git a/model/src/main/java/cn/bunny/dto/LoginDto.java b/model/src/main/java/cn/bunny/dto/LoginDto.java new file mode 100644 index 0000000..c4073d3 --- /dev/null +++ b/model/src/main/java/cn/bunny/dto/LoginDto.java @@ -0,0 +1,16 @@ +package cn.bunny.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class LoginDto { + private String username; + // 密码 + private String password; +} diff --git a/model/src/main/java/cn/bunny/entity/system/User.java b/model/src/main/java/cn/bunny/entity/system/User.java new file mode 100644 index 0000000..c03718a --- /dev/null +++ b/model/src/main/java/cn/bunny/entity/system/User.java @@ -0,0 +1,68 @@ +package cn.bunny.entity.system; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 用户信息 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Getter +@Setter +@Accessors(chain = true) +@Schema(description = "用户信息") +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "用户ID") + @TableId(value = "user_id", type = IdType.AUTO) + private String userId; + + @Schema(description = "昵称") + private String nickName; + + @Schema(description = "邮箱") + private String email; + + @Schema(description = "密码") + private String password; + + @Schema(description = "0:女 1:男") + private Integer sex; + + @Schema(description = "个人描述") + private String personDescription; + + @Schema(description = "加入时间") + private LocalDateTime joinTime; + + @Schema(description = "最后登录时间") + private LocalDateTime lastLoginTime; + + @Schema(description = "最后登录IP") + private String lastLoginIp; + + @Schema(description = "最后登录ip地址") + private String lastLoginIpAddress; + + @Schema(description = "积分") + private Integer totalIntegral; + + @Schema(description = "当前积分") + private Integer currentIntegral; + + @Schema(description = "0:禁用 1:正常") + private Byte status; +} diff --git a/model/src/main/java/cn/bunny/entity/system/UserIntegralRecord.java b/model/src/main/java/cn/bunny/entity/system/UserIntegralRecord.java new file mode 100644 index 0000000..ac5ea9c --- /dev/null +++ b/model/src/main/java/cn/bunny/entity/system/UserIntegralRecord.java @@ -0,0 +1,46 @@ +package cn.bunny.entity.system; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 用户积分记录表 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("user_integral_record") +@Schema(description = "用户积分记录表") +public class UserIntegralRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "记录ID") + @TableId(value = "record_id", type = IdType.AUTO) + private Integer recordId; + + @Schema(description = "用户ID") + private String userId; + + @Schema(description = "操作类型") + private Byte operType; + + @Schema(description = "积分") + private Integer integral; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/model/src/main/java/cn/bunny/entity/system/UserRole.java b/model/src/main/java/cn/bunny/entity/system/UserRole.java new file mode 100644 index 0000000..c1ba58c --- /dev/null +++ b/model/src/main/java/cn/bunny/entity/system/UserRole.java @@ -0,0 +1,47 @@ +package cn.bunny.entity.system; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("user_role") +@Schema(description = "UserRole对象") +public class UserRole implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private String id; + + private String userId; + + private String roleName; + + private String description; + + private String roleCode; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; +} diff --git a/model/src/main/java/cn/bunny/vo/system/ValidateCodeVo.java b/model/src/main/java/cn/bunny/vo/system/ValidateCodeVo.java new file mode 100644 index 0000000..b01b14f --- /dev/null +++ b/model/src/main/java/cn/bunny/vo/system/ValidateCodeVo.java @@ -0,0 +1,20 @@ +package cn.bunny.vo.system; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "验证码响应结果实体类") +public class ValidateCodeVo { + @Schema(description = "验证码key") + private String codeKey; // 验证码的key + + @Schema(description = "验证码value") + private String codeValue; // 图片验证码对应的字符串数据 +} \ No newline at end of file diff --git a/module/spring-security/pom.xml b/module/spring-security/pom.xml new file mode 100644 index 0000000..03d252d --- /dev/null +++ b/module/spring-security/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + + cn.bunny + module + 0.0.1-SNAPSHOT + + + spring-security + jar + + spring-security + https://maven.apache.org + + + UTF-8 + + + + + cn.bunny + service-utils + 0.0.1-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.security + spring-security-test + + + diff --git a/module/spring-security/src/main/java/cn/bunny/security/config/WebSecurityConfig.java b/module/spring-security/src/main/java/cn/bunny/security/config/WebSecurityConfig.java new file mode 100644 index 0000000..64cb2f1 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/config/WebSecurityConfig.java @@ -0,0 +1,86 @@ +package cn.bunny.security.config; + +import cn.bunny.common.result.constant.SecurityConstant; +import cn.bunny.security.custom.CustomPasswordEncoder; +import cn.bunny.security.filter.TokenAuthenticationFilter; +import cn.bunny.security.filter.TokenLoginFilterService; +import cn.bunny.security.handelr.SecurityAccessDeniedHandler; +import cn.bunny.security.handelr.SecurityAuthenticationEntryPoint; +import cn.bunny.security.service.CustomAuthorizationManagerService; +import cn.bunny.security.service.CustomUserDetailsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.session.SessionRegistry; +import org.springframework.security.core.session.SessionRegistryImpl; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.util.matcher.RegexRequestMatcher; + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity +public class WebSecurityConfig { + + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private CustomUserDetailsService customUserDetailsService; + @Autowired + private CustomPasswordEncoder customPasswordEncoder; + @Autowired + private CustomAuthorizationManagerService customAuthorizationManager; + @Autowired + private AuthenticationConfiguration authenticationConfiguration; + + @Bean + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + httpSecurity + // 前端段分离不需要---禁用明文验证 + .httpBasic(AbstractHttpConfigurer::disable) + // 前端段分离不需要---禁用默认登录页 + .formLogin(AbstractHttpConfigurer::disable) + // 前端段分离不需要---禁用退出页 + .logout(AbstractHttpConfigurer::disable) + // 前端段分离不需要---csrf攻击 + .csrf(AbstractHttpConfigurer::disable) + // 跨域访问权限,如果需要可以关闭后自己配置跨域访问 + .cors(AbstractHttpConfigurer::disable) + // 前后端分离不需要---因为是无状态的 + .sessionManagement(AbstractHttpConfigurer::disable) + // 前后端分离不需要---记住我,e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey") + .rememberMe(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(authorize -> { + // 如果访问路径有下面的,不需要访问权限 + authorize.requestMatchers(SecurityConstant.annotations).permitAll(); + // 有样式文件,不需要访问权限 + authorize.requestMatchers(RegexRequestMatcher.regexMatcher("^\\S*[css|js]$")).permitAll(); + // 上面都不是需要鉴权访问 + authorize.anyRequest().access(customAuthorizationManager); + }) + .exceptionHandling(exception -> { + // 请求未授权接口 + exception.authenticationEntryPoint(new SecurityAuthenticationEntryPoint()); + // 没有权限访问 + exception.accessDeniedHandler(new SecurityAccessDeniedHandler()); + }) + // 自定义过滤器 + .addFilterBefore(new TokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class) + .addFilterAt(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class) + // 自定义密码加密器和用户登录 + .passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService); + + return httpSecurity.build(); + } + + @Bean + public SessionRegistry sessionRegistry() { + return new SessionRegistryImpl(); + } +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/custom/CustomPasswordEncoder.java b/module/spring-security/src/main/java/cn/bunny/security/custom/CustomPasswordEncoder.java new file mode 100644 index 0000000..57864ed --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/custom/CustomPasswordEncoder.java @@ -0,0 +1,28 @@ +package cn.bunny.security.custom; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.PasswordManagementConfigurer; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.util.DigestUtils; + +/** + * 自定义密码加密比对 + */ +@Configuration +public class CustomPasswordEncoder implements PasswordEncoder, Customizer> { + @Override + public String encode(CharSequence rawPassword) { + return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes()); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + return encodedPassword.matches(DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes())); + } + + @Override + public void customize(PasswordManagementConfigurer httpSecurityPasswordManagementConfigurer) { + } +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/custom/CustomUser.java b/module/spring-security/src/main/java/cn/bunny/security/custom/CustomUser.java new file mode 100644 index 0000000..92bb32d --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/custom/CustomUser.java @@ -0,0 +1,22 @@ +package cn.bunny.security.custom; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.User; + +import java.util.Collection; + +/** + * 重写自带的User + */ +@Getter +@Setter +public class CustomUser extends User { + private cn.bunny.entity.system.User user; + + public CustomUser(cn.bunny.entity.system.User user, Collection authorities) { + super(user.getEmail(), user.getPassword(), authorities); + this.user = user; + } +} \ No newline at end of file diff --git a/module/spring-security/src/main/java/cn/bunny/security/filter/TokenAuthenticationFilter.java b/module/spring-security/src/main/java/cn/bunny/security/filter/TokenAuthenticationFilter.java new file mode 100644 index 0000000..dea5c18 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/filter/TokenAuthenticationFilter.java @@ -0,0 +1,74 @@ +package cn.bunny.security.filter; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.utils.JwtHelper; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class TokenAuthenticationFilter extends OncePerRequestFilter { + private final RedisTemplate redisTemplate; + + public TokenAuthenticationFilter(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + String token = request.getHeader("token"); + + // login请求就没token,直接放行,因为后边有其他的过滤器 + if (token == null) { + doFilter(request, response, chain); + return; + } + + // 如果是登录接口,直接放行 + UsernamePasswordAuthenticationToken authentication = getAuthentication(request); + SecurityContextHolder.getContext().setAuthentication(authentication); + chain.doFilter(request, response); + } + + private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) { + // 请求头是否有token + String token = request.getHeader("token"); + if (StringUtils.hasText(token)) { + String username = JwtHelper.getUserName(token); + if (StringUtils.hasText(username)) { + // 当前用户信息放到ThreadLocal里面 + BaseContext.setUserId(JwtHelper.getUserId(token)); + BaseContext.setUsername(username); + + // 通过username从redis获取权限数据 + String authString = (String) redisTemplate.opsForValue().get(username); + // 把redis获取字符串权限数据转换要求集合类型 List + if (StringUtils.hasText(authString)) { + List maplist = JSON.parseArray(authString, Map.class); + System.out.println(maplist); + List authList = new ArrayList<>(); + for (Map map : maplist) { + String authority = (String) map.get("authority"); + authList.add(new SimpleGrantedAuthority(authority)); + } + return new UsernamePasswordAuthenticationToken(username, null, authList); + } else { + return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>()); + } + } + } + return null; + } +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/filter/TokenLoginFilterService.java b/module/spring-security/src/main/java/cn/bunny/security/filter/TokenLoginFilterService.java new file mode 100644 index 0000000..314d4e3 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/filter/TokenLoginFilterService.java @@ -0,0 +1,84 @@ +package cn.bunny.security.filter; + + +import cn.bunny.common.result.enums.ResultCodeEnum; +import cn.bunny.common.result.utils.Result; +import cn.bunny.common.service.utils.ResponseUtil; +import cn.bunny.dto.LoginDto; +import cn.bunny.security.handelr.SecurityAuthenticationFailureHandler; +import cn.bunny.security.handelr.SecurityAuthenticationSuccessHandler; +import cn.bunny.security.service.CustomUserDetailsService; +import cn.bunny.vo.system.LoginVo; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.util.StringUtils; + +import java.io.IOException; + +/** + * 由于SpringSecurity的登录只能是表单形式 并且用户名密码需要时username、password,可以通过继承 UsernamePasswordAuthenticationFilter 获取登录请求的参数 + * 再去设置到 UsernamePasswordAuthenticationToken 中 来改变请求传参方式、参数名等 或者也可以在登录的时候加入其他参数等等 + * 也可以在这里添加验证码、短信等的验证 + */ +public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilter { + private final RedisTemplate redisTemplate; + private final CustomUserDetailsService customUserDetailsService; + private LoginDto loginDto; + + // 构造方法 + public TokenLoginFilterService(AuthenticationConfiguration authenticationConfiguration, RedisTemplate redisTemplate, CustomUserDetailsService customUserDetailsService) throws Exception { + this.setAuthenticationSuccessHandler(new SecurityAuthenticationSuccessHandler()); + this.setAuthenticationFailureHandler(new SecurityAuthenticationFailureHandler()); + this.setPostOnly(false); + // 指定登录接口及提交方式,可以指定任意路径 + this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/*/login", "POST")); + this.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager()); + this.redisTemplate = redisTemplate; + this.customUserDetailsService = customUserDetailsService; + } + + // 登录认证 + // 获取输入的用户名和密码,调用方法认证 + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { + try { + // 获取用户信息 + loginDto = new ObjectMapper().readValue(request.getInputStream(), LoginDto.class); + // 封装对象 + Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword()); + // 调用方法 + return this.getAuthenticationManager().authenticate(authenticationToken); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + // 认证成功调用方法 + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) { + // 返回登录信息 + LoginVo login = customUserDetailsService.login(loginDto); + ResponseUtil.out(response, Result.success(login)); + } + + // 认证失败调用方法 + protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { + // 用户名为空 + if (!StringUtils.hasText(loginDto.getUsername())) { + ResponseUtil.out(response, Result.error(ResultCodeEnum.USERNAME_NOT_EMPTY)); + } + // 密码为空 + if (!StringUtils.hasText(loginDto.getPassword())) { + ResponseUtil.out(response, Result.error(ResultCodeEnum.PASSWORD_NOT_EMPTY)); + } + // 抛出异常 + ResponseUtil.out(response, Result.error(null, ResultCodeEnum.LOGIN_ERROR)); + } +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAccessDeniedHandler.java b/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAccessDeniedHandler.java new file mode 100644 index 0000000..c4ffb54 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAccessDeniedHandler.java @@ -0,0 +1,26 @@ +package cn.bunny.security.handelr; + +import cn.bunny.common.result.enums.ResultCodeEnum; +import cn.bunny.common.result.utils.Result; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.SneakyThrows; +import org.springframework.security.access.AccessDeniedException; + +/** + * 没有权限访问 + */ +public class SecurityAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler { + @SneakyThrows + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) { + Result result = Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED); + + Object json = JSON.toJSON(result); + + // 返回响应 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(json); + } +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationEntryPoint.java b/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationEntryPoint.java new file mode 100644 index 0000000..8fd92c3 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationEntryPoint.java @@ -0,0 +1,39 @@ +package cn.bunny.security.handelr; + +import cn.bunny.common.result.utils.Result; +import cn.bunny.common.result.enums.ResultCodeEnum; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import java.io.IOException; + +/** + * 请求未认证接口 + */ +@Slf4j +public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { + String token = response.getHeader("token"); + String message = authException.getMessage(); + // 创建结果对象 + Result result; + + if (token == null) { + result = Result.error(new Object(), ResultCodeEnum.LOGIN_AUTH); + log.info("请求未登录接口:{},用户id:{}", message, null); + } else { + result = Result.error(new Object(), ResultCodeEnum.LOGGED_IN_FROM_ANOTHER_DEVICE); + log.info("请求未授权接口:{},用户id:{}", message, token); + } + + + // 返回响应 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(JSON.toJSON(result)); + } +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationFailureHandler.java b/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationFailureHandler.java new file mode 100644 index 0000000..34c21f6 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationFailureHandler.java @@ -0,0 +1,26 @@ +package cn.bunny.security.handelr; + +import cn.bunny.common.result.utils.Result; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.core.AuthenticationException; + +import java.io.IOException; + +public class SecurityAuthenticationFailureHandler implements org.springframework.security.web.authentication.AuthenticationFailureHandler { + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + // 错误消息 + String localizedMessage = exception.getLocalizedMessage(); + Result result = Result.error(localizedMessage); + + // 转成JSON + Object json = JSON.toJSON(result); + + // 返回响应 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(json); + } +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationSuccessHandler.java b/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationSuccessHandler.java new file mode 100644 index 0000000..8642721 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/handelr/SecurityAuthenticationSuccessHandler.java @@ -0,0 +1,26 @@ +package cn.bunny.security.handelr; + +import cn.bunny.common.result.utils.Result; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; + +import java.io.IOException; + +/** + * 登录成功 + */ +public class SecurityAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { + // 获取用户身份信息 + Object principal = authentication.getPrincipal(); + Result result = Result.success(principal); + + // 返回 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(JSON.toJSON(result)); + } +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/service/CustomAuthorizationManagerService.java b/module/spring-security/src/main/java/cn/bunny/security/service/CustomAuthorizationManagerService.java new file mode 100644 index 0000000..3c1f939 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/service/CustomAuthorizationManagerService.java @@ -0,0 +1,7 @@ +package cn.bunny.security.service; + +import org.springframework.security.authorization.AuthorizationManager; +import org.springframework.security.web.access.intercept.RequestAuthorizationContext; + +public interface CustomAuthorizationManagerService extends AuthorizationManager { +} diff --git a/module/spring-security/src/main/java/cn/bunny/security/service/CustomUserDetailsService.java b/module/spring-security/src/main/java/cn/bunny/security/service/CustomUserDetailsService.java new file mode 100644 index 0000000..4db2d85 --- /dev/null +++ b/module/spring-security/src/main/java/cn/bunny/security/service/CustomUserDetailsService.java @@ -0,0 +1,23 @@ +package cn.bunny.security.service; + +import cn.bunny.dto.LoginDto; +import cn.bunny.vo.system.LoginVo; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +public interface CustomUserDetailsService extends UserDetailsService { + /** + * 根据用户名获取用户对象(获取不到直接抛异常) + */ + @Override + UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; + + /** + * 前台用户登录接口 + * + * @param loginDto 登录参数 + * @return 登录后结果返回 + */ + LoginVo login(LoginDto loginDto); +} diff --git a/server-gateway/src/main/java/cn/bunny/service/gateway/task/TemplateTask.java b/server-gateway/src/main/java/cn/bunny/service/gateway/task/TemplateTask.java new file mode 100644 index 0000000..d3232bd --- /dev/null +++ b/server-gateway/src/main/java/cn/bunny/service/gateway/task/TemplateTask.java @@ -0,0 +1,14 @@ +package cn.bunny.service.gateway.task; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class TemplateTask { + @Scheduled(cron = "0/1 5 * * * ?") + public void templateTask() { + log.info("定时任务执行..."); + } +} diff --git a/service/service-admin/Dockerfile b/service/service-admin/Dockerfile new file mode 100644 index 0000000..447a2bc --- /dev/null +++ b/service/service-admin/Dockerfile @@ -0,0 +1,21 @@ +FROM openjdk:21 +MAINTAINER bunny + +#系统编码 +ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 + +# 设置时区,构建镜像时执行的命令 +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +RUN echo "Asia/Shanghai" > /etc/timezone + +# 设定工作目录 +WORKDIR /home/bunny + +# 复制jar包 +COPY target/*.jar /home/bunny/app.jar + +#启动容器时的进程 +ENTRYPOINT ["java","-jar","/home/bunny/app.jar"] + +#暴露 8800 端口 +EXPOSE 8800 \ No newline at end of file diff --git a/service/service-admin/pom.xml b/service/service-admin/pom.xml new file mode 100644 index 0000000..af3768f --- /dev/null +++ b/service/service-admin/pom.xml @@ -0,0 +1,101 @@ + + 4.0.0 + + cn.bunny + service + 0.0.1-SNAPSHOT + + + service-admin + jar + + service-admin + https://maven.apache.org + + + UTF-8 + 192.168.3.98:1100 + 192.168.3.98:2375 + bunny-admin + + + + cn.bunny + spring-security + 0.0.1-SNAPSHOT + + + + cn.bunny + service-utils + 0.0.1-SNAPSHOT + + + cn.bunny + module-mail + 0.0.1-SNAPSHOT + + + cn.bunny + module-minio + 0.0.1-SNAPSHOT + + + + org.aspectj + aspectjrt + + + org.aspectj + aspectjweaver + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + com.spotify + docker-maven-plugin + 1.2.2 + + + + build-image + + package + + build + push + + + + + harbor + http://${docker.repostory} + + http://${docker.host} + + + ${docker.repostory}/${docker.registry.name}/${project.artifactId}:${project.version} + + + ${project.basedir} + + false + + + + + diff --git a/service/service-admin/src/main/java/cn/bunny/service/admin/ServiceAdminApplication.java b/service/service-admin/src/main/java/cn/bunny/service/admin/ServiceAdminApplication.java new file mode 100644 index 0000000..f714149 --- /dev/null +++ b/service/service-admin/src/main/java/cn/bunny/service/admin/ServiceAdminApplication.java @@ -0,0 +1,22 @@ +package cn.bunny.service.admin; + +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; + +@ComponentScan(basePackages = {"cn.bunny"}) +@MapperScan("cn.bunny.service.admin.mapper") +@EnableScheduling// 定时任务 +@EnableCaching// 开启缓存注解 +@SpringBootApplication +@Slf4j +public class ServiceAdminApplication { + public static void main(String[] args) { + log.info("ServiceApplication启动..."); + SpringApplication.run(ServiceAdminApplication.class, args); + } +} \ No newline at end of file diff --git a/service/service-admin/src/main/resources/application-dev.yml b/service/service-admin/src/main/resources/application-dev.yml new file mode 100644 index 0000000..616df4b --- /dev/null +++ b/service/service-admin/src/main/resources/application-dev.yml @@ -0,0 +1,19 @@ +bunny: + datasource: + host: 106.15.251.123 + port: 3305 + sqlData: bunny_docs + username: root + password: "02120212" + + redis: + host: 47.120.65.66 + port: 6379 + database: 3 + password: "02120212" + + minio: + endpointUrl: "http://129.211.31.58:9000" + bucket-name: ssyx + accessKey: bunny + secretKey: "02120212" \ No newline at end of file diff --git a/service/service-admin/src/main/resources/application.yml b/service/service-admin/src/main/resources/application.yml new file mode 100644 index 0000000..036eb8e --- /dev/null +++ b/service/service-admin/src/main/resources/application.yml @@ -0,0 +1,63 @@ +server: + port: 8802 + +spring: + profiles: + active: dev + application: + name: service-admin + + datasource: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${bunny.datasource.host}:${bunny.datasource.port}/${bunny.datasource.sqlData}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true + username: ${bunny.datasource.username} + password: ${bunny.datasource.password} + + data: + redis: + host: ${bunny.redis.host} + port: ${bunny.redis.port} + database: ${bunny.redis.database} + password: ${bunny.redis.password} + lettuce: + pool: + max-active: 20 #最大连接数 + max-wait: -1 #最大阻塞等待时间(负数表示没限制) + max-idle: 5 #最大空闲 + min-idle: 0 #最小空闲 + + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + +mybatis-plus: + mapper-locations: classpath:mapper/*.xml + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志 + +logging: + level: + cn.bunny.service.mapper: debug + cn.bunny.service.controller: info + cn.bunny.service.service: info + pattern: + dateformat: HH:mm:ss:SSS + file: + path: "logs/${spring.application.name}" + +bunny: + minio: + endpointUrl: ${bunny.minio.endpointUrl} + accessKey: ${bunny.minio.accessKey} + secretKey: ${bunny.minio.secretKey} + bucket-name: ${bunny.minio.bucket-name} + + snowflake: + datacenterBits: 5 # 数据中心id位数 + workerBits: 5 # 机器id位数 + sequenceBits: 12 # 序列id所占位数 + datacenterId: 1 # 数据中心id,范围0-2^5-1 + workerId: 1 # 机器id,范围0-2^5-1 + twepoch: 1704038400000 # 时间戳起始点(2024-01-01 00::00:00 的毫秒数) + maxBatchCount: 100000 #单次批量生成id的最大数量 默认10万 \ No newline at end of file diff --git a/service/service-admin/src/main/resources/banner.txt b/service/service-admin/src/main/resources/banner.txt new file mode 100644 index 0000000..cc77fc2 --- /dev/null +++ b/service/service-admin/src/main/resources/banner.txt @@ -0,0 +1,16 @@ +-----------------▄██-█▄--------- +-----------------███▄██▄-------- +-----------------███████-------- +-----------------▀███████------- +-------------------██████▄▄----- +-------------------█████████▄--- +-------------------██████▄████-- +-------▄███████████████████████- +-----▄███████████████████████▀-- +---▄██████████████████████------ +---███████████████████████------ +---███████████████████████------ +-▄▄██████████████████████▀------ +-█████████████████▀█████-------- +-▀██████████████▀▀-▀█████▄------ +-------▀▀▀▀▀▀▀▀▀------▀▀▀▀------ \ No newline at end of file diff --git a/service/service-admin/src/main/resources/favicon.ico b/service/service-admin/src/main/resources/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..385f8a67127e1978b08387383f5935feaf561d04 GIT binary patch literal 17014 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 G5Bv)+nYH-< literal 0 HcmV?d00001 diff --git a/service/service-admin/src/main/resources/logback.xml b/service/service-admin/src/main/resources/logback.xml new file mode 100644 index 0000000..04ecbe3 --- /dev/null +++ b/service/service-admin/src/main/resources/logback.xml @@ -0,0 +1,61 @@ + + + + + + + %cyan([%thread]) %yellow(%-5level) %green(%logger{100}).%boldRed(%method)-%boldMagenta(%line) - %blue(%msg%n) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/service/service-web/Dockerfile b/service/service-web/Dockerfile new file mode 100644 index 0000000..447a2bc --- /dev/null +++ b/service/service-web/Dockerfile @@ -0,0 +1,21 @@ +FROM openjdk:21 +MAINTAINER bunny + +#系统编码 +ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 + +# 设置时区,构建镜像时执行的命令 +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +RUN echo "Asia/Shanghai" > /etc/timezone + +# 设定工作目录 +WORKDIR /home/bunny + +# 复制jar包 +COPY target/*.jar /home/bunny/app.jar + +#启动容器时的进程 +ENTRYPOINT ["java","-jar","/home/bunny/app.jar"] + +#暴露 8800 端口 +EXPOSE 8800 \ No newline at end of file diff --git a/service/service-web/pom.xml b/service/service-web/pom.xml new file mode 100644 index 0000000..6a7c3e7 --- /dev/null +++ b/service/service-web/pom.xml @@ -0,0 +1,114 @@ + + 4.0.0 + + cn.bunny + service + 0.0.1-SNAPSHOT + + + service-web + jar + + service-main + https://maven.apache.org + + + UTF-8 + 192.168.3.98:1100 + 192.168.3.98:2375 + bunny-web + + + + + cn.bunny + spring-security + 0.0.1-SNAPSHOT + + + + cn.bunny + service-utils + 0.0.1-SNAPSHOT + + + cn.bunny + module-mail + 0.0.1-SNAPSHOT + + + cn.bunny + module-minio + 0.0.1-SNAPSHOT + + + + org.aspectj + aspectjrt + + + org.aspectj + aspectjweaver + + + + org.springframework.cloud + spring-cloud-starter-loadbalancer + 4.1.2 + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + 2023.0.0.0-RC1 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + com.spotify + docker-maven-plugin + 1.2.2 + + + + build-image + + package + + build + push + + + + + harbor + http://${docker.repostory} + + http://${docker.host} + + + ${docker.repostory}/${docker.registry.name}/${project.artifactId}:${project.version} + + + ${project.basedir} + + false + + + + + diff --git a/service/service-web/src/main/java/cn/bunny/service/web/ServiceWebApplication.java b/service/service-web/src/main/java/cn/bunny/service/web/ServiceWebApplication.java new file mode 100644 index 0000000..d7bdf63 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/ServiceWebApplication.java @@ -0,0 +1,20 @@ +package cn.bunny.service.web; + +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@Slf4j +@ComponentScan(basePackages = {"cn.bunny"}) +@MapperScan("cn.bunny.service.web.mapper") +@EnableCaching// 开启缓存注解 +public class ServiceWebApplication { + public static void main(String[] args) { + log.info("ServiceApplication启动..."); + SpringApplication.run(ServiceWebApplication.class, args); + } +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/aop/annotation/AutoFill.java b/service/service-web/src/main/java/cn/bunny/service/web/aop/annotation/AutoFill.java new file mode 100644 index 0000000..8c26d32 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/aop/annotation/AutoFill.java @@ -0,0 +1,15 @@ +package cn.bunny.service.aop.annotation; + +import cn.bunny.enums.OperationType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface AutoFill { + // 数据库操作类型 + OperationType value(); +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoFillAspect.java b/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoFillAspect.java new file mode 100644 index 0000000..7d2fc45 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/aop/aspect/AutoFillAspect.java @@ -0,0 +1,27 @@ +package cn.bunny.service.aop.aspect; + +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; + +@Aspect +@Component +@Slf4j +public class AutoFillAspect { + @Pointcut("execution(* cn.bunny.service.*.*(..))") + public void autoFillPointcut() { + } + + /** + * 之前操作 + * + * @param joinPoint 参数 + */ + @Before("autoFillPointcut()") + public void autoFill(JoinPoint joinPoint) { + log.info("开始进行自动填充"); + } +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/controller/LoginController.java b/service/service-web/src/main/java/cn/bunny/service/web/controller/LoginController.java new file mode 100644 index 0000000..8ca67d9 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/controller/LoginController.java @@ -0,0 +1,33 @@ +package cn.bunny.service.web.controller; + +import cn.bunny.common.result.utils.Result; +import cn.bunny.dto.LoginDto; +import cn.bunny.service.web.service.LoginService; +import cn.bunny.vo.system.LoginVo; +import cn.bunny.vo.system.ValidateCodeVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@Tag(name = "登录和注册相关接口") +@RequestMapping("/api") +@RestController +public class LoginController { + @Autowired + private LoginService loginService; + + @Operation(summary = "登录接口", description = "前台用户登录接口") + @PostMapping("login") + public Result login(@RequestBody LoginDto loginDto) { + LoginVo vo = loginService.login(loginDto); + return Result.success(vo); + } + + @Operation(summary = "生成验证码", description = "生成验证码") + @GetMapping("checkCode") + public Result checkCode() { + ValidateCodeVo vo = loginService.checkCode(); + return Result.success(vo); + } +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/controller/UserController.java b/service/service-web/src/main/java/cn/bunny/service/web/controller/UserController.java new file mode 100644 index 0000000..1fad15f --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/controller/UserController.java @@ -0,0 +1,18 @@ +package cn.bunny.service.web.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 用户信息 前端控制器 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@RestController +@RequestMapping("/user") +public class UserController { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/controller/UserIntegralRecordController.java b/service/service-web/src/main/java/cn/bunny/service/web/controller/UserIntegralRecordController.java new file mode 100644 index 0000000..727cf66 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/controller/UserIntegralRecordController.java @@ -0,0 +1,18 @@ +package cn.bunny.service.web.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 用户积分记录表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@RestController +@RequestMapping("/userIntegralRecord") +public class UserIntegralRecordController { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/controller/UserRoleController.java b/service/service-web/src/main/java/cn/bunny/service/web/controller/UserRoleController.java new file mode 100644 index 0000000..c222e9f --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/controller/UserRoleController.java @@ -0,0 +1,18 @@ +package cn.bunny.service.web.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 前端控制器 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@RestController +@RequestMapping("/userRole") +public class UserRoleController { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserIntegralRecordMapper.java b/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserIntegralRecordMapper.java new file mode 100644 index 0000000..257458d --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserIntegralRecordMapper.java @@ -0,0 +1,18 @@ +package cn.bunny.service.web.mapper; + +import cn.bunny.entity.system.UserIntegralRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 用户积分记录表 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Mapper +public interface UserIntegralRecordMapper extends BaseMapper { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserMapper.java b/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserMapper.java new file mode 100644 index 0000000..7332cba --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserMapper.java @@ -0,0 +1,27 @@ +package cn.bunny.service.web.mapper; + +import cn.bunny.entity.system.User; +import cn.bunny.vo.system.LoginVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 用户信息 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Mapper +public interface UserMapper extends BaseMapper { + + /** + * 前台用户登录接口 + * + * @param username 邮箱/昵称 + * @param password 吗,Image + * @return 登录参数 + */ + LoginVo login(String username, String password); +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserRoleMapper.java b/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserRoleMapper.java new file mode 100644 index 0000000..fd5e6e1 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/mapper/UserRoleMapper.java @@ -0,0 +1,18 @@ +package cn.bunny.service.web.mapper; + +import cn.bunny.entity.system.UserRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Mapper +public interface UserRoleMapper extends BaseMapper { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/security/CustomAuthorizationManagerServiceImpl.java b/service/service-web/src/main/java/cn/bunny/service/web/security/CustomAuthorizationManagerServiceImpl.java new file mode 100644 index 0000000..608bf57 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/security/CustomAuthorizationManagerServiceImpl.java @@ -0,0 +1,36 @@ +package cn.bunny.service.web.security; + +import cn.bunny.security.service.CustomAuthorizationManagerService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.access.intercept.RequestAuthorizationContext; +import org.springframework.stereotype.Service; + +import java.util.function.Supplier; + + +/** + * 自定义权限判断 + * 判断用户有哪些权限 + */ +@Service +@Slf4j +public class CustomAuthorizationManagerServiceImpl implements CustomAuthorizationManagerService { + @Override + public void verify(Supplier authentication, RequestAuthorizationContext requestAuthorizationContext) { + CustomAuthorizationManagerService.super.verify(authentication, requestAuthorizationContext); + } + + @Override + public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext object) { + String token = object.getRequest().getHeader("token"); + + if (token == null) { + throw new AccessDeniedException(""); + } + + return new AuthorizationDecision(true); + } +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/security/CustomUserDetailsService.java b/service/service-web/src/main/java/cn/bunny/service/web/security/CustomUserDetailsService.java new file mode 100644 index 0000000..61867c8 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/security/CustomUserDetailsService.java @@ -0,0 +1,58 @@ +package cn.bunny.service.web.security; + +import cn.bunny.dto.LoginDto; +import cn.bunny.entity.system.User; +import cn.bunny.entity.system.UserRole; +import cn.bunny.security.custom.CustomUser; +import cn.bunny.service.web.mapper.UserMapper; +import cn.bunny.service.web.mapper.UserRoleMapper; +import cn.bunny.service.web.service.LoginService; +import cn.bunny.vo.system.LoginVo; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import java.util.List; + +@Configuration +public class CustomUserDetailsService implements cn.bunny.security.service.CustomUserDetailsService { + @Autowired + private UserMapper userMapper; + @Autowired + private LoginService loginService; + @Autowired + private UserRoleMapper userRoleMapper; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 根据邮箱查询用户名 + User user = userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getEmail, username)); + List sysRoleList = userRoleMapper.selectList(null); + // 如果这次为空,再试下查询昵称 + if (user == null) { + user = userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getNickName, username)); + } + // 都为空抛出异常,用户不存在 + if (user == null) { + throw new UsernameNotFoundException(""); + } + + // 查询所有的角色 + List roleAuthoritieList = sysRoleList.stream().map(UserRole::getRoleCode).toList(); + return new CustomUser(user, AuthorityUtils.createAuthorityList(roleAuthoritieList)); + } + + /** + * 前台用户登录接口 + * + * @param loginDto 登录参数 + * @return 登录后结果返回 + */ + @Override + public LoginVo login(LoginDto loginDto) { + return loginService.login(loginDto); + } +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/service/LoginService.java b/service/service-web/src/main/java/cn/bunny/service/web/service/LoginService.java new file mode 100644 index 0000000..433c1b0 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/service/LoginService.java @@ -0,0 +1,24 @@ +package cn.bunny.service.web.service; + +import cn.bunny.dto.LoginDto; +import cn.bunny.entity.system.User; +import cn.bunny.vo.system.LoginVo; +import cn.bunny.vo.system.ValidateCodeVo; +import com.baomidou.mybatisplus.extension.service.IService; + +public interface LoginService extends IService { + /** + * 前台用户登录接口 + * + * @param loginDto 登录参数 + * @return 登录后结果返回 + */ + LoginVo login(LoginDto loginDto); + + /** + * 生成验证码 + * + * @return 验证码生成信息 + */ + ValidateCodeVo checkCode(); +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/service/UserIntegralRecordService.java b/service/service-web/src/main/java/cn/bunny/service/web/service/UserIntegralRecordService.java new file mode 100644 index 0000000..091d37f --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/service/UserIntegralRecordService.java @@ -0,0 +1,16 @@ +package cn.bunny.service.web.service; + +import cn.bunny.entity.system.UserIntegralRecord; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 用户积分记录表 服务类 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +public interface UserIntegralRecordService extends IService { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/service/UserRoleService.java b/service/service-web/src/main/java/cn/bunny/service/web/service/UserRoleService.java new file mode 100644 index 0000000..f3b6f5a --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/service/UserRoleService.java @@ -0,0 +1,16 @@ +package cn.bunny.service.web.service; + +import cn.bunny.entity.system.UserRole; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +public interface UserRoleService extends IService { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/service/UserService.java b/service/service-web/src/main/java/cn/bunny/service/web/service/UserService.java new file mode 100644 index 0000000..2f5ffd4 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/service/UserService.java @@ -0,0 +1,16 @@ +package cn.bunny.service.web.service; + +import cn.bunny.entity.system.User; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 用户信息 服务类 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +public interface UserService extends IService { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/service/impl/LoginServiceImpl.java b/service/service-web/src/main/java/cn/bunny/service/web/service/impl/LoginServiceImpl.java new file mode 100644 index 0000000..c4c22df --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/service/impl/LoginServiceImpl.java @@ -0,0 +1,69 @@ +package cn.bunny.service.web.service.impl; + +import cn.bunny.common.result.constant.CommonMessageConstant; +import cn.bunny.common.service.utils.EmptyUtil; +import cn.bunny.common.service.utils.JwtHelper; +import cn.bunny.dto.LoginDto; +import cn.bunny.entity.system.User; +import cn.bunny.service.web.mapper.UserMapper; +import cn.bunny.service.web.service.LoginService; +import cn.bunny.vo.system.LoginVo; +import cn.bunny.vo.system.ValidateCodeVo; +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.CircleCaptcha; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.util.DigestUtils; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@Service +public class LoginServiceImpl extends ServiceImpl implements LoginService { + @Autowired + private UserMapper userMapper; + @Autowired + private RedisTemplate redisTemplate; + + /** + * 前台用户登录接口 + * + * @param loginDto 登录参数 + * @return 登录后结果返回 + */ + @Override + public LoginVo login(LoginDto loginDto) { + // 判断用户和密码是否为空 + String username = loginDto.getUsername(); + EmptyUtil.isEmpty(username, CommonMessageConstant.USERNAME_NOT_EMPTY); + // 密码不能为空 + EmptyUtil.isEmpty(loginDto.getPassword(), CommonMessageConstant.PASSWORD_NOT_EMPTY); + String password = DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes()); + + // 设置返回类型 + LoginVo loginVo = userMapper.login(username, password); + String token = JwtHelper.createToken(Long.valueOf(loginVo.getUserId()), loginVo.getEmail(), 7); + loginVo.setToken(token); + + return loginVo; + } + + /** + * 生成验证码 + * + * @return 验证码生成信息 + */ + @Override + public ValidateCodeVo checkCode() { + // 生成验证码 + CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2); + String code = captcha.getCode(); + String base64Image = "data:image/png;base64," + captcha.getImageBase64(); + // 存储到Redis中 + String uuid = UUID.randomUUID().toString().replaceAll("-", ""); + redisTemplate.opsForValue().set(uuid, code, 10, TimeUnit.MINUTES); + return ValidateCodeVo.builder().codeKey(uuid).codeValue(base64Image).build(); + } +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserIntegralRecordServiceImpl.java b/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserIntegralRecordServiceImpl.java new file mode 100644 index 0000000..072bf9d --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserIntegralRecordServiceImpl.java @@ -0,0 +1,20 @@ +package cn.bunny.service.web.service.impl; + +import cn.bunny.entity.system.UserIntegralRecord; +import cn.bunny.service.web.mapper.UserIntegralRecordMapper; +import cn.bunny.service.web.service.UserIntegralRecordService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户积分记录表 服务实现类 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Service +public class UserIntegralRecordServiceImpl extends ServiceImpl implements UserIntegralRecordService { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserRoleServiceImpl.java b/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserRoleServiceImpl.java new file mode 100644 index 0000000..1758324 --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserRoleServiceImpl.java @@ -0,0 +1,20 @@ +package cn.bunny.service.web.service.impl; + +import cn.bunny.entity.system.UserRole; +import cn.bunny.service.web.mapper.UserRoleMapper; +import cn.bunny.service.web.service.UserRoleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Service +public class UserRoleServiceImpl extends ServiceImpl implements UserRoleService { + +} diff --git a/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserServiceImpl.java b/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..e63451a --- /dev/null +++ b/service/service-web/src/main/java/cn/bunny/service/web/service/impl/UserServiceImpl.java @@ -0,0 +1,20 @@ +package cn.bunny.service.web.service.impl; + +import cn.bunny.entity.system.User; +import cn.bunny.service.web.mapper.UserMapper; +import cn.bunny.service.web.service.UserService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户信息 服务实现类 + *

+ * + * @author Bunny + * @since 2024-05-13 + */ +@Service +public class UserServiceImpl extends ServiceImpl implements UserService { + +} diff --git a/service/service-web/src/main/resources/application-dev.yml b/service/service-web/src/main/resources/application-dev.yml new file mode 100644 index 0000000..0209e71 --- /dev/null +++ b/service/service-web/src/main/resources/application-dev.yml @@ -0,0 +1,24 @@ +bunny: + datasource: + host: 106.15.251.123 + port: 3305 + sqlData: bunny_docs + username: root + password: "02120212" + + redis: + host: 47.120.65.66 + port: 6379 + database: 3 + password: "02120212" + + minio: + endpointUrl: "http://129.211.31.58:9000" + bucket-name: ssyx + accessKey: bunny + secretKey: "02120212" + + nacos: + server-addr: z-bunny.cn:8848 + discovery: + namespace: bunnyBBS \ No newline at end of file diff --git a/service/service-web/src/main/resources/application.yml b/service/service-web/src/main/resources/application.yml new file mode 100644 index 0000000..0ec40d1 --- /dev/null +++ b/service/service-web/src/main/resources/application.yml @@ -0,0 +1,71 @@ +server: + port: 8801 + +spring: + profiles: + active: dev + application: + name: service-web + datasource: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${bunny.datasource.host}:${bunny.datasource.port}/${bunny.datasource.sqlData}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true + username: ${bunny.datasource.username} + password: ${bunny.datasource.password} + + data: + redis: + host: ${bunny.redis.host} + port: ${bunny.redis.port} + database: ${bunny.redis.database} + password: ${bunny.redis.password} + lettuce: + pool: + max-active: 20 #最大连接数 + max-wait: -1 #最大阻塞等待时间(负数表示没限制) + max-idle: 5 #最大空闲 + min-idle: 0 #最小空闲 + + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + + cloud: + sentinel: + log: + dir: logs/${spring.application.name}/sentinel + nacos: + discovery: + namespace: ${bunny.nacos.discovery.namespace} + server-addr: ${bunny.nacos.server-addr} + +mybatis-plus: + mapper-locations: classpath:mapper/*.xml + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志 + +logging: + level: + cn.bunny.service.mapper: debug + cn.bunny.service.controller: info + cn.bunny.service.service: info + pattern: + dateformat: HH:mm:ss:SSS + file: + path: "logs/${spring.application.name}" + +bunny: + minio: + endpointUrl: ${bunny.minio.endpointUrl} + accessKey: ${bunny.minio.accessKey} + secretKey: ${bunny.minio.secretKey} + bucket-name: ${bunny.minio.bucket-name} + + snowflake: + datacenterBits: 5 # 数据中心id位数 + workerBits: 5 # 机器id位数 + sequenceBits: 12 # 序列id所占位数 + datacenterId: 1 # 数据中心id,范围0-2^5-1 + workerId: 1 # 机器id,范围0-2^5-1 + twepoch: 1704038400000 # 时间戳起始点(2024-01-01 00::00:00 的毫秒数) + maxBatchCount: 100000 #单次批量生成id的最大数量 默认10万 \ No newline at end of file diff --git a/service/service-web/src/main/resources/banner.txt b/service/service-web/src/main/resources/banner.txt new file mode 100644 index 0000000..cc77fc2 --- /dev/null +++ b/service/service-web/src/main/resources/banner.txt @@ -0,0 +1,16 @@ +-----------------▄██-█▄--------- +-----------------███▄██▄-------- +-----------------███████-------- +-----------------▀███████------- +-------------------██████▄▄----- +-------------------█████████▄--- +-------------------██████▄████-- +-------▄███████████████████████- +-----▄███████████████████████▀-- +---▄██████████████████████------ +---███████████████████████------ +---███████████████████████------ +-▄▄██████████████████████▀------ +-█████████████████▀█████-------- +-▀██████████████▀▀-▀█████▄------ +-------▀▀▀▀▀▀▀▀▀------▀▀▀▀------ \ No newline at end of file diff --git a/service/service-web/src/main/resources/favicon.ico b/service/service-web/src/main/resources/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..385f8a67127e1978b08387383f5935feaf561d04 GIT binary patch literal 17014 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 G5Bv)+nYH-< literal 0 HcmV?d00001 diff --git a/service/service-web/src/main/resources/logback.xml b/service/service-web/src/main/resources/logback.xml new file mode 100644 index 0000000..04ecbe3 --- /dev/null +++ b/service/service-web/src/main/resources/logback.xml @@ -0,0 +1,61 @@ + + + + + + + %cyan([%thread]) %yellow(%-5level) %green(%logger{100}).%boldRed(%method)-%boldMagenta(%line) - %blue(%msg%n) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/service/service-web/src/main/resources/mapper/UserIntegralRecordMapper.xml b/service/service-web/src/main/resources/mapper/UserIntegralRecordMapper.xml new file mode 100644 index 0000000..198bd01 --- /dev/null +++ b/service/service-web/src/main/resources/mapper/UserIntegralRecordMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + user_id, oper_type, integral, create_time + + + diff --git a/service/service-web/src/main/resources/mapper/UserMapper.xml b/service/service-web/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..a45e006 --- /dev/null +++ b/service/service-web/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,19 @@ + + + + + + + user_id, nick_name, email, password, sex, person_description, join_time, last_login_time, last_login_ip, last_login_ip_address, total_integral, current_integral, status + + + + + + diff --git a/service/service-web/src/main/resources/mapper/UserRoleMapper.xml b/service/service-web/src/main/resources/mapper/UserRoleMapper.xml new file mode 100644 index 0000000..332b514 --- /dev/null +++ b/service/service-web/src/main/resources/mapper/UserRoleMapper.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + id, user_id, role_name, description, role_code, create_time, update_time + + +