当前位置:   article > 正文

springboot集成图片验证+redis缓存一步到位_spring boot 图片拖坠验证码实现

spring boot 图片拖坠验证码实现

1.图片验证与缓存依赖:

  1. <dependencies>
  2. <!-- 验证码-->
  3. <dependency>
  4. <groupId>com.github.whvcse</groupId>
  5. <artifactId>easy-captcha</artifactId>
  6. <version>1.6.2</version>
  7. </dependency>
  8. <!-- redis-->
  9. <dependency>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-data-redis</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.apache.commons</groupId>
  15. <artifactId>commons-pool2</artifactId>
  16. </dependency>
  17. </dependencies>

2.redis配置:在application.properties中加入配置

  1. spring.redis.host=localhost
  2. spring.redis.port=6379
  3. spring.redis.database= 0
  4. spring.redis.timeout=1800000
  5. spring.redis.lettuce.pool.max-active=20
  6. spring.redis.lettuce.pool.max-wait=-1
  7. #最大阻塞等待时间(负数表示没限制)
  8. spring.redis.lettuce.pool.max-idle=5
  9. spring.redis.lettuce.pool.min-idle=0
  10. #最小空闲

3.redis工具类:

        注意之所以每加static是因为咱们是注入形式调用的,而不是通过类名调用,这里是通过spring对象帮我们调用。注意!!!同时@component注解不要忘记加!

  1. package com.laoyang.educms.utils;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.data.redis.core.RedisTemplate;
  4. import org.springframework.stereotype.Component;
  5. import org.springframework.util.CollectionUtils;
  6. import javax.annotation.Resource;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Set;
  10. import java.util.concurrent.TimeUnit;
  11. /**
  12. * @author:Kevin
  13. * @create: 2022-10-05 14:30
  14. * @Description:
  15. */
  16. @Component
  17. public class redisutils {
  18. @Autowired
  19. private RedisTemplate<String, Object> redisTemplate;
  20. // =============================common============================
  21. /**
  22. * 指定缓存失效时间
  23. *
  24. * @param key 键
  25. * @param time 时间(秒)
  26. */
  27. public boolean expire(String key, long time) {
  28. try {
  29. if (time > 0) {
  30. redisTemplate.expire(key, time, TimeUnit.SECONDS);
  31. }
  32. return true;
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. return false;
  36. }
  37. }
  38. /**
  39. * 根据key 获取过期时间
  40. *
  41. * @param key 键 不能为null
  42. * @return 时间(秒) 返回0代表为永久有效
  43. */
  44. public long getExpire(String key) {
  45. return redisTemplate.getExpire(key, TimeUnit.SECONDS);
  46. }
  47. /**
  48. * 判断key是否存在
  49. *
  50. * @param key 键
  51. * @return true 存在 false不存在
  52. */
  53. public boolean hasKey(String key) {
  54. try {
  55. return redisTemplate.hasKey(key);
  56. } catch (Exception e) {
  57. e.printStackTrace();
  58. return false;
  59. }
  60. }
  61. /**
  62. * 删除缓存
  63. *
  64. * @param key 可以传一个值 或多个
  65. */
  66. @SuppressWarnings("unchecked")
  67. public void del(String... key) {
  68. if (key != null && key.length > 0) {
  69. if (key.length == 1) {
  70. redisTemplate.delete(key[0]);
  71. } else {
  72. redisTemplate.delete(CollectionUtils.arrayToList(key));
  73. }
  74. }
  75. }
  76. // ============================String=============================
  77. /**
  78. * 普通缓存获取
  79. *
  80. * @param key 键
  81. * @return
  82. */
  83. public Object get(String key) {
  84. return key == null ? null : redisTemplate.opsForValue().get(key);
  85. }
  86. /**
  87. * 普通缓存放入
  88. *
  89. * @param key 键
  90. * @param value 值
  91. * @return true成功 false失败
  92. */
  93. public boolean set(String key, Object value) {
  94. try {
  95. redisTemplate.opsForValue().set(key, value);
  96. return true;
  97. } catch (Exception e) {
  98. e.printStackTrace();
  99. return false;
  100. }
  101. }
  102. /**
  103. * 普通缓存放入并设置时间
  104. *
  105. * @param key 键
  106. * @param value 值
  107. * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
  108. * @return true成功 false 失败
  109. */
  110. public boolean set(String key, Object value, long time) {
  111. try {
  112. if (time > 0) {
  113. redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
  114. } else {
  115. set(key, value);
  116. }
  117. return true;
  118. } catch (Exception e) {
  119. e.printStackTrace();
  120. return false;
  121. }
  122. }
  123. /**
  124. * 递增
  125. *
  126. * @param key 键
  127. * @param delta 要增加几(大于0)
  128. */
  129. public long incr(String key, long delta) {
  130. if (delta < 0) {
  131. throw new RuntimeException("递增因子必须大于0");
  132. }
  133. return redisTemplate.opsForValue().increment(key, delta);
  134. }
  135. /**
  136. * 递减
  137. *
  138. * @param key 键
  139. * @param delta 要减少几(小于0)
  140. */
  141. public long decr(String key, long delta) {
  142. if (delta < 0) {
  143. throw new RuntimeException("递减因子必须大于0");
  144. }
  145. return redisTemplate.opsForValue().increment(key, -delta);
  146. }
  147. // ================================Map=================================
  148. /**
  149. * HashGet
  150. *
  151. * @param key 键 不能为null
  152. * @param item 项 不能为null
  153. */
  154. public Object hget(String key, String item) {
  155. return redisTemplate.opsForHash().get(key, item);
  156. }
  157. /**
  158. * 获取hashKey对应的所有键值
  159. *
  160. * @param key 键
  161. * @return 对应的多个键值
  162. */
  163. public Map<Object, Object> hmget(String key) {
  164. return redisTemplate.opsForHash().entries(key);
  165. }
  166. /**
  167. * HashSet
  168. *
  169. * @param key 键
  170. * @param map 对应多个键值
  171. */
  172. public boolean hmset(String key, Map<String, Object> map) {
  173. try {
  174. redisTemplate.opsForHash().putAll(key, map);
  175. return true;
  176. } catch (Exception e) {
  177. e.printStackTrace();
  178. return false;
  179. }
  180. }
  181. /**
  182. * HashSet 并设置时间
  183. *
  184. * @param key 键
  185. * @param map 对应多个键值
  186. * @param time 时间(秒)
  187. * @return true成功 false失败
  188. */
  189. public boolean hmset(String key, Map<String, Object> map, long time) {
  190. try {
  191. redisTemplate.opsForHash().putAll(key, map);
  192. if (time > 0) {
  193. expire(key, time);
  194. }
  195. return true;
  196. } catch (Exception e) {
  197. e.printStackTrace();
  198. return false;
  199. }
  200. }
  201. /**
  202. * 向一张hash表中放入数据,如果不存在将创建
  203. *
  204. * @param key 键
  205. * @param item 项
  206. * @param value 值
  207. * @return true 成功 false失败
  208. */
  209. public boolean hset(String key, String item, Object value) {
  210. try {
  211. redisTemplate.opsForHash().put(key, item, value);
  212. return true;
  213. } catch (Exception e) {
  214. e.printStackTrace();
  215. return false;
  216. }
  217. }
  218. /**
  219. * 向一张hash表中放入数据,如果不存在将创建
  220. *
  221. * @param key 键
  222. * @param item 项
  223. * @param value 值
  224. * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
  225. * @return true 成功 false失败
  226. */
  227. public boolean hset(String key, String item, Object value, long time) {
  228. try {
  229. redisTemplate.opsForHash().put(key, item, value);
  230. if (time > 0) {
  231. expire(key, time);
  232. }
  233. return true;
  234. } catch (Exception e) {
  235. e.printStackTrace();
  236. return false;
  237. }
  238. }
  239. /**
  240. * 删除hash表中的值
  241. *
  242. * @param key 键 不能为null
  243. * @param item 项 可以使多个 不能为null
  244. */
  245. public void hdel(String key, Object... item) {
  246. redisTemplate.opsForHash().delete(key, item);
  247. }
  248. /**
  249. * 判断hash表中是否有该项的值
  250. *
  251. * @param key 键 不能为null
  252. * @param item 项 不能为null
  253. * @return true 存在 false不存在
  254. */
  255. public boolean hHasKey(String key, String item) {
  256. return redisTemplate.opsForHash().hasKey(key, item);
  257. }
  258. /**
  259. * hash递增 如果不存在,就会创建一个 并把新增后的值返回
  260. *
  261. * @param key 键
  262. * @param item 项
  263. * @param by 要增加几(大于0)
  264. */
  265. public double hincr(String key, String item, double by) {
  266. return redisTemplate.opsForHash().increment(key, item, by);
  267. }
  268. /**
  269. * hash递减
  270. *
  271. * @param key 键
  272. * @param item 项
  273. * @param by 要减少记(小于0)
  274. */
  275. public double hdecr(String key, String item, double by) {
  276. return redisTemplate.opsForHash().increment(key, item, -by);
  277. }
  278. // ============================set=============================
  279. /**
  280. * 根据key获取Set中的所有值
  281. *
  282. * @param key 键
  283. */
  284. public Set<Object> sGet(String key) {
  285. try {
  286. return redisTemplate.opsForSet().members(key);
  287. } catch (Exception e) {
  288. e.printStackTrace();
  289. return null;
  290. }
  291. }
  292. /**
  293. * 根据value从一个set中查询,是否存在
  294. *
  295. * @param key 键
  296. * @param value 值
  297. * @return true 存在 false不存在
  298. */
  299. public boolean sHasKey(String key, Object value) {
  300. try {
  301. return redisTemplate.opsForSet().isMember(key, value);
  302. } catch (Exception e) {
  303. e.printStackTrace();
  304. return false;
  305. }
  306. }
  307. /**
  308. * 将数据放入set缓存
  309. *
  310. * @param key 键
  311. * @param values 值 可以是多个
  312. * @return 成功个数
  313. */
  314. public long sSet(String key, Object... values) {
  315. try {
  316. return redisTemplate.opsForSet().add(key, values);
  317. } catch (Exception e) {
  318. e.printStackTrace();
  319. return 0;
  320. }
  321. }
  322. /**
  323. * 将set数据放入缓存
  324. *
  325. * @param key 键
  326. * @param time 时间(秒)
  327. * @param values 值 可以是多个
  328. * @return 成功个数
  329. */
  330. public long sSetAndTime(String key, long time, Object... values) {
  331. try {
  332. Long count = redisTemplate.opsForSet().add(key, values);
  333. if (time > 0)
  334. expire(key, time);
  335. return count;
  336. } catch (Exception e) {
  337. e.printStackTrace();
  338. return 0;
  339. }
  340. }
  341. /**
  342. * 获取set缓存的长度
  343. *
  344. * @param key 键
  345. */
  346. public long sGetSetSize(String key) {
  347. try {
  348. return redisTemplate.opsForSet().size(key);
  349. } catch (Exception e) {
  350. e.printStackTrace();
  351. return 0;
  352. }
  353. }
  354. /**
  355. * 移除值为value的
  356. *
  357. * @param key 键
  358. * @param values 值 可以是多个
  359. * @return 移除的个数
  360. */
  361. public long setRemove(String key, Object... values) {
  362. try {
  363. Long count = redisTemplate.opsForSet().remove(key, values);
  364. return count;
  365. } catch (Exception e) {
  366. e.printStackTrace();
  367. return 0;
  368. }
  369. }
  370. // ===============================list=================================
  371. /**
  372. * 获取list缓存的内容
  373. *
  374. * @param key 键
  375. * @param start 开始
  376. * @param end 结束 0 到 -1代表所有值
  377. */
  378. public List<Object> lGet(String key, long start, long end) {
  379. try {
  380. return redisTemplate.opsForList().range(key, start, end);
  381. } catch (Exception e) {
  382. e.printStackTrace();
  383. return null;
  384. }
  385. }
  386. /**
  387. * 获取list缓存的长度
  388. *
  389. * @param key 键
  390. */
  391. public long lGetListSize(String key) {
  392. try {
  393. return redisTemplate.opsForList().size(key);
  394. } catch (Exception e) {
  395. e.printStackTrace();
  396. return 0;
  397. }
  398. }
  399. /**
  400. * 通过索引 获取list中的值
  401. *
  402. * @param key 键
  403. * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
  404. */
  405. public Object lGetIndex(String key, long index) {
  406. try {
  407. return redisTemplate.opsForList().index(key, index);
  408. } catch (Exception e) {
  409. e.printStackTrace();
  410. return null;
  411. }
  412. }
  413. /**
  414. * 将list放入缓存
  415. *
  416. * @param key 键
  417. * @param value 值
  418. */
  419. public boolean lSet(String key, Object value) {
  420. try {
  421. redisTemplate.opsForList().rightPush(key, value);
  422. return true;
  423. } catch (Exception e) {
  424. e.printStackTrace();
  425. return false;
  426. }
  427. }
  428. /**
  429. * 将list放入缓存
  430. *
  431. * @param key 键
  432. * @param value 值
  433. * @param time 时间(秒)
  434. */
  435. public boolean lSet(String key, Object value, long time) {
  436. try {
  437. redisTemplate.opsForList().rightPush(key, value);
  438. if (time > 0)
  439. expire(key, time);
  440. return true;
  441. } catch (Exception e) {
  442. e.printStackTrace();
  443. return false;
  444. }
  445. }
  446. /**
  447. * 将list放入缓存
  448. *
  449. * @param key 键
  450. * @param value 值
  451. * @return
  452. */
  453. public boolean lSet(String key, List<Object> value) {
  454. try {
  455. redisTemplate.opsForList().rightPushAll(key, value);
  456. return true;
  457. } catch (Exception e) {
  458. e.printStackTrace();
  459. return false;
  460. }
  461. }
  462. /**
  463. * 将list放入缓存
  464. *
  465. * @param key 键
  466. * @param value 值
  467. * @param time 时间(秒)
  468. * @return
  469. */
  470. public boolean lSet(String key, List<Object> value, long time) {
  471. try {
  472. redisTemplate.opsForList().rightPushAll(key, value);
  473. if (time > 0)
  474. expire(key, time);
  475. return true;
  476. } catch (Exception e) {
  477. e.printStackTrace();
  478. return false;
  479. }
  480. }
  481. /**
  482. * 根据索引修改list中的某条数据
  483. *
  484. * @param key 键
  485. * @param index 索引
  486. * @param value 值
  487. * @return
  488. */
  489. public boolean lUpdateIndex(String key, long index, Object value) {
  490. try {
  491. redisTemplate.opsForList().set(key, index, value);
  492. return true;
  493. } catch (Exception e) {
  494. e.printStackTrace();
  495. return false;
  496. }
  497. }
  498. /**
  499. * 移除N个值为value
  500. *
  501. * @param key 键
  502. * @param count 移除多少个
  503. * @param value 值
  504. * @return 移除的个数
  505. */
  506. public long lRemove(String key, long count, Object value) {
  507. try {
  508. Long remove = redisTemplate.opsForList().remove(key, count, value);
  509. return remove;
  510. } catch (Exception e) {
  511. e.printStackTrace();
  512. return 0;
  513. }
  514. }
  515. }

