一、效果图

二、实现生成图形验证码、校验验证码

1、实现后端接口

①控制层代码

 /*** 生成图片验证码* time用于保证每次可以刷新图片验证码*/@GetMapping("authCode/{time}")public void getAuthCode(@PathVariable("time")String time, HttpServletRequest request, HttpServletResponse response) throws IOException {loginService.getAuthCode(request,response);}/*** 验证图片验证码*/@GetMapping("verifyCode/{inputVerify}")public Result verifyCode(@PathVariable("inputVerify") String inputVerify, HttpServletRequest request){Boolean bool = loginService.verifyCode(inputVerify,request);return new Result(1,"已验证",bool);}

②业务层代码

 /*** 生成图片验证码*/@Overridepublic void getAuthCode(HttpServletRequest request, HttpServletResponse response) throws IOException {//req.setCharacterEncoding("utf-8");//res.setContentType("text/html;charset=utf-8");// 设置http响应的文件MIME类型为图片response.setContentType("image/jpeg");// 不让浏览器记录此图片的缓存response.setDateHeader("expries", -1);response.setHeader("Cache-Control", "no-cache");response.setHeader("Pragma", "no-cache");// 这里调用了一个工具类VerifyCodeUtils来生成指定位数(也可指定内容)的验证码字符串String verifyCode = VerifyCodeUtils.generateVerifyCode(4);// 将生成验证码字符串保存到session域中,方面进行表单验证request.getSession().setAttribute("verifyCode", verifyCode);VerifyCodeUtils.outputImage(60, 30, response.getOutputStream(), verifyCode);}/*** 验证图片验证码*/@Overridepublic Boolean verifyCode(String inputVerify, HttpServletRequest request) {String verifyCode = (String) request.getSession().getAttribute("verifyCode");return inputVerify.equalsIgnoreCase(verifyCode);}

③工具类:画图、校验

里面包含多种方法,和传递方式,这里我采用的是将图片流传入请求头的session域中,也可以存到本地

public class VerifyCodeUtils{// 可自定义验证码字符源public static final String VERIFY_CODES = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";/*** 使用系统默认字符源生成验证码* @param verifySize 验证码长度* @return*/public static String generateVerifyCode(int verifySize){return generateVerifyCode(verifySize, VERIFY_CODES);}/*** 使用指定源生成验证码* @param verifySize 验证码长度* @param sources   验证码字符源* @return*/public static String generateVerifyCode(int verifySize, String sources){if(sources == null || sources.length() == 0){sources = VERIFY_CODES;}int codesLen = sources.length();Random rand = new Random(System.currentTimeMillis());StringBuilder verifyCode = new StringBuilder(verifySize);for(int i = 0; i < verifySize; i++){verifyCode.append(sources.charAt(rand.nextInt(codesLen-1)));}return verifyCode.toString();}/*** 生成随机验证码文件,并返回验证码值* @param w 图片宽(像素)* @param h 图片高(像素)* @param outputFile* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException{String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, outputFile, verifyCode);return verifyCode;}/*** 输出随机验证码图片流,并返回验证码值* @param w* @param h* @param os* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException{String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, os, verifyCode);return verifyCode;}/*** 生成指定验证码图像文件* @param w* @param h* @param outputFile* @param code* @throws IOException*/public static void outputImage(int w, int h, File outputFile, String code) throws IOException{if(outputFile == null){return;}File dir = outputFile.getParentFile();if(!dir.exists()){dir.mkdirs();}try{outputFile.createNewFile();FileOutputStream fos = new FileOutputStream(outputFile);outputImage(w, h, fos, code);fos.close();} catch(IOException e){throw e;}}/*** 输出指定验证码图片流* @param w* @param h* @param os* @param code* @throws IOException*/public static void outputImage(int w,int h,OutputStream os,String code) throws IOException{int verifySize = code.length();BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);Random rand = new Random();Graphics2D g2 = image.createGraphics();Color[] colors = new Color[5];Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN,Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,Color.PINK, Color.YELLOW };float[] fractions = new float[colors.length];for(int i = 0; i < colors.length; i++){colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];fractions[i] = rand.nextFloat();}Arrays.sort(fractions);Paint linearPaint = new LinearGradientPaint(0, 0, w, h, fractions, colors);Paint linearPaint2 = new LinearGradientPaint(0, 0, w, h, new float[]{0.3f, .6f, .8f, .9f}, new Color[]{Color.BLUE, Color.BLACK, Color.GREEN, Color.BLUE});//设置图片背景为白色g2.setPaint(Color.WHITE);g2.fillRect(0, 0, w, h);//设置图片渐变背景g2.setPaint(linearPaint);g2.fillRoundRect(0, 0, w, h, 5, 5);g2.setPaint(linearPaint2);int fontSize = (int) (Math.min(w/verifySize, h));Font font = new Font("微软雅黑", Font.BOLD, fontSize);g2.setFont(font);char[] chars = code.toCharArray();for(int i = 0; i < verifySize; i++){AffineTransform affine = new AffineTransform();affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);g2.setTransform(affine);g2.drawChars(chars, i, 1, (w / verifySize) * i, h/2 + fontSize /2);}g2.dispose();ImageIO.write(image, "jpg", os);}//public static void main(String[] args) throws IOException{//    File dir = new File("D:/image");//    int w = 200, h = 80;//    for(int i = 0; i < 100; i++){//        String verifyCode = generateVerifyCode(4);//        File file = new File(dir, verifyCode + ".jpg");//        outputImage(w, h, file, verifyCode);//    }//}
}

2、前端实现

前端采用的是vue3+ts+element-plus

验证码单独提取出一个组件

<div><img :src="data:image" style="height: 60px" @click="changeImage" /><span@click="changeImage">看不清点击换一张</span>
</div>
  // 图片urlconst image = ref(url.value + '/authCode/1');  // 此处为图片生成接口的完整路径// 更换图片方法const changeImage = () => {image.value = url.value + '/authCode/' + getNowTime();};// 加一个当前时间,确保每次刷新都可以重新发送请求function getNowTime() {var date = new Date();//年 getFullYear():四位数字返回年份var year = date.getFullYear(); //getFullYear()代替getYear()//月 getMonth():0 ~ 11var month = date.getMonth() + 1;//日 getDate():(1 ~ 31)var day = date.getDate();//时 getHours():(0 ~ 23)var hour = date.getHours();//分 getMinutes(): (0 ~ 59)var minute = date.getMinutes();//秒 getSeconds():(0 ~ 59)var second = date.getSeconds();var time = '当前时间是:' + year + month + day + hour + minute + second;return time;}

form表单

<el-form-item><image-check /></el-form-item> <!-- 引入子组件 -->
<el-form-item label="图形验证码" prop="checkNum"><el-inputv-model="registerData.checkNum"placeholder="请输入图形验证码"/>
</el-form-item>
  const ruleFormRef = ref<FormInstance>();  // 图形验证码校验规则const validateCheckNum = (rule: any, value: string, callback: any) => {if (value === '') {callback(new Error('请输入验证码'));} else {// 发送校验请求getImageCode(value).then((res) => {if (res) {callback();} else {callback(new Error('验证码错误'));}});}};// 表单校验规则const rules = reactive({checkNum: [{ validator: validateCheckNum, trigger: 'blur' }]});

三、实现手机短信发送,以及短信验证

1、后端接口实现

①因为借助的是阿里云的测试短信,所以需要引入依赖

<!-- 阿里云 短信验证依赖、sdk 依赖 -->
<dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.6.0</version>
</dependency>
<dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-dysmsapi</artifactId><version>2.2.1</version>
</dependency>

②控制层代码

/*** 发送短信验证码*/@PostMapping ("sendMessage")public Result sendMessage(@RequestBody String phoneNo,HttpServletRequest request){loginService.sendMessage(phoneNo,request);return new Result(1,"发送验证码成功","发送验证码成功");}/*** 短信验证码验证*/@PostMapping ("receiveMessage")public Result receiveMessage(@RequestBody String PhoneCode,HttpServletRequest request) {String result = loginService.receiveMessage(PhoneCode,request);return new Result(1,result,result);}

③业务层代码

将验证码的key保存到session域中,方面进行验证码验证,并且存入redis设置一分钟过期

/*** 发送短信验证码*/@Overridepublic void sendMessage(String phoneNo, HttpServletRequest request) {// 这里最好也做一次手机号码校验,我这里偷懒没做Boolean bool = IsMobile.isMobile(phoneNo);String randomCode = String.valueOf((int)((Math.random()*9+1)*100000));WebUtil.sendMessage(phoneNo,randomCode);//当前时间SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");Date date = new Date(System.currentTimeMillis());String format = formatter.format(date);// 将验证码的key保存到session域中,方面进行验证码验证request.getSession().setAttribute("phoneKey", "phone"+format);// 存入redisredisTemplate.opsForValue().set("phone"+format,randomCode,60, TimeUnit.SECONDS);}/*** 短信验证码验证*/@Overridepublic String receiveMessage(String phoneCode, HttpServletRequest request) {String phoneKey = (String) request.getSession().getAttribute("phoneKey");if(!StringUtils.isEmpty(phoneKey)){System.err.println(redisTemplate.hasKey(phoneKey));if(Boolean.TRUE.equals(redisTemplate.hasKey(phoneKey))){String phoneKey1 = redisTemplate.opsForValue().get(phoneKey);if(Objects.equals(phoneKey1, phoneCode)){return "验证成功";}else {return "验证错误";}}else {return "验证超时";}}else {return "请求体没有phoneKey的值";}}

④发送短信工具类

下面的key和keysecret需要去登录自己的阿里云账号查看,因为用的是短信测试,所以其他配置信息都只能使用默认的

public class WebUtil {/*** 发送短信验证码方法* @param phoneNum* @param messageCode*/public static void sendMessage(String phoneNum,String messageCode) {DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "你的key", "你的keysecret");/** use STS TokenDefaultProfile profile = DefaultProfile.getProfile("<your-region-id>",           // The region ID"<your-access-key-id>",       // The AccessKey ID of the RAM account"<your-access-key-secret>",   // The AccessKey Secret of the RAM account"<your-sts-token>");          // STS Token**/IAcsClient client = new DefaultAcsClient(profile);SendSmsRequest request = new SendSmsRequest();request.setSignName("阿里云短信测试");request.setTemplateCode("SMS_154950909");request.setPhoneNumbers(phoneNum);request.setTemplateParam("{\"code\":"+messageCode+"}");try {SendSmsResponse response = client.getAcsResponse(request);System.out.println(new Gson().toJson(response));} catch (ServerException e) {e.printStackTrace();} catch (ClientException e) {System.out.println("ErrCode:" + e.getErrCode());System.out.println("ErrMsg:" + e.getErrMsg());System.out.println("RequestId:" + e.getRequestId());}}
}

2、前端实现

前端采用的是vue3+ts+element-plus

form表单

<el-form-item label="手机号" prop="phoneNo"><el-input v-model="registerData.phoneNo" placeholder="请输入手机号"><template #prepend><span style="width: 0px; margin: 0 0 0 -25px">+86</span></template></el-input></el-form-item><el-form-item label="手机验证码" prop="checkPhoneNo"><el-inputv-model="registerData.checkPhoneNo"placeholder="请输入手机验证码"style="width: 160px"/><el-button:disabled="disabled"type="primary"style="width: 80px; margin-left: 10px"@click="getCheckPhoneNo">{{ getPhoneCodeName }}</el-button></el-form-item><el-form-item label=""><span v-show="isCheckDesc === true" style="color: red">{{checkDesc}}</span>
</el-form-item>
  const ruleFormRef = ref<FormInstance>();  // 获取短信验证码按钮名称const getPhoneCodeName = ref('获取验证码');// 获取短信验证码按钮是否启用const disabled = ref(false);// 短信验证码按钮倒计时时间const timeNum = ref(60);// 发送验证码后的提示内容const checkDesc = ref('验证码已发送,可能会有延迟,请注意查收');// 发送验证码后的提示内容是否展示const isCheckDesc = ref(false);// 手机验证码校验规则const validateCheckPhoneNo = (rule: any, value: string, callback: any) => {if (value === '') {callback(new Error('请输入手机验证码'));} else {receiveMessage(value).then((res) => {if (res === '验证超时') {callback(new Error('验证码已超时,请重新发送'));} else if (res === '验证错误') {callback(new Error('验证码错误,请重新输入'));} else if (res === '请求体没有phoneKey的值') {callback(new Error('请先发送验证码'));} else {isCheckDesc.value = false;callback();}});}};// 表单校验规则const rules = reactive({checkPhoneNo: [{ validator: validateCheckPhoneNo, trigger: 'blur' }],});// 获取手机验证码方法const getCheckPhoneNo = () => {const reg =/^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/;if (!reg.test(registerData.phoneNo)) {ElMessage({message: '请先正确输入手机号',type: 'warning'});return;}disabled.value = true;sendMessage(registerData.phoneNo).then((res) => {if (res === '手机号格式错误') {ElMessage({message: '请先正确输入手机号',type: 'warning'});disabled.value = false;return;} else {isCheckDesc.value = true;let timer = setInterval(() => {--timeNum.value;getPhoneCodeName.value = `重新发送 ${timeNum.value}`;}, 1000);setTimeout(() => {clearInterval(timer);timeNum.value = 60;disabled.value = false;getPhoneCodeName.value = '获取验证码';}, 60000);}});};

java+vue3实现生成、验证图形验证码,和手机短信验证码相关推荐

  1. Flask项目实战——6—(前台用户模型、前台登录注册、图形验证码、手机短信验证码、添加表单验证短信验证码请求)

    1.前台用户模型 前台用户模型定义 创建前台模型文件 apps/front/models.py # -*- encoding: utf-8 -*- """ @File : ...

  2. java 随机手机验证码_基于Java随机生成手机短信验证码的实例代码|chu

    简单版 /** * 产生4位随机数(0000-9999) * * @return 4位随机数 */ public static String getFourRandom() { return Stri ...

  3. java生成短信验证码_Java随机生成手机短信验证码的方法

    本文实例讲述了Java随机生成手机短信验证码的方法.分享给大家供大家参考,具体如下: /** * 创建指定数量的随机字符串 * @param numberFlag 是否是数字 * @param len ...

  4. java 随机手机验证码_Java实现随机生成手机短信验证码的简单代码

    这篇文章主要介绍了Java随机生成手机短信验证码的方法,涉及Java数学运算计算随机数及字符串操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下 本文实例讲述了Java随机生成手机短信验证码的 ...

  5. java+生成手机验证码_基于Java随机生成手机短信验证码的实例代码

    简单版 /** * 产生4位随机数(0000-9999) * * @return 4位随机数 */ public static String getFourRandom() { return Stri ...

  6. Java调用WebService接口实现发送手机短信验证码功能,java 手机验证码,WebService接口调用...

    近来由于项目需要,需要用到手机短信验证码的功能,其中最主要的是用到了第三方提供的短信平台接口WebService客户端接口,下面我把我在项目中用到的记录一下,以便给大家提供个思路,由于本人的文采有限, ...

  7. Java调用WebService接口实现发送手机短信验证码功能

    为什么80%的码农都做不了架构师?>>>    一.样式示例: 二.前台的注册页面的代码:reg.jsp <%@ page language="java" ...

  8. java调接口实现发送手机短信验证码功能,手机验证码,接口调用

    原文地址:  http://blog.csdn.net/sxdtzhaoxinguo/article/details/34437591 近来由于项目需要,需要用到手机短信验证码的功能,其中最主要的是用 ...

  9. JAVA外卖项目第五天 套餐模块和短信验证码

    瑞吉外卖-第五天 课程内容 新增套餐 套餐分页查询 删除套餐 短信发送 手机验证码登录 1. 新增套餐 1.1 需求分析 套餐就是菜品的集合. 后台系统中可以管理套餐信息,通过新增套餐功能来添加一个新 ...

  10. java 实现语音报警代码_Java实现发送手机短信语音验证功能代码实例

    这篇文章主要介绍了Java实现发送手机短信语音验证功能代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 利用第三方平台可以实现发送手机短信验证 ...

最新文章

  1. Ubuntu 14.04 64bit上磁力链爬虫dht部署指南
  2. 二分图的匹配问题以及求解算法
  3. MySQL返回多行错误怎么处理_结果包含多个行错误mysql
  4. Python2 Python3 爬取赶集网租房信息,带源码分析
  5. python函数体以冒号起始、并且是缩进格式的_函数体以冒号起始,并且是缩进格式的。(3.0分)_学小易找答案...
  6. Certificate Transparency 那些事 | JerryQu 的小站
  7. mysql2008分数约束_关于SQL2008对表中列的约束
  8. 屈臣氏供应链数据分析
  9. U盘写保护不能格式化文件不能删除解决办法
  10. python zip压缩_用Python处理ZIP压缩包
  11. vue 项目使用Standardjs进行语法错误检测和修复
  12. 阿里巴巴2018秋招面经之前端岗(1~5面)
  13. 首位文博虚拟宣推官“文夭夭”上岗
  14. 《StereoDRNet: Dilated Residual StereoNet》
  15. spring boot 项目重新搭建----------mvc配置:拦截器
  16. extern C 引起的 error C2059
  17. Spark教程——(10)Spark SQL读取Phoenix数据本地执行计算
  18. 远景能源面试+高管终面
  19. org.apache.hadoop.hive.ql.exec.mr.MapredLocalTask
  20. Windows pytorch编译安装SoftPool

热门文章

  1. JAVA语言的由来以及相关情况介绍
  2. 人人农场机器人v3.0测试版 正式发布
  3. 计算机二级长春光华学院,长春光华学院排名2021 吉林排名第3全国排名第73
  4. python名片管理系统难点总结_Python学习笔记之名片管理系统
  5. 云渲染是什么?云渲染好处以及安装方法。
  6. CST shape tools
  7. HDMI Type A、B、C、D接口图
  8. Java文件完整性校验SHA256
  9. 企业钉钉群发送信息轮子
  10. 森林防火监控系统解决方案及标准权威解读