From 15baa509073eb6d9cf70e2c032b20998c062cb6a Mon Sep 17 00:00:00 2001 From: lensferno Date: Thu, 18 Aug 2022 20:56:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=99=BB=E5=BD=95=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API-Document.md | 12 +- pom.xml | 19 ++- .../dscape/auth/StpInterfaceImpl.java | 5 +- .../lensfrex/dscape/dao/entity/UserBasic.java | 6 +- .../dscape/dao/mapper/UserBasicMapper.java | 14 ++ .../dscape/dao/service/UserBasicService.java | 13 ++ .../impl/RolePermissionServiceImpl.java | 1 + .../service/impl/UserBasicServiceImpl.java | 16 ++ .../dto/request/user/RegisterRequestBody.java | 10 ++ .../dto/response/general/ResponseCode.java | 4 + .../response/user/RegisterResponseBody.java | 9 ++ .../lensfrex/dscape/enums/user/UserBasic.java | 62 -------- .../lensfrex/dscape/enums/user/UserRole.java | 17 --- .../dscape/enums/user/UserRoleEnum.java | 20 +++ .../dscape/enums/user/UserStatus.java | 15 -- .../dscape/enums/user/UserStatusEnum.java | 21 +++ .../dscape/exception/GlobalException.java | 16 ++ .../handler/GlobalExceptionHandler.java | 137 ++++++++++++++++++ .../dscape/utils/ObjectJsonSerializer.java | 45 ++++++ .../dscape/utils/ObjectSerializer.java | 48 ++++++ .../web/controllers/user/UserController.java | 24 ++- .../dscape/web/service/user/UserService.java | 74 +++++++++- src/main/resources/application.yml | 15 +- 23 files changed, 487 insertions(+), 116 deletions(-) create mode 100644 src/main/java/net/lensfrex/dscape/dao/mapper/UserBasicMapper.java create mode 100644 src/main/java/net/lensfrex/dscape/dao/service/UserBasicService.java create mode 100644 src/main/java/net/lensfrex/dscape/dao/service/impl/UserBasicServiceImpl.java create mode 100644 src/main/java/net/lensfrex/dscape/dto/request/user/RegisterRequestBody.java create mode 100644 src/main/java/net/lensfrex/dscape/dto/response/user/RegisterResponseBody.java delete mode 100644 src/main/java/net/lensfrex/dscape/enums/user/UserBasic.java delete mode 100644 src/main/java/net/lensfrex/dscape/enums/user/UserRole.java create mode 100644 src/main/java/net/lensfrex/dscape/enums/user/UserRoleEnum.java delete mode 100644 src/main/java/net/lensfrex/dscape/enums/user/UserStatus.java create mode 100644 src/main/java/net/lensfrex/dscape/enums/user/UserStatusEnum.java create mode 100644 src/main/java/net/lensfrex/dscape/exception/GlobalException.java create mode 100644 src/main/java/net/lensfrex/dscape/exception/handler/GlobalExceptionHandler.java create mode 100644 src/main/java/net/lensfrex/dscape/utils/ObjectJsonSerializer.java create mode 100644 src/main/java/net/lensfrex/dscape/utils/ObjectSerializer.java diff --git a/API-Document.md b/API-Document.md index b535785..7ef34da 100644 --- a/API-Document.md +++ b/API-Document.md @@ -63,13 +63,13 @@ | 参数 | 值类型 | 可空 | 说明 | | -------- | ------ | ----- | ------------------------------------------------ | - | userName | string | false | 用户登录名,非空 | + | user_name | string | false | 用户登录名,非空 | | password | string | false | 用户登录密码,非空,其值为明文密码两次sha256加密 | 例如: ``` json { - "userName": "admin", + "user_name": "admin", "password": "e723fb2ff93afb010960ac20c05439f1cdd1ecbb533947e7de9f43656a612052" } ``` @@ -121,14 +121,14 @@ | 参数 | 值类型 | 可空 | 说明 | | -------- | ------ | ----- | ------------------------------------------------ | - | userName | string | false | 用户登录名,非空 | + | user_name | string | false | 用户登录名,非空 | | password | string | false | 用户登录密码,非空,其值为明文密码两次sha256加密 | | superior | string | true | 上级管理员用户名 | 例如: ``` json { - "userName": "admin", + "user_name": "admin", "password": "e723fb2ff93afb010960ac20c05439f1cdd1ecbb533947e7de9f43656a612052", "superior": "lensfrex" } @@ -384,7 +384,7 @@ | 参数 | 值类型 | 可空 | 说明 | | -------- | -------------- | -------------------- | ------------------------------------------------ | - | userName | string | false | 用户登录名,非空 | + | user_name | string | false | 用户登录名,非空 | | password | string | false | 用户登录密码,非空,其值为明文密码两次sha256加密 | | role | int | true | 用户角色 | | token | string(header) | 管理员的access_token | @@ -392,7 +392,7 @@ 例如: ``` json { - "userName": "admin", + "user_name": "admin", "password": "e723fb2ff93afb010960ac20c05439f1cdd1ecbb533947e7de9f43656a612052", "role": 0 } diff --git a/pom.xml b/pom.xml index ac6c270..e8e24ad 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ dscape-server dscape-server - 1.8 + 11 @@ -136,6 +136,23 @@ commons-pool2 + + + cn.langpy + ko-time + 2.2.2 + + + org.springframework.boot + spring-boot-starter-freemarker + 2.7.1 + + + org.springframework.boot + spring-boot-starter-aop + 2.7.1 + + diff --git a/src/main/java/net/lensfrex/dscape/auth/StpInterfaceImpl.java b/src/main/java/net/lensfrex/dscape/auth/StpInterfaceImpl.java index 5679fe1..89d6623 100644 --- a/src/main/java/net/lensfrex/dscape/auth/StpInterfaceImpl.java +++ b/src/main/java/net/lensfrex/dscape/auth/StpInterfaceImpl.java @@ -34,7 +34,6 @@ public class StpInterfaceImpl implements StpInterface { this.redis = redis; } - @Override public List getPermissionList(Object loginId, String loginType) { String uid = (String) loginId; @@ -43,7 +42,7 @@ public class StpInterfaceImpl implements StpInterface { List rolePermissions = new ArrayList<>(); for (String role : userRoles) { - String redisRolePermissionKey = "dscape:auth:role.permission:" + role; + String redisRolePermissionKey = "dscape:auth:role:permission:" + role; if (Boolean.FALSE.equals(redis.hasKey(redisRolePermissionKey))) { log.debug("角色 " + uid + " 的权限信息缓存不存在,从数据库中查找并放入缓存"); @@ -70,7 +69,7 @@ public class StpInterfaceImpl implements StpInterface { @Override public List getRoleList(Object loginId, String loginType) { String uid = (String) loginId; - String redisUserRoleKey = "dscape:auth:user.role:" + uid; + String redisUserRoleKey = "dscape:auth:user:role:" + uid; List userRoleList = new ArrayList<>(2); if (Boolean.FALSE.equals(redis.hasKey(redisUserRoleKey))) { diff --git a/src/main/java/net/lensfrex/dscape/dao/entity/UserBasic.java b/src/main/java/net/lensfrex/dscape/dao/entity/UserBasic.java index 77a1fa6..179991a 100644 --- a/src/main/java/net/lensfrex/dscape/dao/entity/UserBasic.java +++ b/src/main/java/net/lensfrex/dscape/dao/entity/UserBasic.java @@ -1,16 +1,16 @@ package net.lensfrex.dscape.dao.entity; import lombok.Data; -import java.io.Serializable; -import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.io.Serializable; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; /** * @description user_basic * @author lensfrex - * @date 2022-08-17 + * @date 2022-08-18 */ @Data public class UserBasic implements Serializable { diff --git a/src/main/java/net/lensfrex/dscape/dao/mapper/UserBasicMapper.java b/src/main/java/net/lensfrex/dscape/dao/mapper/UserBasicMapper.java new file mode 100644 index 0000000..a1c2f2e --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/dao/mapper/UserBasicMapper.java @@ -0,0 +1,14 @@ +package net.lensfrex.dscape.dao.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; +import net.lensfrex.dscape.dao.entity.UserBasic; +import java.util.List; +/** + * @description user_basicMapper + * @author lensfrex + * @date 2022-08-18 + */ +@Mapper +public interface UserBasicMapper extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/net/lensfrex/dscape/dao/service/UserBasicService.java b/src/main/java/net/lensfrex/dscape/dao/service/UserBasicService.java new file mode 100644 index 0000000..31fd3f9 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/dao/service/UserBasicService.java @@ -0,0 +1,13 @@ +package net.lensfrex.dscape.dao.service; +import net.lensfrex.dscape.dao.entity.UserBasic; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.IService; +/** + * @description user_basic服务层 + * @author lensfrex + * @date 2022-08-18 + */ +@Service +public interface UserBasicService extends IService { + +} \ No newline at end of file diff --git a/src/main/java/net/lensfrex/dscape/dao/service/impl/RolePermissionServiceImpl.java b/src/main/java/net/lensfrex/dscape/dao/service/impl/RolePermissionServiceImpl.java index b94e376..9d2ae2f 100644 --- a/src/main/java/net/lensfrex/dscape/dao/service/impl/RolePermissionServiceImpl.java +++ b/src/main/java/net/lensfrex/dscape/dao/service/impl/RolePermissionServiceImpl.java @@ -17,6 +17,7 @@ import java.util.List; @Service public class RolePermissionServiceImpl extends ServiceImpl implements RolePermissionService { + @Override public List getPermissions(String role) { QueryWrapper wrapper = new QueryWrapper<>(); diff --git a/src/main/java/net/lensfrex/dscape/dao/service/impl/UserBasicServiceImpl.java b/src/main/java/net/lensfrex/dscape/dao/service/impl/UserBasicServiceImpl.java new file mode 100644 index 0000000..4bd79f5 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/dao/service/impl/UserBasicServiceImpl.java @@ -0,0 +1,16 @@ +/* + * Class created by lensfrex. + */ + +package net.lensfrex.dscape.dao.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.lensfrex.dscape.dao.entity.UserBasic; +import net.lensfrex.dscape.dao.mapper.UserBasicMapper; +import net.lensfrex.dscape.dao.service.UserBasicService; +import org.springframework.stereotype.Service; + +@Service +public class UserBasicServiceImpl extends ServiceImpl implements UserBasicService { + +} \ No newline at end of file diff --git a/src/main/java/net/lensfrex/dscape/dto/request/user/RegisterRequestBody.java b/src/main/java/net/lensfrex/dscape/dto/request/user/RegisterRequestBody.java new file mode 100644 index 0000000..24b18d9 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/dto/request/user/RegisterRequestBody.java @@ -0,0 +1,10 @@ +package net.lensfrex.dscape.dto.request.user; + +import lombok.Data; + +@Data +public class RegisterRequestBody { + private String password; + private String superior; + private String userName; +} \ No newline at end of file diff --git a/src/main/java/net/lensfrex/dscape/dto/response/general/ResponseCode.java b/src/main/java/net/lensfrex/dscape/dto/response/general/ResponseCode.java index a24f8d4..819992f 100644 --- a/src/main/java/net/lensfrex/dscape/dto/response/general/ResponseCode.java +++ b/src/main/java/net/lensfrex/dscape/dto/response/general/ResponseCode.java @@ -14,6 +14,10 @@ public enum ResponseCode { SERVER_INTERNAL_ERROR(50000, "服务器内部错误"), API_NOT_IMPLEMENT(0, "接口未实现"), + USERNAME_OR_PASSWORD_WRONG(40301, "用户名或密码不正确"), + USER_WAS_BANNED(40302, "用户已被封禁"), + USER_WAS_NOT_IDENTIFIED(40301, "上级管理员未认证该用户"), + ; private final int code; diff --git a/src/main/java/net/lensfrex/dscape/dto/response/user/RegisterResponseBody.java b/src/main/java/net/lensfrex/dscape/dto/response/user/RegisterResponseBody.java new file mode 100644 index 0000000..a926011 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/dto/response/user/RegisterResponseBody.java @@ -0,0 +1,9 @@ +package net.lensfrex.dscape.dto.response.user; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class RegisterResponseBody { + private String uid; +} \ No newline at end of file diff --git a/src/main/java/net/lensfrex/dscape/enums/user/UserBasic.java b/src/main/java/net/lensfrex/dscape/enums/user/UserBasic.java deleted file mode 100644 index 6504014..0000000 --- a/src/main/java/net/lensfrex/dscape/enums/user/UserBasic.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.lensfrex.dscape.enums.user; - -public class UserBasic { - private String uid; - private String userName; - private String password; - private UserStatus status; - private UserRole role; - - public String getUid() { - return uid; - } - - public void setUid(String uid) { - this.uid = uid; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public UserRole getRole() { - return role; - } - - public void setRole(UserRole role) { - this.role = role; - } - - public UserStatus getStatus() { - return status; - } - - public void setStatus(UserStatus status) { - this.status = status; - } - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("UserBasic{"); - sb.append("uid='").append(uid).append('\''); - sb.append(", userName='").append(userName).append('\''); - sb.append(", password='").append(password).append('\''); - sb.append(", status=").append(status); - sb.append(", role=").append(role); - sb.append('}'); - return sb.toString(); - } -} - diff --git a/src/main/java/net/lensfrex/dscape/enums/user/UserRole.java b/src/main/java/net/lensfrex/dscape/enums/user/UserRole.java deleted file mode 100644 index c889c60..0000000 --- a/src/main/java/net/lensfrex/dscape/enums/user/UserRole.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.lensfrex.dscape.enums.user; - -import com.baomidou.mybatisplus.annotation.EnumValue; - -public enum UserRole { - ADMIN(1, "admin"), NORMAL_USER(0, "normal"); - - @EnumValue - private final int role; - - private final String desc; - - UserRole(int role, String desc) { - this.role = role; - this.desc = desc; - } -} diff --git a/src/main/java/net/lensfrex/dscape/enums/user/UserRoleEnum.java b/src/main/java/net/lensfrex/dscape/enums/user/UserRoleEnum.java new file mode 100644 index 0000000..6b3c5f1 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/enums/user/UserRoleEnum.java @@ -0,0 +1,20 @@ +package net.lensfrex.dscape.enums.user; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import lombok.Getter; + +@Getter +public enum UserRoleEnum { + ADMIN(1, "admin"), + NORMAL_USER(0, "normal"); + + @EnumValue + private final int code; + + private final String name; + + UserRoleEnum(int code, String name) { + this.code = code; + this.name = name; + } +} diff --git a/src/main/java/net/lensfrex/dscape/enums/user/UserStatus.java b/src/main/java/net/lensfrex/dscape/enums/user/UserStatus.java deleted file mode 100644 index d2a3a6b..0000000 --- a/src/main/java/net/lensfrex/dscape/enums/user/UserStatus.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.lensfrex.dscape.enums.user; - -import com.baomidou.mybatisplus.annotation.EnumValue; - -public enum UserStatus { - - NORMAL(0), BANNED(1), DELETED(2); - - @EnumValue - private final int status; - - UserStatus(int status) { - this.status = status; - } -} diff --git a/src/main/java/net/lensfrex/dscape/enums/user/UserStatusEnum.java b/src/main/java/net/lensfrex/dscape/enums/user/UserStatusEnum.java new file mode 100644 index 0000000..f79a895 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/enums/user/UserStatusEnum.java @@ -0,0 +1,21 @@ +package net.lensfrex.dscape.enums.user; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import lombok.Getter; + +@Getter +public enum UserStatusEnum { + + NORMAL(0, "正常"), + BANNED(1, "封禁中"), + NOT_IDENTIFIED(2, "管理员未认证"); + + @EnumValue + private final int code; + private final String name; + + UserStatusEnum(int code, String name) { + this.code = code; + this.name = name; + } +} diff --git a/src/main/java/net/lensfrex/dscape/exception/GlobalException.java b/src/main/java/net/lensfrex/dscape/exception/GlobalException.java new file mode 100644 index 0000000..6a5e8c0 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/exception/GlobalException.java @@ -0,0 +1,16 @@ +package net.lensfrex.dscape.exception; + +import net.lensfrex.dscape.dto.response.general.ResponseCode; + +public class GlobalException extends RuntimeException { + private final ResponseCode responseCode; + + public GlobalException(ResponseCode responseCode) { + super(responseCode.toString()); + this.responseCode = responseCode; + } + + public ResponseCode getResponseCode() { + return responseCode; + } +} \ No newline at end of file diff --git a/src/main/java/net/lensfrex/dscape/exception/handler/GlobalExceptionHandler.java b/src/main/java/net/lensfrex/dscape/exception/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..f67260b --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/exception/handler/GlobalExceptionHandler.java @@ -0,0 +1,137 @@ +package net.lensfrex.dscape.exception.handler; + +import com.fasterxml.jackson.databind.JsonMappingException; +import net.lensfrex.dscape.dto.response.general.Response; +import net.lensfrex.dscape.dto.response.general.ResponseCode; +import net.lensfrex.dscape.exception.GlobalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.HttpMediaTypeNotSupportedException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +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.multipart.MultipartException; + +/** + * 全局异常处理,负责后端抛出Exception时响应相应的信息 + */ +@RestControllerAdvice +public class GlobalExceptionHandler { + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * 负责处理各种自定义业务异常(权限不足,学号不存在等) + * @param e 抛出的异常 + * @return 统一响应 + */ + @ExceptionHandler(GlobalException.class) + public Response handler(GlobalException e) { + log.debug("请求错误: " + e.getResponseCode().getMessage()); + return Response.error(e.getResponseCode()); + } + + /** + * 负责处理和响应其他部分都没有接收的异常(说白了就是剩下的都返回50000) + * 这部分日志要特别关注,所以以error打出来 + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(Exception.class) + public Response handler(Exception e) { + log.error("请求错误: " + e.getMessage()); + log.error("异常类: " + e.getClass()); + log.error("追踪:", e); + return Response.error(ResponseCode.SERVER_INTERNAL_ERROR); + } + + /** + * 处理参数不完整的请求异常 + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(MissingServletRequestParameterException.class) + public Response handler(MissingServletRequestParameterException e) { + log.debug("请求的参数不完整: " + e.getMessage()); + return Response.error(ResponseCode.PARAM_WRONG); + } + + /** + * 处理参数类型错误的请求异常(请求参数类型错误) + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + public Response handler(MethodArgumentTypeMismatchException e) { + log.debug(String.format("请求错误(%s): %s", e.getClass().getName(), e.getMessage())); + return Response.error(ResponseCode.PARAM_WRONG); + } + + /** + * 处理参数类型错误的请求异常(请求参数类型错误) + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(IllegalArgumentException.class) + public Response handler(IllegalArgumentException e) { + log.debug(String.format("请求错误(%s): %s", e.getClass().getName(), e.getMessage())); + return Response.error(ResponseCode.PARAM_WRONG); + } + + /** + * 处理参数类型错误的请求异常2(Json解析错误) + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(JsonMappingException.class) + public Response handler(JsonMappingException e) { + log.debug(String.format("请求错误(%s): %s", e.getClass().getName(), e.getMessage())); + return Response.error(ResponseCode.PARAM_WRONG); + } + + /** + * 处理参数类型错误的请求异常3(字段映射错误) + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(HttpMessageNotReadableException.class) + public Response handler(HttpMessageNotReadableException e) { + log.debug(String.format("请求错误(%s): %s", e.getClass().getName(), e.getMessage())); + return Response.error(ResponseCode.PARAM_WRONG); + } + + /** + * 处理请求头中“Content-Type”字段不正确的异常 + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(HttpMediaTypeNotSupportedException.class) + public Response handler(HttpMediaTypeNotSupportedException e) { + log.debug(String.format("请求错误(%s): %s", e.getClass().getName(), e.getMessage())); + return Response.error(ResponseCode.PARAM_WRONG, "请求头\"Contene-Type\"字段有误"); + } + + /** + * 处理请求方法错误的情况 + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public Response handler(HttpRequestMethodNotSupportedException e) { + log.debug(String.format("请求错误(%s): %s", e.getClass().getName(), e.getMessage())); + return Response.error(ResponseCode.INVALID_REQUEST); + } + + /** + * 处理上传文件时不是Multipart方式 + * @param e 异常 + * @return 统一响应 + */ + @ExceptionHandler(MultipartException.class) + public Response handler(MultipartException e) { + log.debug(String.format("请求错误(%s): %s", e.getClass().getName(), e.getMessage())); + return Response.error(ResponseCode.INVALID_REQUEST); + } +} \ No newline at end of file diff --git a/src/main/java/net/lensfrex/dscape/utils/ObjectJsonSerializer.java b/src/main/java/net/lensfrex/dscape/utils/ObjectJsonSerializer.java new file mode 100644 index 0000000..bbc0433 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/utils/ObjectJsonSerializer.java @@ -0,0 +1,45 @@ +/* + * Class created by lensfrex. + */ + +package net.lensfrex.dscape.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.stereotype.Component; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +@Component +public class ObjectJsonSerializer { + /** + * 序列化对象到json字符串 + * + * @param obj 待序列化的对象 + * @return 序列化后的数据 + */ + public String serialize(Object obj) { + try { + return new ObjectMapper().registerModule(new JavaTimeModule()).writeValueAsString(obj); + } catch (Exception e) { + return null; + } + } + + /** + * 反序列化对象 + * + * @param data 源数据 + * @return 反序列化后的对象 + */ + public T deserialize(String data, Class valueType) { + try { + return new ObjectMapper().registerModule(new JavaTimeModule()).readValue(data, valueType); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/main/java/net/lensfrex/dscape/utils/ObjectSerializer.java b/src/main/java/net/lensfrex/dscape/utils/ObjectSerializer.java new file mode 100644 index 0000000..8f20e67 --- /dev/null +++ b/src/main/java/net/lensfrex/dscape/utils/ObjectSerializer.java @@ -0,0 +1,48 @@ +/* + * Class created by lensfrex. + */ + +package net.lensfrex.dscape.utils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +@Slf4j +@Component +public class ObjectSerializer { + /** + * 序列化对象到二进制 + * + * @param obj 待序列化的对象 + * @return 序列化后的数据 + */ + public byte[] serialize(Object obj) { + try { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + new ObjectOutputStream(byteArrayOutputStream).writeObject(obj); + + return byteArrayOutputStream.toByteArray(); + } catch (Exception e) { + return null; + } + } + + /** + * 反序列化对象 + * + * @param data 源数据 + * @return 反序列化后的对象 + */ + public Object deserialize(byte[] data) { + try { + return new ObjectInputStream(new ByteArrayInputStream(data)).readObject(); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/main/java/net/lensfrex/dscape/web/controllers/user/UserController.java b/src/main/java/net/lensfrex/dscape/web/controllers/user/UserController.java index d36cce4..8838afb 100644 --- a/src/main/java/net/lensfrex/dscape/web/controllers/user/UserController.java +++ b/src/main/java/net/lensfrex/dscape/web/controllers/user/UserController.java @@ -9,8 +9,11 @@ import cn.dev33.satoken.stp.StpUtil; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import net.lensfrex.dscape.dto.request.UserLoginRequestBody; +import net.lensfrex.dscape.dto.request.user.RegisterRequestBody; import net.lensfrex.dscape.dto.response.general.Response; import net.lensfrex.dscape.dto.response.general.ResponseCode; +import net.lensfrex.dscape.dto.response.user.RegisterResponseBody; +import net.lensfrex.dscape.exception.GlobalException; import net.lensfrex.dscape.web.service.user.UserService; import org.springframework.web.bind.annotation.*; @@ -25,19 +28,30 @@ public class UserController { this.userService = userService; } - @PostMapping(value = "/login" , produces = "application/json") + @PostMapping(value = "/login", produces = "application/json") public Response login(@RequestBody UserLoginRequestBody requestBody) { + if (requestBody == null + || requestBody.getUserName() == null + || requestBody.getPassword() == null) { + + throw new GlobalException(ResponseCode.PARAM_WRONG); + } + return Response.success(userService.login(requestBody)); } - @GetMapping(value = "/checkLogin" , produces = "application/json") - public Response testLogin(@RequestBody UserLoginRequestBody requestBody) { + @GetMapping(value = "/checkLogin", produces = "application/json") + public Response testLogin() { return Response.success(StpUtil.isLogin()); } @PostMapping(value = "/register", produces = "application/json") - public Response register(@RequestBody String body) { - return Response.error(ResponseCode.API_NOT_IMPLEMENT); + public Response register(@RequestBody RegisterRequestBody request) { + if (request.getUserName() == null || request.getPassword() == null) { + throw new GlobalException(ResponseCode.PARAM_WRONG); + } + + return Response.success(userService.register(request)); } @PostMapping(value = "/modifyPassword/{uid}", produces = "application/json") diff --git a/src/main/java/net/lensfrex/dscape/web/service/user/UserService.java b/src/main/java/net/lensfrex/dscape/web/service/user/UserService.java index 900b8e9..527658b 100644 --- a/src/main/java/net/lensfrex/dscape/web/service/user/UserService.java +++ b/src/main/java/net/lensfrex/dscape/web/service/user/UserService.java @@ -6,13 +6,83 @@ package net.lensfrex.dscape.web.service.user; import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.extern.slf4j.Slf4j; +import net.lensfrex.dscape.dao.entity.UserBasic; +import net.lensfrex.dscape.dao.service.UserBasicService; import net.lensfrex.dscape.dto.request.UserLoginRequestBody; +import net.lensfrex.dscape.dto.request.user.RegisterRequestBody; +import net.lensfrex.dscape.dto.response.general.ResponseCode; +import net.lensfrex.dscape.dto.response.user.RegisterResponseBody; +import net.lensfrex.dscape.enums.user.UserStatusEnum; +import net.lensfrex.dscape.exception.GlobalException; +import net.lensfrex.dscape.utils.ObjectJsonSerializer; +import org.mindrot.jbcrypt.BCrypt; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; +@Slf4j @Service public class UserService { + + private static final String USER_INFO_CACHE_KEY = "dscape:user:basic"; + + private final ObjectJsonSerializer objectJsonSerializer; + + private final RedisTemplate redis; + + private final UserBasicService userBasicService; + + @Autowired + public UserService(ObjectJsonSerializer objectJsonSerializer, + RedisTemplate redis, + UserBasicService userBasicService) { + + this.objectJsonSerializer = objectJsonSerializer; + this.redis = redis; + this.userBasicService = userBasicService; + } + public SaTokenInfo login(UserLoginRequestBody requestBody) { - StpUtil.login(requestBody.getUserName()); + String username = requestBody.getUserName(); + String password = requestBody.getPassword(); + UserBasic userBasic; + + if (Boolean.TRUE.equals(redis.hasKey(USER_INFO_CACHE_KEY))) { + String data = (String) redis.opsForHash().get(USER_INFO_CACHE_KEY, username); + userBasic = objectJsonSerializer.deserialize(data, UserBasic.class); + } else { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.lambda() +// .select(UserBasic::getUid, UserBasic::getPassword, UserBasic::getUserName, UserBasic::getStatus) + .eq(UserBasic::getUserName, username) + .eq(UserBasic::getIsDeleted, 0); + + userBasic = userBasicService.getOne(wrapper); + try { + redis.opsForHash().put(USER_INFO_CACHE_KEY, username, objectJsonSerializer.serialize(userBasic)); + } catch (Exception e) { + log.info("将用户数据存入redis缓存时发生错误", e); + } + } + + if (userBasic != null && BCrypt.checkpw(password, userBasic.getPassword())) { + if (userBasic.getStatus() == UserStatusEnum.BANNED.getCode()) { + throw new GlobalException(ResponseCode.USER_WAS_BANNED); + } else if (userBasic.getStatus() == UserStatusEnum.NOT_IDENTIFIED.getCode()) { + throw new GlobalException(ResponseCode.USER_WAS_NOT_IDENTIFIED); + } + + StpUtil.login(requestBody.getUserName()); + } else { + throw new GlobalException(ResponseCode.USERNAME_OR_PASSWORD_WRONG); + } + return StpUtil.getTokenInfo(); } -} + + public RegisterResponseBody register(RegisterRequestBody requestBody) { + return new RegisterResponseBody(); + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 22ccc87..51deb87 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,7 +7,9 @@ server: enabled: false trust-certificate: trust-certificate-private-key: - +logging: + level: + net.lensfrex.dscape: debug spring: datasource: driver-class-name: org.mariadb.jdbc.Driver @@ -39,4 +41,13 @@ sa-token: is-concurrent: true is-share: false token-style: random-64 - is-log: true \ No newline at end of file + is-log: true + +# 性能检测用的,记得在生产环境中不要enable +ko-time: + enable: true + pointcut: execution(public * net.lensfrex.dscape..*.*(..)) + threshold: 250.0 + exception-enable: true + auth-enable: false + log-enable: true