commit 7f06178d2f52703c9c8ac4e6a7dc6514a00fa34d Author: xpecya Date: Thu Dec 5 13:08:22 2024 +0800 完成管理后台用户管理及登陆 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1b939b --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/* +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/admin/pom.xml b/admin/pom.xml new file mode 100644 index 0000000..28d264e --- /dev/null +++ b/admin/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + com.jinrui + reference + 0.0.1-SNAPSHOT + + + admin + + + 8 + 8 + UTF-8 + + + + + com.jinrui + core + 0.0.1-SNAPSHOT + + + redis.clients + jedis + ${jedis.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + diff --git a/admin/src/main/java/com/jinrui/reference/admin/AdminApplication.java b/admin/src/main/java/com/jinrui/reference/admin/AdminApplication.java new file mode 100644 index 0000000..0d9e152 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/AdminApplication.java @@ -0,0 +1,36 @@ +package com.jinrui.reference.admin; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.util.StringUtils; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +@SpringBootApplication(scanBasePackages = { + "com.jinrui.reference.admin", + "com.jinrui.reference.core" +}) +@MapperScan({ + "com.jinrui.reference.admin.mapper", + "com.jinrui.reference.core.mapper"}) +public class AdminApplication { + + public static void main(String[] args) { + SpringApplication.run(AdminApplication.class, args); + } + + @Bean + public JedisPool jedisPool(@Value("${redis.host}") String host, + @Value("${redis.port}") int port, + @Value("${redis.timeout:1000}") int timeout, + @Value("${redis.password:}") String password) { + if (StringUtils.hasText(password)) { + JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); + return new JedisPool(jedisPoolConfig, host, port, timeout, password); + } + return new JedisPool(host, port); + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/controller/AdminUserController.java b/admin/src/main/java/com/jinrui/reference/admin/controller/AdminUserController.java new file mode 100644 index 0000000..cb2775a --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/controller/AdminUserController.java @@ -0,0 +1,215 @@ +package com.jinrui.reference.admin.controller; + +import com.jinrui.reference.admin.model.dto.login.AdminUserBanDTO; +import com.jinrui.reference.admin.model.dto.login.AdminUserCreateDTO; +import com.jinrui.reference.admin.model.dto.login.AdminUserDeleteDTO; +import com.jinrui.reference.admin.model.entity.AdminUser; +import com.jinrui.reference.admin.model.vo.admin.user.AdminUserVO; +import com.jinrui.reference.admin.service.AdminJwtService; +import com.jinrui.reference.admin.service.AdminUserService; +import com.jinrui.reference.core.model.vo.PageObject; +import com.jinrui.reference.core.model.vo.ResultObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Objects; + +@RestController +@RequestMapping("/admin/user") +public class AdminUserController { + + private static final Logger log = LoggerFactory.getLogger(AdminUserController.class); + + private final AdminUserService adminUserService; + + public AdminUserController(AdminUserService adminUserService) { + this.adminUserService = adminUserService; + } + + /** + * 管理后台分页搜索接口 + * + * @param token 登陆Token + * @param name 用户昵称 模糊搜索 + * @param phone 用户手机号 模糊搜索 + * @param page 分页参数 当前页码 默认第一页 + * @param size 分页参数 当前页长度 默认10条 + * @return 分页搜索结果 + */ + @GetMapping + public PageObject queryAdminUser(@RequestHeader("auth-token") String token, + @RequestParam(value = "name", required = false) String name, + @RequestParam(value = "phone", required = false) String phone, + @RequestParam(value = "page", required = false, defaultValue = "1") int page, + @RequestParam(value = "size", required = false, defaultValue = "10") int size) { + if (!StringUtils.hasText(token)) { + return PageObject.failedPage("登陆Token为空!"); + } + + try { + AdminUser adminUser = AdminJwtService.parseToken(token); + if (adminUser == null) { + log.warn("解析token {}拿不到AdminUser对象!", token); + return PageObject.failedPage("登陆Token有误,请联系系统管理员!"); + } + + if (!adminUser.isActive()) { + log.warn("当前用户已被封禁! id = {}", adminUser.getId()); + return PageObject.failedPage("当前用户已被封禁!请联系系统管理员!"); + } + + log.info("path: /admin/user, method: GET, request user id: {}, name: {}, phone: {}, page: {}, size: {}", + adminUser.getId(), name, phone, page, size); + } catch (Exception e) { + log.error("解析登陆Token出错!", e); + return PageObject.failedPage(500, "服务端错误,请联系系统管理员!"); + } + + return adminUserService.findAdminUser(name, phone, page, size); + } + + /** + * 管理后台用户封禁接口 + * + * @param token 登陆Token + * @param adminUserBanDTO 要封禁的用户ID + * @return 封禁结果 + */ + @PostMapping("/ban") + public ResultObject ban(@RequestHeader("auth-token") String token, + @RequestBody AdminUserBanDTO adminUserBanDTO) { + if (!StringUtils.hasText(token)) { + return ResultObject.failed("登陆Token为空!"); + } + + Long id = adminUserBanDTO.getId(); + if (id == null) { + log.warn("要封禁的用户ID为空!"); + return ResultObject.failed("要封禁的用户ID为空!"); + } + + try { + AdminUser adminUser = AdminJwtService.parseToken(token); + if (adminUser == null) { + log.warn("解析token {}拿不到AdminUser对象!", token); + return ResultObject.failed("登陆Token有误,请联系系统管理员!"); + } + + if (!adminUser.isActive()) { + log.warn("当前用户已被封禁! id = {}", adminUser.getId()); + return ResultObject.failed("当前用户已被封禁!请联系系统管理员!"); + } + + Long adminUserId = adminUser.getId(); + if (Objects.equals(adminUserId, id)) { + log.warn("用户(id = {})尝试自己封禁自己,已禁止该操作", id); + return ResultObject.failed("请勿自己封禁自己!"); + } + + log.info("path: /admin/user/ban, method: POST, request user id: {}, ban user id: {}", adminUserId, id); + } catch (Exception e) { + log.error("解析登陆Token出错!", e); + return ResultObject.failed(500, "服务端错误,请联系系统管理员!"); + } + + return adminUserService.ban(id); + } + + /** + * 管理后台删除用户接口 + * + * @param token 登陆Token + * @param adminUserDeleteDTO 要删除的用户ID + * @return 删除结果 + */ + @DeleteMapping + public ResultObject delete(@RequestHeader("auth-token") String token, + @RequestBody AdminUserDeleteDTO adminUserDeleteDTO) { + if (!StringUtils.hasText(token)) { + return ResultObject.failed("登陆Token为空!"); + } + + Long id = adminUserDeleteDTO.getId(); + if (id == null) { + log.warn("要删除的用户ID为空!"); + return ResultObject.failed("要删除的用户ID为空!"); + } + + try { + AdminUser adminUser = AdminJwtService.parseToken(token); + if (adminUser == null) { + log.warn("解析token {}拿不到AdminUser对象!", token); + return ResultObject.failed("登陆Token有误,请联系系统管理员!"); + } + + if (!adminUser.isActive()) { + log.warn("当前用户已被封禁! id = {}", adminUser.getId()); + return ResultObject.failed("当前用户已被封禁!请联系系统管理员!"); + } + + Long adminUserId = adminUser.getId(); + if (Objects.equals(adminUserId, id)) { + log.warn("用户(id = {})尝试自己删除自己,已禁止该操作", id); + return ResultObject.failed("请勿自己删除自己!"); + } + + log.info("path: /admin/user, method: DELETE, request user id: {}, delete user id: {}", adminUserId, id); + } catch (Exception e) { + log.error("解析登陆Token出错!", e); + return ResultObject.failed(500, "服务端错误,请联系系统管理员!"); + } + + return adminUserService.delete(id); + } + + /** + * 管理后台创建用户接口 + * + * @param token 登陆Token + * @param adminUserCreateDTO 要创建的用户昵称及手机号 + * @return 创建结果 + */ + @PostMapping("/create") + public ResultObject createUser(@RequestHeader("auth-token") String token, + @RequestBody AdminUserCreateDTO adminUserCreateDTO) { + if (!StringUtils.hasText(token)) { + return ResultObject.failed("登陆Token为空!"); + } + + String phone = adminUserCreateDTO.getPhone(); + if (!StringUtils.hasText(phone)) { + return ResultObject.failed("手机号不可为空!"); + } + + String name = adminUserCreateDTO.getName(); + try { + AdminUser adminUser = AdminJwtService.parseToken(token); + if (adminUser == null) { + log.warn("解析token {}拿不到AdminUser对象!", token); + return ResultObject.failed("登陆Token有误,请联系系统管理员!"); + } + + if (!adminUser.isActive()) { + log.warn("当前用户已被封禁! id = {}", adminUser.getId()); + return ResultObject.failed("当前用户已被封禁!请联系系统管理员!"); + } + + log.info("path: /admin/user/create, method: POST, request user id: {}, name: {}, phone: {}", + adminUser.getId(), name, phone); + } catch (Exception e) { + log.error("解析登陆Token出错!", e); + return ResultObject.failed(500, "服务端错误,请联系系统管理员!"); + } + + return adminUserService.create(name, phone); + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/controller/LoginController.java b/admin/src/main/java/com/jinrui/reference/admin/controller/LoginController.java new file mode 100644 index 0000000..2a21d36 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/controller/LoginController.java @@ -0,0 +1,47 @@ +package com.jinrui.reference.admin.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jinrui.reference.admin.model.dto.login.LoginDTO; +import com.jinrui.reference.admin.model.dto.login.SendCaptchaDTO; +import com.jinrui.reference.admin.model.vo.login.LoginVO; +import com.jinrui.reference.admin.service.AdminUserService; +import com.jinrui.reference.core.controller.BaseController; +import com.jinrui.reference.core.model.vo.ResultObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/login") +public class LoginController extends BaseController { + + private static final Logger log = LoggerFactory.getLogger(LoginController.class); + + private final AdminUserService adminUserService; + + public LoginController(ObjectMapper objectMapper, + AdminUserService adminUserService) { + super(objectMapper); + this.adminUserService = adminUserService; + } + + @PostMapping("/captcha") + public ResultObject sendCaptcha(@RequestBody SendCaptchaDTO sendCaptchaDTO) { + String phone = sendCaptchaDTO.getPhone(); + log.info("path: /login/captcha, phone: {}", phone); + ResultObject resultObject = adminUserService.sendCaptcha(phone); + super.logResponse(resultObject); + return resultObject; + } + + @PostMapping + public ResultObject login(@RequestBody LoginDTO loginDTO) { + log.info("path: /login, phone: {}, captcha: {}", loginDTO.getPhone(), loginDTO.getCaptcha()); + ResultObject resultObject = adminUserService.login(loginDTO); + super.logResponse(resultObject); + return resultObject; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/mapper/AdminUserMapper.java b/admin/src/main/java/com/jinrui/reference/admin/mapper/AdminUserMapper.java new file mode 100644 index 0000000..eaac801 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/mapper/AdminUserMapper.java @@ -0,0 +1,68 @@ +package com.jinrui.reference.admin.mapper; + +import com.jinrui.reference.admin.model.entity.AdminUser; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; +import org.apache.ibatis.type.JdbcType; + +import java.util.Date; +import java.util.List; + +public interface AdminUserMapper { + + @Results({ + @Result(column = "id", property = "id", id = true), + @Result(column = "phone", property = "phone"), + @Result(column = "name", property = "name"), + @Result(column = "active", property = "active"), + @Result(column = "create_time", property = "createTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP), + @Result(column = "update_time", property = "updateTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP) + }) + @Select("select * from admin_user where phone = #{phone}") + AdminUser getAdminUserByPhone(@Param("phone") String phone); + + @Results({ + @Result(column = "id", property = "id", id = true), + @Result(column = "phone", property = "phone"), + @Result(column = "name", property = "name"), + @Result(column = "active", property = "active"), + @Result(column = "create_time", property = "createTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP), + @Result(column = "update_time", property = "updateTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP) + }) + @Select("") + List queryAdminUser(@Param("name") String name, @Param("phone") String phone); + + @Update("update admin_user set active = 0, update_time = now() where id = #{id}") + void ban(@Param("id") long id); + + @Delete("delete from admin_user where id = #{id}") + void delete(@Param("id") long id); + + @Insert("") + void create(@Param("name") String name, @Param("phone") String phone); +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserBanDTO.java b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserBanDTO.java new file mode 100644 index 0000000..0b2f793 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserBanDTO.java @@ -0,0 +1,20 @@ +package com.jinrui.reference.admin.model.dto.login; + +/** + * 管理后台禁用用户DTO + */ +public class AdminUserBanDTO { + + /** + * 被禁用的用户ID + */ + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserCreateDTO.java b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserCreateDTO.java new file mode 100644 index 0000000..f403c60 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserCreateDTO.java @@ -0,0 +1,33 @@ +package com.jinrui.reference.admin.model.dto.login; + +/** + * 管理后台创建用户DTO + */ +public class AdminUserCreateDTO { + + /** + * 用户昵称 + */ + private String name; + + /** + * 用户手机号 不可为空 + */ + private String phone; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserDeleteDTO.java b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserDeleteDTO.java new file mode 100644 index 0000000..19b97e8 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/AdminUserDeleteDTO.java @@ -0,0 +1,20 @@ +package com.jinrui.reference.admin.model.dto.login; + +/** + * 管理后台删除用户DTO + */ +public class AdminUserDeleteDTO { + + /** + * 被删除的用户ID + */ + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/LoginDTO.java b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/LoginDTO.java new file mode 100644 index 0000000..7d0b31c --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/LoginDTO.java @@ -0,0 +1,25 @@ +package com.jinrui.reference.admin.model.dto.login; + +@SuppressWarnings("unused") +public class LoginDTO { + + private String phone; + + private String captcha; + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getCaptcha() { + return captcha; + } + + public void setCaptcha(String captcha) { + this.captcha = captcha; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/SendCaptchaDTO.java b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/SendCaptchaDTO.java new file mode 100644 index 0000000..9ae5920 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/model/dto/login/SendCaptchaDTO.java @@ -0,0 +1,15 @@ +package com.jinrui.reference.admin.model.dto.login; + +@SuppressWarnings("unused") +public class SendCaptchaDTO { + + private String phone; + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/model/entity/AdminUser.java b/admin/src/main/java/com/jinrui/reference/admin/model/entity/AdminUser.java new file mode 100644 index 0000000..f42eeb0 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/model/entity/AdminUser.java @@ -0,0 +1,125 @@ +package com.jinrui.reference.admin.model.entity; + +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; + +import java.util.Date; +import java.util.Map; + +/** + * 管理后台用户 + */ +@SuppressWarnings("unused") +public class AdminUser { + + /** + * 用户ID + */ + private Long id; + + /** + * 用户手机号 + */ + private String phone; + + /** + * 用户名称 + */ + private String name; + + /** + *

当前用户状态 是否启用

+ * true - 启动 | false - 禁用 + */ + private boolean active; + + /** + * 用户创建时间 + */ + private Date createTime; + + /** + * 用户修改时间 + */ + private Date updateTime; + + public AdminUser() {} + + public AdminUser(DecodedJWT decodedJWT) { + for (Map.Entry entry : decodedJWT.getClaims().entrySet()) { + String keyName = entry.getKey(); + Claim value = entry.getValue(); + switch (keyName) { + case "id": { + this.id = value.asLong(); + break; + } + case "phone": { + this.phone = value.asString(); + break; + } + case "name": { + this.name = value.asString(); + break; + } + case "createTime": { + this.createTime = new Date(value.asLong()); + break; + } + case "updateTime": { + this.updateTime = new Date(value.asLong()); + break; + } + } + } + this.active = true; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/model/vo/admin/user/AdminUserVO.java b/admin/src/main/java/com/jinrui/reference/admin/model/vo/admin/user/AdminUserVO.java new file mode 100644 index 0000000..66aa7f8 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/model/vo/admin/user/AdminUserVO.java @@ -0,0 +1,103 @@ +package com.jinrui.reference.admin.model.vo.admin.user; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.jinrui.reference.admin.model.entity.AdminUser; + +import java.util.Date; + +/** + * 管理后台用户 + */ +@SuppressWarnings("unused") +public class AdminUserVO { + + /** + * 用户ID + */ + private Long id; + + /** + * 用户手机号 + */ + private String phone; + + /** + * 用户名称 + */ + private String name; + + /** + *

当前用户状态 是否启用

+ * true - 启动 | false - 禁用 + */ + private boolean active; + + /** + * 用户创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** + * 用户修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + public AdminUserVO(AdminUser adminUser) { + this.id = adminUser.getId(); + this.phone = adminUser.getPhone(); + this.name = adminUser.getName(); + this.active = adminUser.isActive(); + this.createTime = adminUser.getCreateTime(); + this.updateTime = adminUser.getUpdateTime(); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/model/vo/login/LoginVO.java b/admin/src/main/java/com/jinrui/reference/admin/model/vo/login/LoginVO.java new file mode 100644 index 0000000..0faecf3 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/model/vo/login/LoginVO.java @@ -0,0 +1,103 @@ +package com.jinrui.reference.admin.model.vo.login; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.jinrui.reference.admin.model.entity.AdminUser; +import com.jinrui.reference.admin.service.AdminJwtService; + +import java.util.Date; + +/** + * 登陆返回值 + */ +@SuppressWarnings("unused") +public class LoginVO { + + /** + * 用户ID + */ + private Long id; + + /** + * 用户手机号 + */ + private String phone; + + /** + * 用户昵称 + */ + private String name; + + /** + * 用户登陆Token + */ + private String token; + + /** + * 用户创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** + * 用户修改时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + public LoginVO(AdminUser adminUser) { + this.id = adminUser.getId(); + this.phone = adminUser.getPhone(); + this.name = adminUser.getName(); + this.token = AdminJwtService.generateToken(adminUser); + this.createTime = adminUser.getCreateTime(); + this.updateTime = adminUser.getUpdateTime(); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/service/AdminJwtService.java b/admin/src/main/java/com/jinrui/reference/admin/service/AdminJwtService.java new file mode 100644 index 0000000..191cea3 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/service/AdminJwtService.java @@ -0,0 +1,62 @@ +package com.jinrui.reference.admin.service; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTCreator; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.jinrui.reference.admin.model.entity.AdminUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class AdminJwtService { + + private static final Logger log = LoggerFactory.getLogger(AdminJwtService.class); + private static final String SECRET = "R!E@F#E$R%E^N&C*E"; + + private AdminJwtService() {} + + /** + * 管理后台根据用户对象生成JWT TOKEN + * + * @param adminUser 管理后台用户对象 + * @return JWT TOKEN + */ + public static String generateToken(AdminUser adminUser) { + Long id = adminUser.getId(); + String phone = adminUser.getPhone(); + String name = adminUser.getName(); + long createTime = adminUser.getCreateTime().getTime(); + long updateTime = adminUser.getUpdateTime().getTime(); + JWTCreator.Builder jwtBuilder = JWT.create(); + jwtBuilder.withClaim("id", id); + jwtBuilder.withClaim("phone", phone); + jwtBuilder.withClaim("name", name); + jwtBuilder.withClaim("createTime", createTime); + jwtBuilder.withClaim("updateTime", updateTime); + jwtBuilder.withClaim("timestamp", System.currentTimeMillis()); + return jwtBuilder.sign(Algorithm.HMAC256(SECRET)); + } + + public static AdminUser parseToken(String token) { + if (token == null) { + throw new NullPointerException("token is null!"); + } + JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)) + .withClaimPresence("id") + .withClaimPresence("phone") + .withClaimPresence("name") + .withClaimPresence("createTime") + .withClaimPresence("updateTime") + .withClaimPresence("timestamp") + .build(); + try { + DecodedJWT decodedJWT = jwtVerifier.verify(token); + return new AdminUser(decodedJWT); + } catch (JWTVerificationException e) { + log.error("error in verifying token!", e); + } + return null; + } +} diff --git a/admin/src/main/java/com/jinrui/reference/admin/service/AdminUserService.java b/admin/src/main/java/com/jinrui/reference/admin/service/AdminUserService.java new file mode 100644 index 0000000..d62bf95 --- /dev/null +++ b/admin/src/main/java/com/jinrui/reference/admin/service/AdminUserService.java @@ -0,0 +1,288 @@ +package com.jinrui.reference.admin.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jinrui.reference.admin.mapper.AdminUserMapper; +import com.jinrui.reference.admin.model.dto.login.LoginDTO; +import com.jinrui.reference.admin.model.entity.AdminUser; +import com.jinrui.reference.admin.model.vo.admin.user.AdminUserVO; +import com.jinrui.reference.admin.model.vo.login.LoginVO; +import com.jinrui.reference.core.model.vo.PageObject; +import com.jinrui.reference.core.model.vo.ResultObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +import java.util.List; +import java.util.Objects; +import java.util.Random; +import java.util.stream.Collectors; + +@Service +public class AdminUserService { + + private static final String REDIS_LOGIN_LOCK_KEY = "login-lock-"; + private static final String REDIS_KEY_SEND_CAPTCHA_TO_PREFIX = "send-captcha-to-"; + private static final String REDIS_KEY_CAPTCHA = "login-captcha-"; + private static final Logger log = LoggerFactory.getLogger(AdminUserService.class); + + private final JedisPool jedisPool; + private final AdminUserMapper adminUserMapper; + private final ObjectMapper objectMapper; + + public AdminUserService(JedisPool jedisPool, + AdminUserMapper adminUserMapper, + ObjectMapper objectMapper) { + this.jedisPool = jedisPool; + this.adminUserMapper = adminUserMapper; + this.objectMapper = objectMapper; + } + + /** + *

给指定手机号发送验证码,如果不是系统中已有的手机号则不发送,被禁用的账号不发送

+ *

同一个手机号60秒之内只能发送一封验证码短信,验证码有效期10分钟

+ * + * @param phone 要发送验证码的手机号 + */ + public ResultObject sendCaptcha(String phone) { + if (!StringUtils.hasText(phone)) { + return ResultObject.failed("手机号为空!"); + } + + String redisLockKey = getLoginLockKey(phone); + try (Jedis jedis = jedisPool.getResource()) { + long incrResult = jedis.incr(redisLockKey); + if (incrResult > 1) { + jedis.decr(redisLockKey); + return ResultObject.failed("系统繁忙,请稍后再试!"); + } + jedis.expire(redisLockKey, 3L); + + String redisCaptchaKey = getRedisCaptchaKey(phone); + incrResult = jedis.incr(redisCaptchaKey); + if (incrResult > 1) { + log.warn("手机号{}在一分钟内已发送过短信,请勿重复发送!", phone); + jedis.decr(redisLockKey); + jedis.decr(redisCaptchaKey); + return ResultObject.failed("该手机号一分钟内已发送过短信,请勿重复发送!"); + } + jedis.expire(redisCaptchaKey, 60L); + + AdminUser adminUser = adminUserMapper.getAdminUserByPhone(phone); + if (adminUser == null) { + String errorMessage = String.format("找不到手机号为%s的用户!", phone); + log.warn(errorMessage); + jedis.decr(redisLockKey); + return ResultObject.failed(errorMessage); + } + if (!adminUser.isActive()) { + log.warn("被禁用的用户(phone = {})尝试登陆!", phone); + jedis.decr(redisLockKey); + return ResultObject.failed("当前用户已被禁用,请联系系统管理员!"); + } + + String randomCaptcha = randomCaptcha(); + log.info("记录手机号{}的登陆验证码: {}", phone, randomCaptcha); + String redisCaptchaListKey = getRedisCaptchaListKey(phone); + String captchaList = jedis.get(redisCaptchaListKey); + if (!StringUtils.hasText(captchaList) || "nil".equals(captchaList)) { + captchaList = randomCaptcha; + } else { + captchaList += ("," + randomCaptcha); + } + log.info("手机号{}当前的验证码列表: {}", phone, captchaList); + jedis.set(redisCaptchaListKey, captchaList); + jedis.expire(redisCaptchaListKey, 600L); + jedis.decr(redisLockKey); + return ResultObject.success(randomCaptcha); + } catch (Exception e) { + log.error("sendCaptcha异常!", e); + return ResultObject.failed(500, "服务端错误,请联系系统管理员!"); + } + } + + /** + * 根据验证码进行登陆,登陆后给当前手机发送的所有验证码无效 + * + * @param loginDTO 登陆参数 + * @return 登陆结果 + */ + public ResultObject login(LoginDTO loginDTO) { + String phone = loginDTO.getPhone(); + if (!StringUtils.hasText(phone)) { + return ResultObject.failed("手机号为空!"); + } + String captcha = loginDTO.getCaptcha(); + if (!StringUtils.hasText(captcha)) { + return ResultObject.failed("验证码为空!"); + } + int captchaLength = captcha.length(); + if (captchaLength != 6) { + log.warn("手机号{}登陆时试图使用错误的验证码{}", phone, captcha); + return ResultObject.failed("验证码错误,请重新输入!"); + } + + String redisLockKey = getLoginLockKey(phone); + try (Jedis jedis = jedisPool.getResource()) { + long incrResult = jedis.incr(redisLockKey); + if (incrResult > 1) { + jedis.decr(redisLockKey); + return ResultObject.failed("系统繁忙,请稍后再试!"); + } + jedis.expire(redisLockKey, 3L); + + String redisCaptchaListKey = getRedisCaptchaListKey(phone); + String captchaList = jedis.get(redisCaptchaListKey); + if (!StringUtils.hasText(captchaList)) { + log.warn("没有找到给手机号{}发送的验证码!", phone); + jedis.decr(redisLockKey); + return ResultObject.failed("验证码错误,请重新输入!"); + } + + String[] split = captchaList.split(","); + for (String available : split) { + if (Objects.equals(captcha, available)) { + log.info("手机号{}验证码校验成功!", phone); + AdminUser adminUser = adminUserMapper.getAdminUserByPhone(phone); + if (adminUser == null) { + return ResultObject.failed("用户不存在,请联系系统管理员!"); + } + if (!adminUser.isActive()) { + return ResultObject.failed("用户已被禁用,请联系系统管理员!"); + } + LoginVO loginVO = new LoginVO(adminUser); + jedis.del(redisLockKey, redisCaptchaListKey); + return ResultObject.success(loginVO); + } + } + log.info("没有给手机{}发送过验证码{}, 已发送过的验证码是[{}]", phone, captcha, captchaList); + jedis.decr(redisLockKey); + return ResultObject.failed("验证码错误,请重新输入!"); + } catch (Exception e) { + log.error("login错误!", e); + return ResultObject.failed(500, "服务端错误,请联系系统管理员!"); + } + } + + /** + * 查询管理后台用户 + * + * @param name 用户名 模糊匹配 + * @param phone 手机号 模糊匹配 + * @param page 当前页码 默认第一页 + * @param size 每页长度 默认10条 + * @return 查询结果 + */ + public PageObject findAdminUser(String name, String phone, int page, int size) { + List resultList = adminUserMapper.queryAdminUser(name, phone); + if (CollectionUtils.isEmpty(resultList)) { + return PageObject.empty(page); + } + + PageObject pageObject = new PageObject<>(); + pageObject.setTotal(resultList.size()); + List responseList = resultList.stream() + .skip((long) (page - 1) * size) + .limit(size) + .map(AdminUserVO::new) + .collect(Collectors.toList()); + pageObject.setCurrent(page); + pageObject.setSize(Math.min(size, resultList.size())); + pageObject.setCode(200); + pageObject.setData(responseList); + + try { + String pageString = objectMapper.writeValueAsString(pageObject); + log.info("查询管理后台结果: {}", pageString); + } catch (JsonProcessingException e) { + log.error("查询用户返回分页对象json映射报错!", e); + } + return pageObject; + } + + /** + * 管理后台封禁用户接口 + * + * @param id 要封禁的用户ID + * @return 封禁结果 + */ + public ResultObject ban(Long id) { + try { + adminUserMapper.ban(id); + } catch (Exception e) { + log.error("ban错误!", e); + return ResultObject.failed(500, "服务端错误!请联系系统管理员!"); + } + return ResultObject.success(); + } + + /** + * 管理后台删除用户接口 + * + * @param id 要删除的用户ID + * @return 删除结果 + */ + public ResultObject delete(Long id) { + try { + adminUserMapper.delete(id); + } catch (Exception e) { + log.error("delete错误!", e); + return ResultObject.failed(500, "服务端错误!请联系系统管理员!"); + } + + return ResultObject.success(); + } + + public ResultObject create(String name, String phone) { + try { + AdminUser adminUser = adminUserMapper.getAdminUserByPhone(phone); + if (adminUser != null) { + log.warn("手机号{}已被注册!", phone); + return ResultObject.failed("手机号已存在,请更换"); + } + } catch (Exception e) { + log.error("根据手机号查询用户出错!", e); + return ResultObject.failed(500, "服务端错误!请联系系统管理员!"); + } + + try { + adminUserMapper.create(name, phone); + } catch (Exception e) { + log.error("注册用户报错!", e); + return ResultObject.failed(500, "服务端错误!请联系系统管理员!"); + } + + return ResultObject.success(); + } + + private static String getRedisCaptchaKey(String phone) { + return REDIS_KEY_SEND_CAPTCHA_TO_PREFIX + phone; + } + + private static String getRedisCaptchaListKey(String phone) { + return REDIS_KEY_CAPTCHA + phone; + } + + /** + * 生成随机六位数字验证码 + * + * @return 数字验证码 + */ + private static String randomCaptcha() { + StringBuilder stringBuilder = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < 6; i++) { + int nextInt = random.nextInt(10); + stringBuilder.append(nextInt); + } + return stringBuilder.toString(); + } + + private static String getLoginLockKey(String phone) { + return REDIS_LOGIN_LOCK_KEY + phone; + } +} diff --git a/admin/src/main/resources/application.yml b/admin/src/main/resources/application.yml new file mode 100644 index 0000000..4fb8955 --- /dev/null +++ b/admin/src/main/resources/application.yml @@ -0,0 +1,22 @@ +server: + port: 13579 +oss: + ak: LTAI5t8z9QNdCG6b54mDgx8p + sk: F3M41hTgH8g99ZgVWyelj42825YbZM + roleArn: acs:ram::1647420045565932:role/ramoss + endPoint: oss-cn-hangzhou.aliyuncs.com + region: oss-cn-hangzhou + bucketName: lengfeng-test + baseUrl: https://lengfeng-test.oss-cn-hangzhou.aliyuncs.com + sts: + endPoint: sts.cn-hangzhou.aliyuncs.com +spring: + datasource: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/reference?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&allowMultiQueries=true + username: root + password: Aa123456@ +redis: + host: 127.0.0.1 + port: 6379 diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..64ae0ba --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + com.jinrui + reference + 0.0.1-SNAPSHOT + + + core + + + 8 + 8 + UTF-8 + 1.70 + 4.4.0 + + + + + com.aliyun.oss + aliyun-sdk-oss + 3.17.4 + + + com.fasterxml.jackson.core + jackson-annotations + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + com.mysql + mysql-connector-j + + + com.zaxxer + HikariCP + + + com.auth0 + java-jwt + ${jwt.version} + + + commons-codec + commons-codec + + + org.bouncycastle + bcutil-jdk15on + ${bouncycastle.version} + + + + diff --git a/core/src/main/java/com/jinrui/reference/core/WebConfig.java b/core/src/main/java/com/jinrui/reference/core/WebConfig.java new file mode 100644 index 0000000..711dca8 --- /dev/null +++ b/core/src/main/java/com/jinrui/reference/core/WebConfig.java @@ -0,0 +1,21 @@ +package com.jinrui.reference.core; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + /** + * 跨域访问支持 + */ + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH") + .maxAge(3600); + } +} diff --git a/core/src/main/java/com/jinrui/reference/core/controller/BaseController.java b/core/src/main/java/com/jinrui/reference/core/controller/BaseController.java new file mode 100644 index 0000000..945420f --- /dev/null +++ b/core/src/main/java/com/jinrui/reference/core/controller/BaseController.java @@ -0,0 +1,27 @@ +package com.jinrui.reference.core.controller; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jinrui.reference.core.model.vo.ResultObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class BaseController { + + private static final Logger log = LoggerFactory.getLogger(BaseController.class); + + private final ObjectMapper objectMapper; + + protected BaseController(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + protected void logResponse(ResultObject resultObject) { + try { + String resultString = objectMapper.writeValueAsString(resultObject); + log.info("result: {}", resultString); + } catch (JsonProcessingException e) { + log.error("error in parsing result object into string!", e); + } + } +} diff --git a/core/src/main/java/com/jinrui/reference/core/model/vo/PageObject.java b/core/src/main/java/com/jinrui/reference/core/model/vo/PageObject.java new file mode 100644 index 0000000..3782713 --- /dev/null +++ b/core/src/main/java/com/jinrui/reference/core/model/vo/PageObject.java @@ -0,0 +1,72 @@ +package com.jinrui.reference.core.model.vo; + +import java.util.ArrayList; +import java.util.List; + +/** + * 分页对象 + * + * @param 返回值类型 + */ +public class PageObject extends ResultObject> { + + /** + * 分页页码 默认从1开始 + */ + private int current; + + /** + * 分页长度 默认为10 + */ + private int size; + + /** + * 数据总数 + */ + private int total; + + public static PageObject empty(int page) { + PageObject pageObject = new PageObject<>(); + pageObject.setCode(200); + pageObject.setCurrent(page); + pageObject.setSize(0); + pageObject.setTotal(0); + pageObject.setData(new ArrayList<>()); + return pageObject; + } + + public static PageObject failedPage(int code, String message) { + PageObject pageObject = new PageObject<>(); + pageObject.setCode(code); + pageObject.setMsg(message); + return pageObject; + } + + public static PageObject failedPage(String message) { + return failedPage(400, message); + } + + public int getCurrent() { + return current; + } + + public void setCurrent(int current) { + this.current = current; + } + + public int getSize() { + return size; + } + + public void setSize(int size) { + this.size = size; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } +} diff --git a/core/src/main/java/com/jinrui/reference/core/model/vo/ResultObject.java b/core/src/main/java/com/jinrui/reference/core/model/vo/ResultObject.java new file mode 100644 index 0000000..766e511 --- /dev/null +++ b/core/src/main/java/com/jinrui/reference/core/model/vo/ResultObject.java @@ -0,0 +1,94 @@ +package com.jinrui.reference.core.model.vo; + +/** + * 通用返回结构 + * + * @param 返回对象类型 + */ +@SuppressWarnings("unused") +public class ResultObject { + + /** + * 状态码 + */ + private int code; + + /** + * 错误信息 + */ + private String msg; + + /** + * 返回对象 + */ + private T data; + + /** + * 查询请求成功返回 + * @param data 请求返回值 + * @return 返回结构体 + * @param 返回值类型 + */ + public static ResultObject success(T data) { + ResultObject resultObject = new ResultObject<>(); + resultObject.code = 200; + resultObject.data = data; + return resultObject; + } + + /** + * 修改请求成功返回 + * @return 返回结构体 + * @param 返回值类型 + */ + public static ResultObject success() { + return success(null); + } + + /** + * 前端参数错误返回 + * @param msg 错误信息 + * @return 返回结构体 + * @param 返回值类型 + */ + public static ResultObject failed(String msg) { + return failed(400, msg); + } + + /** + * 自定义状态码错误返回 + * @param msg 错误信息 + * @return 返回结构体 + * @param 返回值类型 + */ + public static ResultObject failed(int code, String msg) { + ResultObject resultObject = new ResultObject<>(); + resultObject.code = code; + resultObject.msg = msg; + return resultObject; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/core/src/main/java/com/jinrui/reference/core/service/JwtService.java b/core/src/main/java/com/jinrui/reference/core/service/JwtService.java new file mode 100644 index 0000000..88ea7d8 --- /dev/null +++ b/core/src/main/java/com/jinrui/reference/core/service/JwtService.java @@ -0,0 +1,105 @@ +//package com.jinrui.reference.core.service; +// +//import com.auth0.jwt.JWT; +//import com.auth0.jwt.JWTCreator; +//import com.auth0.jwt.JWTVerifier; +//import com.auth0.jwt.algorithms.Algorithm; +//import com.auth0.jwt.exceptions.JWTVerificationException; +//import com.auth0.jwt.interfaces.Claim; +//import com.auth0.jwt.interfaces.DecodedJWT; +// +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.stereotype.Service; +//import org.springframework.util.StringUtils; +// +//@Service +//public class JwtService { +// +// private static final Logger log = LoggerFactory.getLogger(JwtService.class); +// private static final String SECRET = "R!E@F#E$R%E^N&C*E"; +// +// /** +// * 管理后台根据用户对象生成JWT TOKEN +// * @param adminUser 管理后台用户对象 +// * @return JWT TOKEN +// */ +// public String generateToken(AdminUser adminUser) { +// Long id = adminUser.getId(); +// String username = adminUser.getUsername(); +// JWTCreator.Builder jwtBuilder = JWT.create(); +// jwtBuilder.withClaim("username", username); +// jwtBuilder.withClaim("id", id); +// jwtBuilder.withClaim("timestamp", System.currentTimeMillis()); +// return jwtBuilder.sign(Algorithm.HMAC256(SECRET)); +// } +// +// /** +// * 微信小程序根据用户对象生成JWT TOKEN +// * @param miniUser 小程序用户对象 +// * @return JWT TOKEN +// */ +// public String generateToken(MiniUser miniUser) { +// Long id = miniUser.getId(); +// String phone = miniUser.getPhone(); +// JWTCreator.Builder jwtBuilder = JWT.create(); +// jwtBuilder.withClaim("phone", phone); +// jwtBuilder.withClaim("id", id); +// jwtBuilder.withClaim("timestamp", System.currentTimeMillis()); +// return jwtBuilder.sign(Algorithm.HMAC256(SECRET)); +// } +// +// /** +// * 管理后台校验JWT TOKEN +// * @param token token +// * @return 校验结果 +// */ +// public AdminUser verify(String token) { +// if (!StringUtils.hasText(token)) { +// log.warn("管理后台token为空!"); +// return null; +// } +// JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)) +// .withClaimPresence("username") +// .withClaimPresence("id") +// .withClaimPresence("timestamp") +// .build(); +// try { +// DecodedJWT decodedJWT = jwtVerifier.verify(token); +// Claim claim = decodedJWT.getClaim("id"); +// Long adminUserId = claim.asLong(); +// log.info("JWT解析成功,管理后台用户ID: {}", adminUserId); +// return adminUserMapper.getById(adminUserId); +// } catch (JWTVerificationException e) { +// log.error("JWT解析异常!token: {}", token, e); +// return null; +// } +// } +// +// /** +// * 小程序校验JWT TOKEN +// * @param token token +// * @return 校验结果 +// */ +// public MiniUser verifyMini(String token) { +// if (!StringUtils.hasText(token)) { +// log.warn("小程序token为空!"); +// return null; +// } +// JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)) +// .withClaimPresence("phone") +// .withClaimPresence("id") +// .withClaimPresence("timestamp") +// .build(); +// try { +// DecodedJWT decodedJWT = jwtVerifier.verify(token); +// Claim claim = decodedJWT.getClaim("id"); +// Long miniUserId = claim.asLong(); +// log.info("JWT解析成功,小程序用户ID: {}", miniUserId); +// return miniUserMapper.getById(miniUserId); +// } catch (JWTVerificationException e) { +// log.error("JWT解析异常!token: {}", token, e); +// return null; +// } +// } +//} diff --git a/mini/pom.xml b/mini/pom.xml new file mode 100644 index 0000000..870b413 --- /dev/null +++ b/mini/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.jinrui + reference + 0.0.1-SNAPSHOT + + + mini + + + 8 + 8 + UTF-8 + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5bdd7d3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + pom + + admin + mini + core + + + + org.springframework.boot + spring-boot-starter-parent + 2.7.18 + + + + + 1.8 + UTF-8 + 2.3.2 + + + com.jinrui + reference + 0.0.1-SNAPSHOT + reference + + + + hejiuxiaofendui-flexible-wesley + wesley + https://hejiuxiaofendui-maven.pkg.coding.net/repository/flexible/wesley/ + + true + + + true + + + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + + + compile + + + + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + true + + + + +