图形验证码+短信验证码实战

您所在的位置:网站首页 图片验证码怎样才能正确输入 图形验证码+短信验证码实战

图形验证码+短信验证码实战

2024-07-16 10:53| 来源: 网络整理| 查看: 265

前言:

  上一篇分分享了基于阿里云实现的短信验证码文章,考虑到为了防止登录时,非人工操作,频繁获取验证码,趁热打铁,现在添加了图片验证码服务功能。借鉴网上传统的做法,把实现这两个验证的功能做成有个独立的服务,通过Http分别请求获取校验图片验证码和短信验证码。

一、需求描述: 图形验证码为,短信验证码为6位纯数字 同一系统图片验证码缓存中只存在一个,没有有效期,每次刷新更新旧图形验证码 短信验证码有效期2分钟 每个手机号60秒内只能发送一次短信验证码,在服务器端执行校验 同一个手机号在同一时间内可以有多个有效的短信验证码,根据不同系统类型区分 每个短信验证码至多可被使用3次,无论和请求中的验证码是否匹配,随后立即作废,以防止暴力攻击 发送短信验证码之前,先验证图形验证码是否正确 二、图片验证码实现: 生成随机验证码字符串: /// /// 获取随机验证码 /// /// public static string GenerateCaptchaCode() { Random rand = new Random(); int maxRand = Letters.Length - 1; StringBuilder sb = new StringBuilder(); for (int i = 0; i < 4; i++) { int index = rand.Next(maxRand); sb.Append(Letters[index]); } return sb.ToString(); } 随机验证码生成验证码图片: /// /// 生成随机验证码图片 /// /// /// /// /// public static CaptchaResult GenerateCaptcha(int width, int height, string captchaCode) { using (Bitmap baseMap = new Bitmap(width, height)) using (Graphics graph = Graphics.FromImage(baseMap)) { Random rand = new Random(); graph.Clear(GetRandomLightColor()); DrawCaptchaCode(); DrawDisorderLine(); AdjustRippleEffect(); MemoryStream ms = new MemoryStream(); baseMap.Save(ms, ImageFormat.Png); return new CaptchaResult { CaptchaCode = captchaCode, CaptchaByteData = ms.ToArray(), Timestamp = DateTime.Now }; int GetFontSize(int imageWidth, int captchCodeCount) { var averageSize = imageWidth / captchCodeCount; return Convert.ToInt32(averageSize); } Color GetRandomDeepColor() { int redlow = 160, greenLow = 100, blueLow = 160; return Color.FromArgb(rand.Next(redlow), rand.Next(greenLow), rand.Next(blueLow)); } Color GetRandomLightColor() { int low = 180, high = 255; int nRend = rand.Next(high) % (high - low) + low; int nGreen = rand.Next(high) % (high - low) + low; int nBlue = rand.Next(high) % (high - low) + low; return Color.FromArgb(nRend, nGreen, nBlue); } void DrawCaptchaCode() { SolidBrush fontBrush = new SolidBrush(Color.Black); int fontSize = GetFontSize(width, captchaCode.Length); Font font = new Font(FontFamily.GenericSerif, fontSize, FontStyle.Bold, GraphicsUnit.Pixel); for (int i = 0; i < captchaCode.Length; i++) { fontBrush.Color = GetRandomDeepColor(); int shiftPx = fontSize / 6; //float x = i * fontSize + rand.Next(-shiftPx, shiftPx) + rand.Next(-shiftPx, shiftPx); float x = i * fontSize + rand.Next(-shiftPx, shiftPx) / 2; //int maxY = height - fontSize; int maxY = height - fontSize * 2; if (maxY < 0) { maxY = 0; } float y = rand.Next(0, maxY); graph.DrawString(captchaCode[i].ToString(), font, fontBrush, x, y); } } void DrawDisorderLine() { Pen linePen = new Pen(new SolidBrush(Color.Black), 2); //for (int i = 0; i < rand.Next(3, 5); i++) for (int i = 0; i < 2; i++) { linePen.Color = GetRandomDeepColor(); Point startPoint = new Point(rand.Next(0, width), rand.Next(0, height)); Point endPoint = new Point(rand.Next(0, width), rand.Next(0, height)); graph.DrawLine(linePen, startPoint, endPoint); //Point bezierPoint1 = new Point(rand.Next(0, width), rand.Next(0, height)); //Point bezierPoint2 = new Point(rand.Next(0, width), rand.Next(0, height)); //graph.DrawBezier(linePen, startPoint, bezierPoint1, bezierPoint2, endPoint); } } void AdjustRippleEffect() { short nWave = 6; int nWidth = baseMap.Width; int nHeight = baseMap.Height; Point[,] pt = new Point[nWidth, nHeight]; for (int x = 0; x < nWidth; ++x) { for (int y = 0; y < nHeight; ++y) { var xo = nWave * Math.Sin(2.0 * 3.1415 * y / 128.0); var yo = nWave * Math.Cos(2.0 * 3.1415 * x / 128.0); var newX = x + xo; var newY = y + yo; if (newX > 0 && newX < nWidth) { pt[x, y].X = (int)newX; } else { pt[x, y].X = 0; } if (newY > 0 && newY < nHeight) { pt[x, y].Y = (int)newY; } else { pt[x, y].Y = 0; } } } Bitmap bSrc = (Bitmap)baseMap.Clone(); BitmapData bitmapData = baseMap.LockBits(new Rectangle(0, 0, baseMap.Width, baseMap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int scanline = bitmapData.Stride; IntPtr scan0 = bitmapData.Scan0; IntPtr srcScan0 = bmSrc.Scan0; unsafe { byte* p = (byte*)(void*)scan0; byte* pSrc = (byte*)(void*)srcScan0; int nOffset = bitmapData.Stride - baseMap.Width * 3; for (int y = 0; y < nHeight; ++y) { for (int x = 0; x < nWidth; ++x) { var xOffset = pt[x, y].X; var yOffset = pt[x, y].Y; if (yOffset >= 0 && yOffset < nHeight && xOffset >= 0 && xOffset < nWidth) { if (pSrc != null) { p[0] = pSrc[yOffset * scanline + xOffset * 3]; p[1] = pSrc[yOffset * scanline + xOffset * 3 + 1]; p[2] = pSrc[yOffset * scanline + xOffset * 3 + 2]; } } p += 3; } p += nOffset; } } baseMap.UnlockBits(bitmapData); bSrc.UnlockBits(bmSrc); bSrc.Dispose(); } } } 三、短信验证码实现: 见上篇:

