年初,从外地转移阵地到西安,转眼已两个多月。很久不写业务代码了,到了新公司,条件恶劣到前所未有,从需求,设计,架构,实现,实施,测试,bug修复,项目计划制定,项目管理,全他妈我一个人,关键是平台很大,很多技术难点,时间还又紧,要命的是,公司销售左派盛行,连技术老大都是销售出身,直属领导设计出身不懂技术。。。点到为止,剩下的大家自行脑补。吐槽归吐槽,事儿还是得干,程序猿的基本素养不是。于是一个多月,996式搞法,项目上线了,其中包括那个我半天做出来的短信验证码。。。废话大半天,终于说到今天的重点了,那就言归正传。
对于短信验证码,前阵子,看到骚窝洞见分享了一篇短信验证码的文章(https://insights.thoughtworks.cn/sms-authentication-login-api/),感觉可以作为一个最佳实践了,老早就决定按照文中观点实践了,奈何那阵一直996,没时间,直到最近,才忙里偷闲动手整理。原文不再赘述,这里就文中对于短信验证码的关键要点,截图如下:
2.实现
首先,直接上解决方案截图:
典型的应用层 =》 服务层调用架构,采用接口层及IOC解耦。我们先看工具库,Captcha.Util,重点说下ImageCaptchaHelper与MsgCaptchaHelper。图形验证码,这里要致敬EdiWang,图形验证码直接盗版的他的(https://edi.wang/post/2018/10/13/generate-captcha-code-aspnet-core)。整个文件中代码太长,就不贴了,这里只给几个要点:
(1)生成图形验证码的工程,需要标记unsafe,如下:
这是因为图形验证码的生成有部分用到了指针相关,熟悉C#的朋友应该对这个背景知识不陌生:
不用关心这是啥啥啥,照着设置unsafe就成了,我他妈压根儿就懒得看这段指针代码,就是看了也不一定看得懂。。。
(2)图形验证码的位置调整:
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); } }