Browse Source

1、登录接口新增验证码、记住我字段

machaoyi 1 year ago
parent
commit
41e8efdef8

+ 18 - 10
.idea/workspace.xml

@@ -4,15 +4,14 @@
     <option name="autoReloadType" value="SELECTIVE" />
   </component>
   <component name="ChangeListManager">
-    <list default="true" id="1dc46973-e6f5-473b-a131-bf2bbc2dca15" name="更改" comment="1、获取用户菜单排序">
-      <change afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/Auth/entity/UpdatePasswordVO.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/Auth/web/password.java" afterDir="false" />
-      <change afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/utils/PasswordUtils.java" afterDir="false" />
+    <list default="true" id="1dc46973-e6f5-473b-a131-bf2bbc2dca15" name="更改" comment="1、用户修改密码">
+      <change afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/Enum/ErrorCodeEnum.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/utils/CaptchaUtil.java" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/application/src/main/java/com/ctsi/Auth/entity/UserForm.java" beforeDir="false" afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/Auth/entity/UserForm.java" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/application/src/main/java/com/ctsi/Auth/web/login.java" beforeDir="false" afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/Auth/web/login.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/application/src/main/java/com/ctsi/System/SysUser/entity/VO/UserAddVO.java" beforeDir="false" afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/System/SysUser/entity/VO/UserAddVO.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/application/src/main/java/com/ctsi/System/SysUser/service/SysUserService.java" beforeDir="false" afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/System/SysUser/service/SysUserService.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/application/src/main/java/com/ctsi/System/SysUser/service/impl/SysUserServiceImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/System/SysUser/service/impl/SysUserServiceImpl.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/application/src/main/java/com/ctsi/config/SaTokenConfigure.java" beforeDir="false" afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/config/SaTokenConfigure.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/application/src/main/java/com/ctsi/utils/ApiResult.java" beforeDir="false" afterPath="$PROJECT_DIR$/application/src/main/java/com/ctsi/utils/ApiResult.java" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/application/src/main/resources/application.yml" beforeDir="false" afterPath="$PROJECT_DIR$/application/src/main/resources/application.yml" afterDir="false" />
     </list>
     <option name="SHOW_DIALOG" value="false" />
@@ -135,7 +134,7 @@
       <workItem from="1704693899463" duration="56714000" />
       <workItem from="1704875622703" duration="2299000" />
       <workItem from="1704932572547" duration="31458000" />
-      <workItem from="1705278479826" duration="6220000" />
+      <workItem from="1705278479826" duration="10248000" />
     </task>
     <task id="LOCAL-00001" summary="基础框架配置">
       <option name="closed" value="true" />
@@ -297,7 +296,15 @@
       <option name="project" value="LOCAL" />
       <updated>1705279424446</updated>
     </task>
-    <option name="localTasksCounter" value="21" />
+    <task id="LOCAL-00021" summary="1、用户修改密码">
+      <option name="closed" value="true" />
+      <created>1705285128154</created>
+      <option name="number" value="00021" />
+      <option name="presentableId" value="LOCAL-00021" />
+      <option name="project" value="LOCAL" />
+      <updated>1705285128154</updated>
+    </task>
+    <option name="localTasksCounter" value="22" />
     <servers />
   </component>
   <component name="TypeScriptGeneratedFilesManager">
@@ -335,7 +342,8 @@
     <MESSAGE value="1、角色绑定菜单、获取角色菜单&#10;2、用户信息新增角色信息" />
     <MESSAGE value="1、long都改成string传输&#10;2、包整理" />
     <MESSAGE value="1、获取用户菜单排序" />
-    <option name="LAST_COMMIT_MESSAGE" value="1、获取用户菜单排序" />
+    <MESSAGE value="1、用户修改密码" />
+    <option name="LAST_COMMIT_MESSAGE" value="1、用户修改密码" />
   </component>
   <component name="XSLT-Support.FileAssociations.UIState">
     <expand />

+ 4 - 0
application/src/main/java/com/ctsi/Auth/entity/UserForm.java

