我是怎样完成开源系统中的验证码的功能的?

写在前面:

最近有一个想法,做一个程序员师徒系统。因为在大学期间的我在学习java的时候非常地迷茫,找不到自己的方向,也没有一个社会上有经验的前辈去指导,所以走了很多的弯路。后来工作了,想把自己的避坑经验分享给别人,但是发现身边都是有经验的开发者,也没有机会去分享自己的想法,所以富贵同学就想做一个程序员专属的师徒系统,秉承着徒弟能够有人指教少走弯路,师傅能桃李满天下的目的,所以开始做这个师徒系统,也会同步更新该系统所用到的技术,并且作为教程分享给大家,希望大家能够关注一波。

这里推荐使用gitee.com/ele-admin/E… 作为工具来实现验证码的功能,因为它好用,简单,可以作为系统的验证模块使用

第一步,导入jar包

 
 

sql

复制代码

<!--Redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--Redis--> <!--验证码--> <dependency> <groupId>com.github.whvcse</groupId> <artifactId>easy-captcha</artifactId> <version>1.6.2</version> </dependency> <!--验证码-->

之所以用redis的原因是用来存储验证码

第二步,编写redis配置文件

 
 

sql

复制代码

package com.wangfugui.apprentice.common.util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import java.io.Serializable; import java.util.concurrent.TimeUnit; /** * RedisUtils:redis工具类 */ @Component public class RedisUtils { @Autowired @Qualifier("getRedisTemplate") private RedisTemplate redisTemplate; @Autowired @Qualifier("getStringRedisTemplate") private StringRedisTemplate stringRedisTemplate; /** * 设置键值 * * @Param: [key, value] * @return: boolean * @Author: MaSiyi * @Date: 2021/11/20 */ public boolean set(final String key, Object value) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 设置键值(string) * * @Param: [key, value] * @return: boolean * @Author: MaSiyi * @Date: 2021/11/20 */ public boolean setStr(final String key, String value) { boolean result = false; try { ValueOperations<String, String> operations = stringRedisTemplate.opsForValue(); operations.set(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 设置键值(string) * * @Param: [key, value] * @return: boolean * @Author: MaSiyi * @Date: 2021/11/20 */ public boolean setStrEx(final String key, String value,long timeout, TimeUnit unit) { boolean result = false; try { stringRedisTemplate.opsForValue().set(key, value, timeout, unit); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 写入缓存设置失效时间 * * @param key * @param value * @return */ public boolean setEx(final String key, Object value, Long expireTime) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 设置key-value * <p> * 注: 若已存在相同的key, 那么原来的key-value会被丢弃 * * @param key key * @param value key对应的value * @param timeout 过时时长 * @param unit timeout的单位 * @date 2020/3/8 15:40:59 */ public void setEx(String key, String value, long timeout, TimeUnit unit) { redisTemplate.opsForValue().set(key, value, timeout, unit); } /** * 批量删除对应的value */ public void remove(final String... keys) { for (String key : keys) { remove(key); } } /** * 删除对应的value */ public void remove(final String key) { if (exists(key)) { redisTemplate.delete(key); } } /** * 判断缓存当中是否有对应的value * * @param key * @return */ public boolean exists(final String key) { return redisTemplate.hasKey(key); } /** * 根据key,获取到对应的value值 * * @param key key-value对应的key * @return 该key对应的值。 * 注: 若key不存在, 则返回null。 */ public Object get(String key) { return redisTemplate.opsForValue().get(key); } /** * 根据key,获取到对应的value(string)值 * * @param key key-value对应的key * @return 该key对应的值。 * 注: 若key不存在, 则返回null。 */ public String getStr(String key) { return stringRedisTemplate.opsForValue().get(key); } }

这里注入两个模板的原因是用来区分string类型和object的值

第三步,编写配置类

 
 

sql

复制代码

package com.wangfugui.apprentice.config; import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { /** * 重写Redis序列化方式,使用Json方式: * 当我们的数据存储到Redis的时候,我们的键(key)和值(value) * 都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer, * StringRedisTemplate默认使用的是StringRedisSerializer。 * Spring Data JPA为我们提供了下面的Serializer: * GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、 * JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。 * 在此我们将自己配置RedisTemplate并定义Serializer。 * * @param redisConnectionFactory * @return */ @Bean("getRedisTemplate") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); /** * 配置连接工厂 */ redisTemplate.setConnectionFactory(redisConnectionFactory); /** * 使用FJackson2JsonRedisSerializer序列化工具 */ FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); /** * 指定要序列化的域Field、set、get,以及修饰符范围 * ANY是都有,包括private、public */ objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); /** * 指定序列化输入的类型,类必须是非final修饰的, * final修饰的类,比如 * public final class User implements Serializable{},会包异常 */ objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); /** *设置键(key)的序列化采用StringRedisSerializer。 */ redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); /** * 设置值(value)的序列化采用jackson2JsonRedisSerializer。 */ redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } /** * 配置stringRedisTemplate序列化方式 * * @param redisConnectionFactory * @return */ @Bean("getStringRedisTemplate") @ConditionalOnMissingBean(StringRedisTemplate.class) public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } }

配置类这里设置了两个模板,分别对应了第二步的模板需求

第四步,编写controller类

 
 

sql

复制代码

package com.wangfugui.apprentice.controller; import com.wangfugui.apprentice.common.util.RedisUtils; import com.wangfugui.apprentice.common.util.ResponseUtils; import com.wf.captcha.SpecCaptcha; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.UUID; import java.util.concurrent.TimeUnit; @Api(tags = "验证码") @RestController @RequestMapping("captcha") public class CaptchaController { @Autowired private RedisUtils redisUtil; @ResponseBody @ApiOperation("生成验证码") @GetMapping("/makeCaptcha") public ResponseUtils makeCaptcha() { SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5); String verCode = specCaptcha.text().toLowerCase(); String key = UUID.randomUUID().toString(); // 存入redis并设置过期时间为30分钟 redisUtil.setStrEx(key, verCode, 30, TimeUnit.MINUTES); // 将key和base64返回给前端 HashMap<String, Object> map = new HashMap<>(); map.put("key", key); map.put("image", specCaptcha.toBase64()); return ResponseUtils.success(map); } @ResponseBody @ApiOperation("校验验证码") @PostMapping("/getCaptcha") public ResponseUtils getCaptcha(String verCode,String verKey){ // 获取redis中的验证码 String redisCode = redisUtil.getStr(verKey); // 判断验证码 if (verCode==null || !redisCode.equals(verCode.trim().toLowerCase())) { return ResponseUtils.error("验证码不正确"); } return ResponseUtils.success("验证成功"); } }

之后测试就行啦,生成样式举例: 

说在之后

师徒系统我会一直更新,因为是开源的项目,所以我也希望有更多的小伙伴加入进来!! 这是程序员师徒管理系统的地址: 程序员师徒管理系统 

猜你喜欢

转载自blog.csdn.net/BASK2312/article/details/131359650