传送门:基于Aliyun短信验证码实现

四、图片验证码获取与校验: 获取:

代码:

/// /// 获取图片验证码 /// /// 图形验证码请求信息 [HttpGet("img")] public IActionResult GetImageCaptcha([FromQuery]ImgCaptchaDto imgCaptchaDto) { var result = _captchaService.GetImageCaptcha(imgCaptchaDto); var stream = new MemoryStream(result.CaptchaByteData); return new FileStreamResult(stream, "image/png"); }

Http调用:详细调用参数和方式见下方接口在线文档。 image

校验:

代码:

/// /// 验证图片验证码 /// /// 图形验证码信息 /// [HttpPost("img")] public IActionResult ValidateImageCaptcha(ImgCaptchaDto imgCaptchaDto) { bool isCaptchaValid = _captchaService.ValidateImageCaptcha(imgCaptchaDto); if (isCaptchaValid) { HttpResponseDto httpResponseDto = new HttpResponseDto() { IsSuccess = true, Code = StatusCodes.Status200OK, Message = "图形验证码验证成功" }; var responJson = JsonConvert.SerializeObject(httpResponseDto); return Ok(responJson); } else { HttpResponseDto httpResponseDto = new HttpResponseDto() { IsSuccess = false, Code = StatusCodes.Status403Forbidden, Message = "验证失败,请输入正确手机号及获取到的验证码" }; var responJson = JsonConvert.SerializeObject(httpResponseDto); return StatusCode(StatusCodes.Status403Forbidden, responJson); } }

Http调用:详细调用参数和方式见下方接口在线文档。 image

五、短信验证码获取与校验: 获取:

代码:

/// /// 获取短信验证码 /// /// 短信验证码请求信息 /// [HttpGet("msg")] public IActionResult GetMsgCaptcha([FromQuery]MsgCaptchaDto msgCaptchaDto) { var msgSendResult = _captchaService.GetMsgCaptcha(msgCaptchaDto); if (msgSendResult.Item1) { return Ok(msgSendResult.Item2); } else { return StatusCode(StatusCodes.Status403Forbidden, msgSendResult.Item2); } }

Http调用:详细调用参数和方式见下方接口在线文档。 image

image

校验:

代码:

/// /// 验证短信验证码 /// /// 短信验证码信息 /// [HttpPost("msg")] public IActionResult ValidateMsgCaptcha(MsgCaptchaDto msgCaptchaDto) { var validateResult = _captchaService.ValidateMsgCaptcha(msgCaptchaDto); if (validateResult.Item1) { HttpResponseDto httpResponseDto = new HttpResponseDto() { IsSuccess = true, Code = StatusCodes.Status200OK, Message = validateResult.Item2 }; var responJson = JsonConvert.SerializeObject(httpResponseDto); return Ok(responJson); } else { HttpResponseDto httpResponseDto = new HttpResponseDto() { IsSuccess = false, Code = StatusCodes.Status403Forbidden, Message = validateResult.Item2 }; var responJson = JsonConvert.SerializeObject(httpResponseDto); return StatusCode(StatusCodes.Status403Forbidden, responJson); } }

Http调用:详细调用参数和方式见下方接口在线文档。 image

源码链接地址: Gitee完整实例地址:

https://gitee.com/mingliang_it/Captcha

接口在线文档: 链接地址:

https://console-docs.apipost.cn/preview/82c61b0950bae0c8/924487d25ec3df36

本文来自博客园,作者:码农阿亮,转载请注明原文链接:https://www.cnblogs.com/wml-it/p/17617097.html

技术的发展日新月异,随着时间推移,无法保证本博客所有内容的正确性。如有误导,请大家见谅,欢迎评论区指正! 开源库地址,欢迎点亮: GitHub:https://github.com/ITMingliang Gitee:   https://gitee.com/mingliang_it GitLab: https://gitlab.com/ITMingliang 建群声明: 本着技术在于分享,方便大家交流学习的初心,特此建立【编程内功修炼交流群】,为大家答疑解惑。热烈欢迎各位爱交流学习的程序员进群,也希望进群的大佬能不吝分享自己遇到的技术问题和学习心得!进群方式:扫码关注公众号,后台回复【进群】。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3