@@ -11,4 +11,8 @@ public class UserForm {
     private String userName;
     @ApiModelProperty(value = "密码")
     private String password;
+    @ApiModelProperty(value = "验证码")
+    private String captcha;
+    @ApiModelProperty(value = "记住我")
+    private Boolean rememberMe;
 }

+ 42 - 8
application/src/main/java/com/ctsi/Auth/web/login.java

@@ -2,38 +2,58 @@ package com.ctsi.Auth.web;
 
 import cn.dev33.satoken.stp.StpUtil;
 import com.ctsi.Auth.entity.UserForm;
+import com.ctsi.Enum.ErrorCodeEnum;
 import com.ctsi.System.SysMenu.entity.PO.SysMenuSearchPO;
 import com.ctsi.System.SysMenu.service.SysMenuService;
 import com.ctsi.System.SysUser.entity.SysUser;
 import com.ctsi.System.SysUser.service.SysUserService;
 import com.ctsi.utils.ApiResult;
+import com.ctsi.utils.CaptchaUtil;
 import com.ctsi.utils.PasswordEncoderUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
 import java.util.List;
 
 @Api(tags = "授权")
 @RestController
 @RequestMapping(value = "/api/system")
 public class login {
+    @Value("${frame.captcha-type}")
+    private Boolean captchaType;
     @Resource
     private SysUserService sysUserService;
     @Resource
     private SysMenuService sysMenuService;
     @ApiOperation("登录")
     @PostMapping(value = "/login",name = "登录")
-    public ApiResult auth(@RequestBody UserForm userForm){
-        SysUser User =  sysUserService.queryByUserName(userForm.getUserName());
-        if(User == null){
-            return ApiResult.failure("用户不存在",null);
-        }
-        if (!PasswordEncoderUtil.checkPassword(userForm.getPassword(),User.getPassword())){
-            return ApiResult.failure("密码错误",null);
+    public ApiResult auth(@RequestBody UserForm userForm, HttpServletRequest request){
+        // 验证码校验是否开启
+        if (captchaType) {
+            // 从 Session 中获取之前生成的验证码
+            HttpSession session = request.getSession();
+            String storedCaptcha = (String) session.getAttribute("captcha");
+            if (storedCaptcha == null)
+                return ApiResult.result(ErrorCodeEnum.CAPTCHA_INVALID);
+            // 从 Session 中删除验证码
+            session.removeAttribute("captcha");
+            // 比较传入的验证码和 Session 中的验证码是否相等
+            if (!storedCaptcha.equalsIgnoreCase(userForm.getCaptcha()))
+                return ApiResult.result(ErrorCodeEnum.CAPTCHA_INVALID);
         }
-        StpUtil.login(User.getId());
+        SysUser User =  sysUserService.queryByUserName(userForm.getUserName());
+        if(User == null)
+            return ApiResult.result(ErrorCodeEnum.USER_NOT_FOUND);
+        if (!PasswordEncoderUtil.checkPassword(userForm.getPassword(),User.getPassword()))
+            return ApiResult.result(ErrorCodeEnum.PASSWORD_INVALID);
+        StpUtil.login(User.getId(),userForm.getRememberMe());
         return ApiResult.success("登录成功");
     }
 
@@ -54,4 +74,18 @@ public class login {
     public ApiResult<List<SysMenuSearchPO>> getMenuTree(){
         return ApiResult.success(sysMenuService.getMenuTree(StpUtil.getLoginIdAsLong()));
     }
+
+    @ApiOperation("获取验证码")
+    @GetMapping("/captcha")
+    public void getCaptcha(HttpServletResponse response, HttpSession session) {
+        try {
+            byte[] captchaImage = CaptchaUtil.generateCaptcha(session);
+            response.setContentType("image/png");
+            response.getOutputStream().write(captchaImage);
+            response.getOutputStream().flush();
+        } catch (IOException e) {
+            // Handle exception
+            e.printStackTrace();
+        }
+    }
 }

+ 30 - 0
application/src/main/java/com/ctsi/Enum/ErrorCodeEnum.java

@@ -0,0 +1,30 @@
+package com.ctsi.Enum;
+
+public enum ErrorCodeEnum {
+    // 定义具体的错误代码和对应的描述
+    USER_NOT_FOUND(1001, "用户名不存在"),
+    PASSWORD_INVALID(1002, "密码错误"),
+    CAPTCHA_INVALID(1003, "验证码错误,请重新获取");
+    // 可以继续添加其他错误代码
+
+    // 枚举的成员变量
+    private final Integer code;
+    private final String message;
+
+    // 构造函数
+    ErrorCodeEnum(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    // 获取错误代码
+    public Integer getCode() {
+        return code;
+    }
+
+    // 获取错误描述
+    public String getMessage() {
+        return message;
+    }
+}
+

+ 1 - 0
application/src/main/java/com/ctsi/config/SaTokenConfigure.java

@@ -17,6 +17,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
         registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
                 .addPathPatterns("/**")
                 .excludePathPatterns("/api/system/login",
+                        "/api/system/captcha",
                         "/swagger-ui/*",
                         "/v3/api-docs",
                         "/webjars/**",

+ 5 - 0
application/src/main/java/com/ctsi/utils/ApiResult.java

@@ -1,5 +1,6 @@
 package com.ctsi.utils;
 
+import com.ctsi.Enum.ErrorCodeEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
@@ -98,5 +99,9 @@ public class ApiResult<T> {
     public static ApiResult<Void> result(int code, String message) {
         return result(code, message, null);
     }
+
+    public static ApiResult<Void> result(ErrorCodeEnum errorCodeEnum) {
+        return result(errorCodeEnum.getCode(), errorCodeEnum.getMessage(), null);
+    }
 }
 

+ 61 - 0
application/src/main/java/com/ctsi/utils/CaptchaUtil.java

@@ -0,0 +1,61 @@
+package com.ctsi.utils;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Random;
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpSession;
+
+public class CaptchaUtil {
+    private static final int WIDTH = 120;
+    private static final int HEIGHT = 40;
+    private static final int LENGTH = 4;
+
+    public static byte[] generateCaptcha(HttpSession session) throws IOException {
+        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
+        Graphics g = image.getGraphics();
+
+        g.setColor(Color.WHITE);
+        g.fillRect(0, 0, WIDTH, HEIGHT);
+
+        g.setColor(Color.BLACK);
+        g.drawRect(0, 0, WIDTH - 1, HEIGHT - 1);
+
+        String captcha = generateRandomString();
+        g.setFont(new Font("Arial", Font.PLAIN, 20));
+        for (int i = 0; i < LENGTH; i++) {
+            g.setColor(new Color(new Random().nextInt(255), new Random().nextInt(255), new Random().nextInt(255)));
+            g.drawString(String.valueOf(captcha.charAt(i)), 20 * i + 10, 30);
+        }
+
+        for (int i = 0; i < 5; i++) {
+            g.setColor(new Color(new Random().nextInt(255), new Random().nextInt(255), new Random().nextInt(255)));
+            int x1 = new Random().nextInt(WIDTH);
+            int y1 = new Random().nextInt(HEIGHT);
+            int x2 = new Random().nextInt(WIDTH);
+            int y2 = new Random().nextInt(HEIGHT);
+            g.drawLine(x1, y1, x2, y2);
+        }
+
+        g.dispose();
+
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ImageIO.write(image, "png", outputStream);
+        session.setAttribute("captcha", captcha);
+        return outputStream.toByteArray();
+    }
+
+    private static String generateRandomString() {
+        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+        StringBuilder stringBuilder = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < LENGTH; i++) {
+            int index = random.nextInt(characters.length());
+            stringBuilder.append(characters.charAt(index));
+        }
+        return stringBuilder.toString();
+    }
+}
+

+ 3 - 1
application/src/main/resources/application.yml

@@ -57,7 +57,7 @@ sa-token:
   # token 名称(同时也是 cookie 名称)
   token-name: token
   # token 有效期(单位:秒) 默认30天,-1 代表永久有效
-  timeout: 2592000
+  timeout: 86400
   # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
   active-timeout: -1
   # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
@@ -72,3 +72,5 @@ sa-token:
 # frame
 frame:
   default-password: Root@0511
+  # 验证码配置
+  captcha-type: true