4.还需要加入配置类,否则启动不起来,一样@component注解不要忘记加!

        

  1. package com.laoyang.educms.config;
  2. /**
  3. * @author:Kevin
  4. * @create: 2022-10-05 15:38
  5. * @Description:
  6. */
  7. import com.fasterxml.jackson.annotation.JsonAutoDetect;
  8. import com.fasterxml.jackson.annotation.JsonTypeInfo;
  9. import com.fasterxml.jackson.annotation.PropertyAccessor;
  10. import com.fasterxml.jackson.databind.ObjectMapper;
  11. import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
  12. import org.springframework.context.annotation.Bean;
  13. import org.springframework.data.redis.connection.RedisConnectionFactory;
  14. import org.springframework.data.redis.core.RedisTemplate;
  15. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  16. import org.springframework.data.redis.serializer.StringRedisSerializer;
  17. import org.springframework.stereotype.Component;
  18. @Component
  19. public class Config {
  20. @Bean(name = "template")
  21. public RedisTemplate<String, Object> template(RedisConnectionFactory factory) {
  22. // 创建RedisTemplate<String, Object>对象
  23. RedisTemplate<String, Object> template = new RedisTemplate<>();
  24. // 配置连接工厂
  25. template.setConnectionFactory(factory);
  26. // 定义Jackson2JsonRedisSerializer序列化对象
  27. Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);
  28. ObjectMapper om = new ObjectMapper();
  29. // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
  30. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  31. // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会报异常
  32. om.activateDefaultTyping(
  33. LaissezFaireSubTypeValidator.instance ,
  34. ObjectMapper.DefaultTyping.NON_FINAL,
  35. JsonTypeInfo.As.WRAPPER_ARRAY);
  36. jacksonSeial.setObjectMapper(om);
  37. StringRedisSerializer stringSerial = new StringRedisSerializer();
  38. // redis key 序列化方式使用stringSerial
  39. template.setKeySerializer(stringSerial);
  40. // redis value 序列化方式使用jackson
  41. template.setValueSerializer(jacksonSeial);
  42. // redis hash key 序列化方式使用stringSerial
  43. template.setHashKeySerializer(stringSerial);
  44. // redis hash value 序列化方式使用jackson
  45. template.setHashValueSerializer(jacksonSeial);
  46. template.afterPropertiesSet();
  47. return template;
  48. }
  49. }

