11package cn .wildfirechat .app .slide ;
22
3+ import cn .wildfirechat .app .jpa .SlideVerify ;
4+ import cn .wildfirechat .app .jpa .SlideVerifyRepository ;
35import org .slf4j .Logger ;
46import org .slf4j .LoggerFactory ;
7+ import org .springframework .beans .factory .annotation .Autowired ;
58import org .springframework .stereotype .Service ;
69
710import javax .imageio .ImageIO ;
811import java .awt .*;
9- import java .awt .geom .AffineTransform ;
10- import java .awt .geom .PathIterator ;
11- import java .awt .geom .Rectangle2D ;
1212import java .awt .geom .RoundRectangle2D ;
1313import java .awt .image .BufferedImage ;
1414import java .io .ByteArrayOutputStream ;
1717import java .util .HashMap ;
1818import java .util .Map ;
1919import java .util .UUID ;
20- import java .util .concurrent .ConcurrentHashMap ;
2120
2221@ Service
2322public class SlideVerifyService {
2423 private static final Logger LOG = LoggerFactory .getLogger (SlideVerifyService .class );
2524
26- // 存储验证码信息:token -> 验证数据
27- private final ConcurrentHashMap < String , VerifyData > verifyCache = new ConcurrentHashMap <>() ;
25+ @ Autowired
26+ private SlideVerifyRepository slideVerifyRepository ;
2827
2928 // 验证码有效时间(秒)
3029 private static final int VERIFY_TIMEOUT = 300 ; // 5分钟
@@ -38,23 +37,6 @@ public class SlideVerifyService {
3837 private static final int SLIDER_WIDTH = 50 ;
3938 private static final int SLIDER_HEIGHT = 50 ;
4039
41- // 验证数据类
42- private static class VerifyData {
43- int x ; // 正确的x坐标
44- long timestamp ; // 生成时间戳
45- boolean verified ; // 是否已验证
46-
47- VerifyData (int x ) {
48- this .x = x ;
49- this .timestamp = System .currentTimeMillis ();
50- this .verified = false ;
51- }
52-
53- boolean isExpired () {
54- return System .currentTimeMillis () - timestamp > VERIFY_TIMEOUT * 1000 ;
55- }
56- }
57-
5840 /**
5941 * 生成滑动验证码
6042 */
@@ -68,8 +50,9 @@ public Map<String, Object> generateSlideVerify() {
6850
6951 LOG .info ("生成滑动验证码: token={}, x={}, y={}" , token , x , y );
7052
71- // 存储验证数据
72- verifyCache .put (token , new VerifyData (x ));
53+ // 保存验证数据到数据库
54+ SlideVerify slideVerify = new SlideVerify (token , x , System .currentTimeMillis ());
55+ slideVerifyRepository .save (slideVerify );
7356
7457 try {
7558 // 生成背景图(带缺口)
@@ -89,7 +72,7 @@ public Map<String, Object> generateSlideVerify() {
8972 return result ;
9073 } catch (Exception e ) {
9174 LOG .error ("生成滑动验证码失败" , e );
92- verifyCache . remove ( token );
75+ slideVerifyRepository . delete ( slideVerify );
9376 throw new RuntimeException ("生成滑动验证码失败" );
9477 }
9578 }
@@ -98,34 +81,35 @@ public Map<String, Object> generateSlideVerify() {
9881 * 验证滑动位置
9982 */
10083 public boolean verifySlide (String token , int userX ) {
101- VerifyData data = verifyCache . get (token );
84+ SlideVerify data = slideVerifyRepository . findByToken (token ). orElse ( null );
10285
10386 if (data == null ) {
10487 LOG .warn ("验证token不存在: {}" , token );
10588 return false ;
10689 }
10790
108- if (data .isExpired ()) {
91+ if (data .isExpired (VERIFY_TIMEOUT )) {
10992 LOG .warn ("验证token已过期: {}" , token );
110- verifyCache . remove ( token );
93+ slideVerifyRepository . delete ( data );
11194 return false ;
11295 }
11396
114- if (data .verified ) {
97+ if (data .isVerified () ) {
11598 LOG .warn ("验证token已使用: {}" , token );
11699 return false ;
117100 }
118101
119102 // 验证位置是否在误差范围内
120- int difference = Math .abs (data .x - userX );
103+ int difference = Math .abs (data .getX () - userX );
121104 boolean success = difference <= TOLERANCE ;
122105
123106 if (success ) {
124- data .verified = true ;
125- LOG .info ("滑动验证成功,token: {}, 正确位置: {}, 用户位置: {}, 差值: {}" , token , data .x , userX , difference );
107+ data .setVerified (true );
108+ slideVerifyRepository .save (data );
109+ LOG .info ("滑动验证成功,token: {}, 正确位置: {}, 用户位置: {}, 差值: {}" , token , data .getX (), userX , difference );
126110 } else {
127- LOG .warn ("滑动验证失败,token: {}, 正确位置: {}, 用户位置: {}, 差值: {}, 容差: {}" , token , data .x , userX , difference , TOLERANCE );
128- verifyCache . remove ( token ); // 验证失败则移除token
111+ LOG .warn ("滑动验证失败,token: {}, 正确位置: {}, 用户位置: {}, 差值: {}, 容差: {}" , token , data .getX () , userX , difference , TOLERANCE );
112+ slideVerifyRepository . delete ( data ); // 验证失败则删除记录
129113 }
130114
131115 return success ;
@@ -135,15 +119,15 @@ public boolean verifySlide(String token, int userX) {
135119 * 检查token是否已验证(一次性使用)
136120 */
137121 public boolean isVerified (String token ) {
138- VerifyData data = verifyCache . get (token );
139- if (data == null || data .isExpired ()) {
122+ SlideVerify data = slideVerifyRepository . findByToken (token ). orElse ( null );
123+ if (data == null || data .isExpired (VERIFY_TIMEOUT )) {
140124 return false ;
141125 }
142126
143127 // token已验证通过,立即删除,确保只能使用一次
144- if (data .verified ) {
128+ if (data .isVerified () ) {
145129 LOG .info ("验证token已使用,删除token: {}" , token );
146- verifyCache . remove ( token );
130+ slideVerifyRepository . delete ( data );
147131 return true ;
148132 }
149133
@@ -154,7 +138,8 @@ public boolean isVerified(String token) {
154138 * 清理过期的验证数据
155139 */
156140 public void cleanExpiredData () {
157- verifyCache .entrySet ().removeIf (entry -> entry .getValue ().isExpired ());
141+ java .time .Instant cutoff = java .time .Instant .now ().minusSeconds (VERIFY_TIMEOUT );
142+ slideVerifyRepository .deleteExpired (cutoff );
158143 }
159144
160145 /**
0 commit comments