• 滑动验证码


    简单几步实现滑动验证码(后端验证)

     

    LazySlideCaptcha

    介绍

    LazySlideCaptcha是基于.Net Standard 2.1的滑动验证码模块。项目同时提供一个基于vue2的演示前端组件背景图裁剪工具
    【码云地址】 | 【Github 地址】

    图形验证码请移步lazy-captcha

    在线体验点这里

    快速开始

    1. 安装
    Install-Package Lazy.SlideCaptcha.Core
    
    dotnet add package Lazy.SlideCaptcha.Core
    
    1. 注册并配置服务
    builder.Services.AddSlideCaptcha(builder.Configuration);
    
    // 如果使用redis分布式缓存
    //builder.Services.AddStackExchangeRedisCache(options =>
    //{
    //    options.Configuration = builder.Configuration.GetConnectionString("RedisCache");
    //    options.InstanceName = "captcha:";
    //});
    
    "SlideCaptcha": {
        "Backgrounds": [
          {
            "Type": "file",
            "Data": "wwwroot/images/background/1.jpg"
          },
          {
            "Type": "file",
            "Data": "wwwroot/images/background/2.jpg"
          }
        ]
      }
    

    背景图片要求尺寸要求为 552 X 344 , 快速开始可在 Demo 项目 wwwroot/images/background 下挑选。(仅用作演示,生产请自行制作。)也可以通过裁剪工具制作,非常简单,上传图片,拖动范围后保存自动生成 552 X 344 图片。

    1. 接口定义
    [Route("api/[controller]")]
    [ApiController]
    public class CaptchaController : ControllerBase
    {
        private readonly ICaptcha _captcha;
    
        public CaptchaController(ICaptcha captcha)
        {
            _captcha = captcha;
        }
    
        /// <summary>
        /// id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Route("gen")]
        [HttpGet]
        public CaptchaData Generate()
        {
            return _captcha.Generate();
        }
    
        /// <summary>
        /// id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Route("check")]
        [HttpPost]
        public bool Validate([FromQuery]string id, SlideTrack track)
        {
            return _captcha.Validate(id, track);
        }
    }
    
    

    至此后端Api服务已搭建完成。

    1. 前端
      前端提供演示组件lazy-slide-captcha,可通过npm安装。Demo项目为了演示方便直接采用script直接引入方式。
    @{
        ViewData["Title"] = "滑动验证码";
    }
    
    <link rel="stylesheet" href="~/lib/lazy-slide-captcha/dist/lazy-slide-captcha.css" asp-append-version="true" />
    
    <style>
        #app {
            display: flex;
            align-items: center;
            justify-content: center;
        }
    
        .panel {
            padding: 20px;
            box-shadow: inherit;
            border-radius: 6px;
            box-shadow: 0 0 4px 0 #999999;
            margin-top: 100px;
        }
    </style>
    
    <div id="app">
        <div class="panel">
            <lazy-slide-captcha ref="captcha" :width="width" :height="height" :show-refresh="true" :fail-tip="failTip" :success-tip="successTip" @@finish="handleFinish" @@refresh="generate"></lazy-slide-captcha>
        </div>
    </div>
    
    
    @section Scripts{
        <script src="~/lib/vue/vue.min.js"></script>
        <script src="~/lib/vue/axios.min.js"></script>
        <script src="~/lib/lazy-slide-captcha/dist/lazy-slide-captcha.umd.js"></script>
    
        <script>
            var app = new Vue({
                 el: '#app',
                 data(){
                    return {
                        requestId: undefined,
                        failTip: '',
                        successTip: '',
                        // width,height保持与552 * 344同比例即可
                         340,
                        height: 212
                    }
                 },
                 mounted(){
                     this.generate()
                 },
                 methods:{
                     generate(){
                         // 改变内部状态,标识生成请求开始
                         this.$refs.captcha.startRequestGenerate()
    
                         axios.get('/api/captcha/gen')
                           .then((response) => {
                               this.requestId = response.data.id
                               // 改变内部状态,标识生成请求结束,同时设定background,slider图像
                               this.$refs.captcha.endRequestGenerate(response.data.backgroundImage, response.data.sliderImage)
                           })
                           .catch((error) => {
                               console.log(error);
                               // 标识生成请求结束
                               this.$refs.captcha.endRequestGenerate(null, null)
                           });
                     },
                     handleFinish(data){
                         // 改变内部状态,标识验证请求开始
                         this.$refs.captcha.startRequestVerify()
    
                         axios.post(`/api/captcha/check?id=${this.requestId}`, data)
                           .then((response) => {
                               let success = response.data.result === 0
                               // 验证失败时显示信息
                               this.failTip = response.data.result == 1 ? '验证未通过,拖动滑块将悬浮图像正确合并' : '验证超时, 请重新操作'
                               // 验证通过时显示信息
                               this.successTip = '验证通过,超过80%用户'
                               // 改变内部状态,标识验证请求结束,同时设定是否成功状态
                               this.$refs.captcha.endRequestVerify(success)
    
                               if(!success){
                                    setTimeout(() => {
                                        this.generate()
                                    }, 1000)
                               }
                           })
                           .catch((error) => {
                             console.log(error);
                             this.failTip = '服务异常,请稍后重试'
                             // 标识验证请求结束
                             this.$refs.captcha.endRequestVerify(false)
                           });
                     }
                 }
            });
        </script>
    }
    
    折叠

    至此,一个完整的滑动验证已实现,开启服务体验吧。

    配置说明

    支持配置文件和代码配置,同时配置则代码配置覆盖配置文件。

    • 配置文件
    "SlideCaptcha": {
        "ExpirySeconds": 60, // 缓存过期时长
        "StoreageKeyPrefix": "", // 缓存前缀
        "Tolerant": 0.02, // 容错值(校验时用,缺口位置与实际滑动位置匹配容错范围)
        "Backgrounds": [ // 背景图配置
          {
            "Type": "file",
            "Data": "wwwroot/images/background/1.jpg"
          }
        ],
        // Templates不配置,则使用默认模板
        "Templates": [
          {
            "Slider": {
              "Type": "file",
              "Data": "wwwroot/images/template/1/slider.png"
            },
            "Hole": {
              "Type": "file",
              "Data": "wwwroot/images/template/1/hole.png"
            }
          }
        ]
      }
    
    • 代码配置
    builder.Services.AddSlideCaptcha(builder.Configuration, options =>
    {
        options.Tolerant = 0.02f;
        options.StoreageKeyPrefix = "slider-captcha";
    
        options.Backgrounds.Add(new Resource(FileResourceHandler.TYPE, @"wwwroot/images/background/1.jpg"));
        options.Templates.Add
        (
            TemplatePair.Create
            (
                new Resource(FileResourceHandler.TYPE, @"wwwroot/images/template/1/slider.png"),
                new Resource(FileResourceHandler.TYPE, @"wwwroot/images/template/1/hole.png")
            )
        );
    });
    

    扩展

    1. Template自定义
      Template 是指用于生成凹槽和拖块的图片,可通过Templates配置节点设置自定义Template。 默认五个 Template (不要配置,已经包含在类库内部)如下:
    sliderholesliderhole
       

    禁用默认 _Template_调用DisableDefaultTemplates即可:

    builder.Services.AddSlideCaptcha(builder.Configuration)
        .DisableDefaultTemplates();
    
    1. Validator自定义
      类库提供 SimpleValidator , BasicValidator 两个实现。
      SimpleValidator 仅位置验证,BasicValidator除位置验证外,同时对轨迹做验证。_BasicValidator由于算法的原因,容易误判,因此类库默认用SimpleValidator做为默认 Validator 。
      自定义 Validator 继承 BaseValidator , BaseValidator 提供了基本的位置验证。

    举一个栗子:

    public class CustomValidator: BaseValidator
    {
        public override bool ValidateCore(SlideTrack slideTrack, CaptchaValidateData captchaValidateData)
        {
            // BaseValidator已做了基本滑块与凹槽的对齐验证,这里做其他验证
    
            return true;
        }
    }
    

    替换默认的Validator

    builder.Services.AddSlideCaptcha(builder.Configuration);
        .ReplaceValidator<CustomValidator>();
    
    1. ResourceProvider自定义
      除了通过Options配置Background和Template外,你也可以通过自定义ResourceProvider的形式提供Background和Template。
    public class CustomResourceProvider : IResourceProvider
    {
        public List<Resource> Backgrounds()
        {
            return Enumerable.Range(1, 10)
                .ToList()
                .Select(e => new Resource(Core.Resources.Handler.FileResourceHandler.TYPE, $"wwwroot/images/background/{e}.jpg"))
                .ToList();
        }
        
        // 这里返回自定义的Template
        public List<TemplatePair> Templates()
        {
            return new List<TemplatePair>();
        }
    }
    

    注册ResourceProvider

    builder.Services.AddSlideCaptcha(builder.Configuration)
        .AddResourceProvider<CustomResourceProvider>();
    
    1. 自定义ResourceHandler
    public class UrlResourceHandler : IResourceHandler
    {
        public const string Type = "url";
    
        public bool CanHandle(string handlerType)
        {
            return handlerType == Type;
        }
    
        /// <summary>
        /// 这里仅演示,仍然从本地读取。实际需要通过Http读取
        /// </summary>
        /// <param name="resource"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public byte[] Handle(Resource resource)
        {
            if (resource == null) throw new ArgumentNullException(nameof(resource));
            return File.ReadAllBytes(resource.Data);
        }
    }
    

    注册ResourceHandler

    builder.Services.AddSlideCaptcha(builder.Configuration)
        .AddResourceHandler<UrlResourceHandler>();
    

    项目参考

    项目参考了tianai-captchavue-drag-verify非常优秀的项目,非常感谢。

  • 相关阅读:
    lazyload【思路】
    图片旋转
    模拟滚动条【大体功能实现】
    Firefox window.close()的使用注意事项
    修改KindEditor的CSS文件
    ownerDocument property
    网易新闻图片展示效果
    关于td不支持position问题
    strcat strncat
    Tcl_FindExecutable
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/16454365.html
Copyright © 2020-2023  润新知