5.创建service:验证码service:两个方法,一个是生成验证码图片,另一个方法是验证输入的验证码是否正确。

  1. package com.laoyang.educms.service;
  2. import javax.servlet.http.HttpServletResponse;
  3. import java.io.IOException;
  4. /**
  5. * @author:Kevin
  6. * @create: 2022-10-05 13:50
  7. * @Description: 验证码
  8. */
  9. public interface ValidateCodeService {
  10. /**
  11. * 生成验证码
  12. */
  13. void create(String key, HttpServletResponse response) throws IOException;
  14. /**
  15. * 校验验证码
  16. * @param key 前端上送 key
  17. * @param value 前端上送待校验值
  18. */
  19. boolean check(String key, String value);
  20. }

6.编写验证码service的实现类:注意这里会用到缓存,因为咱们这个redis工具类不是static的,所以这里用的话需要对象注入调用

  1. package com.laoyang.educms.service.impl;
  2. import com.laoyang.CommonUtils.Contst.ResultCode;
  3. import com.laoyang.MyException;
  4. import com.laoyang.educms.entity.CacheObject;
  5. import com.laoyang.educms.service.ValidateCodeService;
  6. import com.laoyang.educms.utils.redisutils;
  7. import com.wf.captcha.ArithmeticCaptcha;
  8. import com.wf.captcha.base.Captcha;
  9. import org.apache.commons.lang3.StringUtils;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.http.HttpHeaders;
  12. import org.springframework.http.MediaType;
  13. import org.springframework.stereotype.Service;
  14. import javax.servlet.http.HttpServletResponse;
  15. import java.io.IOException;
  16. /**
  17. * @author:Kevin
  18. * @create: 2022-10-05 13:51
  19. * @Description:
  20. */
  21. @Service
  22. public class ValidateCodeServiceImpl implements ValidateCodeService {
  23. @Autowired
  24. private redisutils redisutils;
  25. /**
  26. * 生成验证码图片
  27. * @param key
  28. * @param response
  29. * @throws IOException
  30. */
  31. @Override
  32. public void create(String key, HttpServletResponse response) throws IOException {
  33. if (StringUtils.isBlank(key)) {
  34. throw new MyException(ResultCode.ERROR,"验证码不能为空");
  35. }
  36. response.setContentType(MediaType.IMAGE_PNG_VALUE);
  37. response.setHeader(HttpHeaders.PRAGMA, "No-cache");
  38. response.setHeader(HttpHeaders.CACHE_CONTROL, "No-cache");
  39. response.setDateHeader(HttpHeaders.EXPIRES, 0L);
  40. Captcha captcha = new ArithmeticCaptcha(115, 42);
  41. captcha.setCharType(2);
  42. String text = captcha.text();
  43. System.out.println(text);
  44. //设置过期时间为5分种
  45. redisutils.set(key,text,300);
  46. captcha.out(response.getOutputStream());
  47. }
  48. /**
  49. * 校验输入的验证码
  50. * @param key 前端上送 key
  51. * @param value 前端上送待校验值
  52. * @return
  53. */
  54. @Override
  55. public boolean check(String key, String value) {
  56. if (StringUtils.isBlank(value)) {
  57. throw new MyException(ResultCode.ERROR,"验证码不能为空");
  58. }
  59. //根据key从缓存中获取验证码
  60. String code = (String) redisutils.get(key);
  61. if (code == null) {
  62. throw new MyException(ResultCode.ERROR,"验证码已经过期");
  63. }
  64. //比对验证码
  65. if (!StringUtils.equalsIgnoreCase(value,
  66. code)) {
  67. throw new MyException(ResultCode.ERROR,"验证码不正确");
  68. }
  69. //验证通过,立即从缓存中删除验证码
  70. redisutils.del(key);
  71. return true;
  72. }
  73. }

