.NET Core Web API 实现图形验证码

目录

1.关于ZKWeb.System.Drawing

2.绘制图形验证码

验证码信息实体类对象

 验证码类型枚举信息

 生成数字验证码

生成数字+字母验证码

生成数字运算验证码

绘制验证码图形

3.Api接口获取验证码及用户登录验证码验证

验证码获取接口示例

用户登录验证码验证接口示例

效果展示


本文介绍如何后端实现图形验证码,包括纯数字验证码、数字+字母验证码以及数字运算验证码

1.关于ZKWeb.System.Drawing

这是一个与.Net核心兼容的系统。绘图实现从mono项目修改而来。适用于windows和linux。

适用系统:

  • Windows 8.1 64bit
  • Ubuntu Server 16.04 LTS 64bit
  • Fedora 24 64bit
  • CentOS 7.2 64bit

 实现的功能:

  • 打开jpg, bmp, ico, png格式的图片
  • 保存 jpg, bmp, ico, png 格式的图片
  • 调整图片大小
  • 绘制图形
  • 打开字体并绘制字符串

2.绘制图形验证码

验证码信息实体类对象

    /// <summary>
    /// 验证码信息
    /// </summary>
    public class VerifyCode
    {
        /// <summary>
        /// 验证码
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 验证码数据流
        /// </summary>
        public byte[] Image { get; set; }
        /// <summary>
        /// base64
        /// </summary>
        public string Base64Str { get { return Convert.ToBase64String(Image); } }
    }

 验证码类型枚举信息

    /// <summary>
    /// 验证码类型
    /// </summary>
    public enum VerifyCodeType
    {
        [Description("纯数字验证码")]
        NUM=0,
        [Description("数字加字母验证码")]
        CHAR=1,
        [Description("数字运算验证码")]
        ARITH =2,
    }

 生成数字验证码

        /// <summary>
        /// 获取数字验证码
        /// </summary>
        /// <param name="n">验证码数</param>
        /// <returns></returns>
        public static string CreateNumCode(int n)
        {
            char[] numChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
            string charCode = string.Empty;
            Random random = new Random();
            for (int i = 0; i < n; i++)
            {
                charCode += numChar[random.Next(numChar.Length)];
            }
            return charCode;
        }

生成数字+字母验证码

        /// <summary>
        /// 获取字符验证码
        /// </summary>
        /// <param name="n">验证码数</param>
        /// <returns></returns>
        public static string CreateCharCode(int n)
        {
            char[] strChar = { 'a', 'b','c','d','e','f','g','h','i','j','k','l','m',
                'n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3',
                '4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K',
                'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

            string charCode = string.Empty;
            Random random = new Random();
            for (int i = 0; i < n; i++)
            {
                charCode += strChar[random.Next(strChar.Length)];
            }
            return charCode;
        }

生成数字运算验证码

        /// <summary>
        /// 获取运算符验证码
        /// </summary>
        /// <returns></returns>
        public static string CreateArithCode(out string resultCode)
        {
            string checkCode ="";
            Random random = new Random();
            int intFirst = random.Next(1, 20);//生成第一个数字
            int intSec = random.Next(1, 20);//生成第二个数字
            int intTemp = 0;
            switch (random.Next(1, 3).ToString())
            {
                case "2":
                    if (intFirst < intSec)
                    {
                        intTemp = intFirst;
                        intFirst = intSec;
                        intSec = intTemp;
                    }
                    checkCode = intFirst + "-" + intSec + "=";
                    resultCode = (intFirst - intSec).ToString();
                    break;
                default:
                    checkCode = intFirst + "+" + intSec + "=";
                    resultCode = (intFirst + intSec).ToString();
                    break;
            }
            return checkCode;
        }

绘制验证码图形

        /// <summary>
        /// 获取验证码
        /// </summary>
        /// <param name="n">验证码数</param>
        /// <param name="type">类型 0:数字 1:字符</param>
        /// <returns></returns>
        public static VerifyCode CreateVerifyCode(int n, VerifyCodeType type)
        {
            int codeW = 170;//宽度
            int codeH = 50;//高度
            int fontSize = 32;//字体大小
            //初始化验证码
            string charCode = string.Empty;
            string resultCode = "";
            switch (type.ToString())
            {
                case "NUM":
                    charCode = CreateNumCode(n);
                    break;
                case "ARITH":
                    charCode = CreateArithCode(out resultCode);
                    n = charCode.Length;
                    break;
                default:
                    charCode = CreateCharCode(n);
                    break;
            }
            //颜色列表
            Color[] colors = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.DarkBlue };
            //字体列表
            string[] fonts = { "Times New Roman", "Verdana", "Arial", "Gungsuh" };
            //创建画布
            Bitmap bitmap = new Bitmap(codeW, codeH);
            Graphics graphics = Graphics.FromImage(bitmap);
            graphics.Clear(Color.White);
            Random random = new Random();
            //画躁线
            for (int i = 0; i < n; i++)
            {
                int x1 = random.Next(codeW);
                int y1 = random.Next(codeH);
                int x2 = random.Next(codeW);
                int y2 = random.Next(codeH);
                Color color = colors[random.Next(colors.Length)];
                Pen pen = new Pen(color);
                graphics.DrawLine(pen, x1, y1, x2, y2);
            }
            //画噪点
            for (int i = 0; i < 100; i++)
            {
                int x = random.Next(codeW);
                int y = random.Next(codeH);
                Color color = colors[random.Next(colors.Length)];
                bitmap.SetPixel(x, y, color);
            }
            //画验证码
            for (int i = 0; i < n; i++)
            {
                string fontStr = fonts[random.Next(fonts.Length)];
                Font font = new Font(fontStr, fontSize);
                Color color = colors[random.Next(colors.Length)];
                graphics.DrawString(charCode[i].ToString(), font, new SolidBrush(color), (float)i * 30 + 5, (float)0);
            }
            //写入内存流
            try
            {
                MemoryStream stream = new MemoryStream();
                bitmap.Save(stream, ImageFormat.Jpeg);
                VerifyCode verifyCode = new VerifyCode()
                {
                    Code = type.ToString()== "ARITH" ? resultCode :charCode,
                    Image = stream.ToArray()
                };
                return verifyCode;
            }
            //释放资源
            finally
            {
                graphics.Dispose();
                bitmap.Dispose();
            }
        }

