瀏覽代碼

1.添加登录页验证码校验

1 3 周之前
父節點
當前提交
5fadf952ca

+ 17 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/exception/CaptchaException.java

@@ -0,0 +1,17 @@
+package top.imwork.window.silos.exception;
+
+/**
+ * Copyright (C), 2015-2026
+ * FileName: CaptchaException
+ * Author<作者姓名>:   stars
+ * CreateTime<创建时间>:   2026/1/12 17:39
+ * UpdateTime<修改时间>:   2026/1/12 17:39
+ * Description〈功能简述〉:
+ * History<历史描述>:
+ * Since<版本号>: 1.0.0
+ */
+public class CaptchaException extends RuntimeException {
+    public CaptchaException(String message) {
+        super(message);
+    }
+}

+ 81 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/handler/ValidateCodeFilter.java

@@ -0,0 +1,81 @@
+package top.imwork.window.silos.handler;
+
+import jakarta.annotation.Resource;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.web.filter.OncePerRequestFilter;
+import top.imwork.commons.core.constants.Constants;
+import top.imwork.commons.core.utils.StringUtils;
+import top.imwork.window.silos.exception.CaptchaException;
+import top.imwork.window.silos.utils.RedisUtils;
+
+import java.io.IOException;
+
+/**
+ * Copyright (C), 2015-2026
+ * FileName: ValidateCodeFilter
+ * Author<作者姓名>:   stars
+ * CreateTime<创建时间>:   2026/1/12 17:36
+ * UpdateTime<修改时间>:   2026/1/12 17:36
+ * Description〈功能简述〉: 验证码校验
+ * History<历史描述>:
+ * Since<版本号>: 1.0.0
+ */
+@Component
+public class ValidateCodeFilter extends OncePerRequestFilter {
+
+    @Resource
+    private RedisUtils redisUtils;
+
+    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+// 只拦截登录请求
+        if (antPathMatcher.match("/auth/login", request.getRequestURI())
+                && "POST".equalsIgnoreCase(request.getMethod())) {
+
+            try {
+                validateCaptcha(request);
+                filterChain.doFilter(request, response);
+            } catch (CaptchaException e) {
+                HttpSession session= request.getSession();
+                session.setAttribute("message", "验证码错误");
+                response.sendRedirect("/login.html");
+                // 验证码错误,返回错误信息
+                /*response.setContentType("application/json;charset=UTF-8");
+                response.getWriter().write(
+                        "{\"code\":500,\"msg\":\"验证码错误\",\"data\":null}"
+                );*/
+            }
+        } else {
+            filterChain.doFilter(request, response);
+        }
+    }
+
+    private void validateCaptcha(HttpServletRequest request) {
+        String captcha = request.getParameter("imageCode");
+        Object cacheCode = redisUtils.hget(Constants.SESSION_KEY,request.getSession().getId());
+        String captchaCode = (String) cacheCode;
+
+        if (StringUtils.isEmpty(captcha) || StringUtils.isEmpty(cacheCode)) {
+            throw new CaptchaException("验证码不能为空");
+        }
+
+        if (StringUtils.isEmpty(captchaCode)) {
+            throw new CaptchaException("验证码已过期");
+        }
+
+        if (!captcha.equalsIgnoreCase(captchaCode)) {
+            throw new CaptchaException("验证码错误");
+        }
+
+        // 验证成功后删除验证码
+        redisUtils.hdel(Constants.SESSION_KEY,request.getSession().getId());
+    }
+}

+ 6 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/security/config/SecurityConfig.java

@@ -16,10 +16,12 @@ import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
 import org.springframework.web.cors.CorsConfiguration;
 import org.springframework.web.cors.CorsConfigurationSource;
 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import top.imwork.window.silos.handler.ValidateCodeFilter;
 import top.imwork.window.silos.security.details.SecurityUserDetailsService;
 import top.imwork.window.silos.security.handler.SecurityAuthenticationFailureHandler;
 import top.imwork.window.silos.security.handler.SecurityAuthenticationSuccessHandler;
@@ -45,6 +47,9 @@ public class SecurityConfig{
     @Resource
     private SecurityAuthenticationFailureHandler authenticationFailureHandler;
 
+    @Resource
+    private ValidateCodeFilter validateCodeFilter;
+
     @Bean
     public PasswordEncoder passwordEncoder() {
         return new BCryptPasswordEncoder();
@@ -75,6 +80,7 @@ public class SecurityConfig{
                         // 其他所有请求都需要认证
                         .anyRequest().authenticated()
                 )
+                .addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                 .headers(headers -> headers
                         .frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)
                 )

+ 1 - 0
imwork-windows/imwork-silos/src/main/resources/templates/login/login.html

@@ -45,6 +45,7 @@
                      onclick="this.src='/ValidateCode/imageCode?t=' + new Date().getTime()">
             </div>
         </div>
+        <div th:text="${message}"></div>
         <div class="layui-form-item">
             <span class="fl"><input type="checkbox" name="remember-me" checked class="silos-checkbox"/>记住密码 </span>
             <a class="fr" href="javascript:">忘记密码</a>