7.编写一个前端后端数据交互的登录DTO

  1. package com.laoyang.educms.entity;
  2. import io.swagger.annotations.ApiModel;
  3. import io.swagger.annotations.ApiModelProperty;
  4. import lombok.*;
  5. import lombok.experimental.Accessors;
  6. import javax.validation.constraints.NotEmpty;
  7. /**
  8. * @author:Kevin
  9. * @create: 2022-10-05 15:00
  10. * @Description:
  11. */
  12. @Data
  13. @NoArgsConstructor
  14. @AllArgsConstructor
  15. @Accessors(chain = true)
  16. @ToString(callSuper = true)
  17. @EqualsAndHashCode(callSuper = false)
  18. @Builder
  19. @ApiModel(value = "LoginParamDTO", description = "登录参数")
  20. public class LoginDto {
  21. @ApiModelProperty(value = "验证码KEY")
  22. @NotEmpty(message = "验证码KEY不能为空")
  23. private String key;
  24. @ApiModelProperty(value = "验证码")
  25. @NotEmpty(message = "验证码不能为空")
  26. private String code;
  27. @ApiModelProperty(value = "账号")
  28. @NotEmpty(message = "账号不能为空")
  29. private String account;
  30. @ApiModelProperty(value = "密码")
  31. @NotEmpty(message = "密码不能为空")
  32. private String password;
  33. @ApiModelProperty(value = "电话号码")
  34. @NotEmpty(message = "电话号码不能为空")
  35. private String Mobile;
  36. }