3.Api接口获取验证码及用户登录验证码验证

验证码获取接口示例

        /// <summary>
        /// 生成图片验证码
        /// </summary>
        /// <param name="codeType">验证码类型 0:纯数字 1:数字+字母 2:数字运算 默认1</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("captcha")]
        [Log(Title = "生成图片验证码")]
        public ApiResult Captcha(string codeType="1")
        {
            string uuid = Guid.NewGuid().ToString().Replace("-", "");
            var codeInfo = new CommonMethod.VerifyCode();
            if (codeType == "1")
            {
                codeInfo = CommonMethod.VerifyCodeHelper.CreateVerifyCode(4, CommonMethod.VerifyCodeType.CHAR);
            }
            else if (codeType == "2")
            {
                codeInfo = CommonMethod.VerifyCodeHelper.CreateVerifyCode(4, CommonMethod.VerifyCodeType.ARITH);
            }
            else if (codeType == "0")
            {
                codeInfo = CommonMethod.VerifyCodeHelper.CreateVerifyCode(4, CommonMethod.VerifyCodeType.NUM);
            }            
            CacheHelper.SetCache(uuid, codeInfo.Code);
            var obj = new { uuid, img = codeInfo.Base64Str };
            return ToJson(1, obj);
        }

用户登录验证码验证接口示例

        [Route("login")]
        [HttpPost]
        [Log(Title = "登录")]
        public IActionResult Login([FromBody] LoginBodyDto loginBody)
        {
            if (loginBody == null) { throw new CustomException("请求参数错误"); }
            loginBody.LoginIP = HttpContextExtension.GetClientUserIp(HttpContext);
            if (CacheHelper.Get(loginBody.Uuid) is string str && !str.ToLower().Equals(loginBody.Code.ToLower()))
            {
                return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误");
            }
            CacheHelper.Remove(loginBody.Uuid);//移除验证码
            SysLogininfor sysLogininfor = RecordLogInfo(httpContextAccessor.HttpContext);
            if (string.IsNullOrEmpty(sysLogininfor.CreateBy))
            {
                sysLogininfor.userName = loginBody.Username;
                sysLogininfor.CreateBy = loginBody.Username;
                sysLogininfor.CreateName = loginBody.Username;
            }
            var user = sysLoginService.Login(loginBody, sysLogininfor);
            List<SysRole> roles = roleService.SelectUserRoleListByUserId(user.ID);
            //权限集合 eg *:*:*,system:user:list
            List<string> permissions = permissionService.GetMenuPermission(user);
            LoginUser loginUser = new(user, roles, permissions);
            CacheService.SetUserPerms(GlobalConstant.UserPermKEY + user.ID, permissions);
            return SUCCESS(JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser), jwtSettings.JwtSettings));
        }

效果展示

 

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3.0 和 ASP.NET Core WebAPI 都支持动态路由,实现起来也比较简单。 首先,在 ASP.NET Core WebAPI 中,我们需要在 Startup.cs 中配置路由。可以使用以下代码: ``` app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action}/{id?}"); }); ``` 这个配置会将请求转发到对应的控制器和方法中。其中,{controller} 和 {action} 表示控制器和方法名,{id?} 表示可选参数。 接着,在 Vue 3.0 中,我们可以使用 vue-router 实现动态路由。可以使用以下代码: ``` const router = createRouter({ history: createWebHistory(), routes: [ { path: '/:controller/:action/:id?', name: 'dynamic', component: DynamicComponent } ] }) ``` 这个配置会将请求转发到 DynamicComponent 组件中。其中,:controller、:action 和 :id? 表示控制器、方法名和可选参数。 最后,我们可以在 DynamicComponent 组件中调用 ASP.NET Core WebAPI 中的动态路由。可以使用以下代码: ``` axios.get(`/api/${this.$route.params.controller}/${this.$route.params.action}/${this.$route.params.id}`) .then(response => { // 处理响应 }) .catch(error => { // 处理错误 }) ``` 这个代码会发送请求到对应的控制器和方法中,其中,this.$route.params.controller、this.$route.params.action 和 this.$route.params.id 分别对应控制器、方法名和参数。 以上就是 Vue 3.0 和 ASP.NET Core WebAPI 实现动态路由的基本步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值