8.编写验证码视图类

  1. package com.laoyang.educms.controller;
  2. import com.laoyang.CommonUtils.R;
  3. import com.laoyang.educms.entity.LoginDto;
  4. import com.laoyang.educms.entity.UcenterMember;
  5. import com.laoyang.educms.service.UcenterMemberService;
  6. import com.laoyang.educms.service.ValidateCodeService;
  7. import io.swagger.annotations.Api;
  8. import io.swagger.annotations.ApiOperation;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.web.bind.annotation.*;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.IOException;
  13. /**
  14. * <p>
  15. * 会员表 前端控制器
  16. * </p>
  17. *
  18. * @author testjava
  19. * @since 2022-10-05
  20. */
  21. @RestController
  22. @CrossOrigin
  23. @Api(value = "UcenterMemberController", tags = "登录")
  24. @RequestMapping("/educms/member")
  25. public class UcenterMemberController {
  26. @Autowired
  27. private UcenterMemberService memberService;
  28. @Autowired
  29. private ValidateCodeService validateCodeService;
  30. /**
  31. * 登录
  32. * @param loginDto
  33. * @return
  34. */
  35. @PostMapping("/login")
  36. public R login(@RequestBody LoginDto loginDto){
  37. if (validateCodeService.check(loginDto.getKey(), loginDto.getCode())){
  38. String token = memberService.login(loginDto);
  39. return R.ok("登录成功").data("token",token);
  40. }
  41. return R.error("登录失败");
  42. }
  43. /**
  44. * 生成验证码
  45. */
  46. @ApiOperation(value = "验证码", notes = "验证码")
  47. @GetMapping(value = "/captcha", produces = "image/png")
  48. public void captcha(@RequestParam(value = "key") String key,
  49. HttpServletResponse response) throws IOException {
  50. this.validateCodeService.create(key, response);
  51. }
  52. }

最终测试实现:

第一个测试生成验证码的接口:

 第二个是从redis缓存中通过传入的key获取数据再和前端用户输入的code值进行判断,如果不对,就从新刷新进行验证

10.前端接受时的写法,否则会乱码,需要加上响应类型为blob

11.前端的js代码获取

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/46508
推荐阅读
相关标签
  

闽ICP备14008679号