当前位置: 首页 > news >正文

C#实现旋转图片验证码

开发环境:C#,VS2019,.NET Core 3.1,ASP.NET Core

1、建立一个验证码控制器

新建两个方法Create和Check,Create用于创建验证码(返回1张图片和令牌),Check用于验证(验证图片旋转角度)它是否有效。

声明一个静态类变量存放列表,列表中存放包含令牌和验证码的对象。

        /// <summary>/// 返回一张图片和令牌./// </summary>/// <returns></returns>public string Create(){try{// 记录验证码到缓存中VCodeCircleModel model = new VCodeCircleModel();model.id = Guid.NewGuid().ToString();    // 生成令牌var vcode = VCodeCircleModel.GetVCode();    // 生成验证码model.code = vcode;_list.Add(model);// 返回图片var images = VCodeCircleModel.GetImage(Convert.ToInt32(vcode));VCodeCircleController_Create_Receive result = new VCodeCircleController_Create_Receive();result.code = "0";result.data.id = model.id;result.data.img = VCodeCircleModel.BitmapToBase64Str(images);var json = JsonConvert.SerializeObject(result);return json;}catch (Exception ex){_logger.LogWarning(exception: ex, message: ex.Message);VCodeCircleController_Create_Receive result = new VCodeCircleController_Create_Receive();result.code = "999999";result.msg = "系统异常";var json = JsonConvert.SerializeObject(result);return json;}}public string Check(string id, string code){try{// 旋转图片的误差在±5var temp = Convert.ToInt32(code) - 5;var index = _list.FindIndex(m =>{if (m.id.Equals(id)){for (int i = 0; i < 10; i++){if (m.code.Equals(temp.ToString())){return true;}temp++;}}return false;});ReceiveObject result = new ReceiveObject();if (index >= 0){_list.RemoveAt(index);result.code = "0";result.msg = "验证成功";var json = JsonConvert.SerializeObject(result);return json;}else{result.code = "1";result.msg = "验证失败";var json = JsonConvert.SerializeObject(result);return json;}}catch (Exception ex){_logger.LogError(exception: ex, message: ex.Message);ReceiveObject result = new ReceiveObject();result.code = "999999";result.msg = "系统异常";var json = JsonConvert.SerializeObject(result);return json;}}

    public class VCodeCircleModel{/// <summary>/// 令牌./// </summary>public string id { get; set; }/// <summary>///验证码./// </summary>public string code { get; set; }/// <summary>/// 获取随机验证码./// </summary>/// <returns></returns>public static string GetVCode(){// 这里的随机码是旋转图片的角度,至少旋转60度,最多旋转300度Random random = new Random();return random.Next(60, 300).ToString();}/// <summary>/// 随机获取一张图片./// </summary>/// <returns></returns>public static Bitmap GetImage(int angle){// 从文件加载原图Random random = new Random();var image_index = random.Next(0, 2);Image originImage;switch (image_index){case 0:originImage = Image.FromFile(string.Format(@"{0}\Images\{1}", PathHelper.Path, "circleImg1.png"));break;case 1:default:originImage = Image.FromFile(string.Format(@"{0}\Images\{1}", PathHelper.Path, "circleImg2.png"));break;}originImage = Rotate(originImage as Bitmap, angle);return (Bitmap)originImage;}/// <summary>/// 图片旋转/// </summary>/// <param name="ImageOriginal">原图.</param>/// <param name="AngleValue">旋转角度.</param>/// <returns></returns>public static Bitmap Rotate(Bitmap ImageOriginal, float AngleValue){AngleValue = AngleValue % 360;double radian = AngleValue * Math.PI / 180.0;double cos = Math.Cos(radian);double sin = Math.Sin(radian);int w = ImageOriginal.Width;int h = ImageOriginal.Height;int W = (int)(Math.Max(Math.Abs(w * cos - h * sin), Math.Abs(w * cos + h * sin)));int H = (int)(Math.Max(Math.Abs(w * sin - h * cos), Math.Abs(w * sin + h * cos)));Bitmap ImageBaseOriginal = new Bitmap(W, H, PixelFormat.Format32bppArgb);System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(ImageBaseOriginal);g.InterpolationMode = InterpolationMode.NearestNeighbor;g.SmoothingMode = SmoothingMode.HighQuality;Point Offset = new Point((W - w) / 2, (H - h) / 2);Rectangle rect = new Rectangle(Offset.X, Offset.Y, w, h);Point center = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);g.Clear(Color.White);g.TranslateTransform(center.X, center.Y);g.RotateTransform(360 - AngleValue);g.TranslateTransform(-center.X, -center.Y);g.DrawImage(ImageOriginal, rect);g.ResetTransform();g.Save();g.Dispose();return ImageBaseOriginal;}/// <summary>/// 将图片对象转成Base64的字符串./// </summary>/// <param name="bitmap"></param>/// <returns></returns>public static string BitmapToBase64Str(Bitmap bitmap){using (MemoryStream memoryStream = new MemoryStream()){bitmap.Save(memoryStream, ImageFormat.Jpeg);byte[] bytes = memoryStream.ToArray();return Convert.ToBase64String(memoryStream.ToArray());}}}

2、新建一个视图文件,引入jquery,css文件,js方法中添加三个鼠标事件 - 鼠标按下,鼠标移动和鼠标松开。页面首次加载时调用控制器的Create方法获取图片和令牌,在鼠标松开时调用Check方法验证旋转的角度是否有效。

本来想实现鼠标在图片上拖动后让图片的效果,但发现难度有点大,就换成了拖动滑块后让图片旋转的形式。

<link href="~/css/circle_slide.css" rel="stylesheet" type="text/css" /><!-- 展示验证码 -->
<div class="container"><div class="main"><div id="content" class="content"><img id="backImage" src="" alt=""></div></div><div id="slider"><div id="sliderBlock"></div></div>
</div><script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/MyCircleSlide.js"></script>

* {margin: 0;padding: 0;
}.main {position: relative;margin-left: 20px;margin-top: 20px;width: 200px;background-color: white;
}.content {width: 100%;
}.content img {width: 100%;height: auto;}#slider {width: 85%;height: 40px;background-color: aliceblue;position: relative;
}#sliderBlock {position: absolute;left: 5px;height: 30px;width: 45px;top: 5px;background-color: white;border-radius: 5px;box-shadow: 0 0 10px 2px lightgray;
}

$(function () {var _imageBase64;    // 大图var _id;// 鼠标左键是否按下var isMouseDown;// 鼠标按下x值var mouseDownStartX;// 鼠标移动距离var mouseMoveLength;init();document.onmousedown = function (event) {var obj = getElementPosition(document.getElementById('sliderBlock'))if (event.clientX > obj.left &&event.clientX < (obj.left + obj.width) &&event.clientY > obj.top &&event.clientY < (obj.top + obj.height)) {// 鼠标点击事件发生在滑动条的范围内this.isMouseDown = truethis.mouseDownStartX = event.clientXconsole.log("鼠标点击事件发生在滑动条的范围内");}}document.onmousemove = function (event) {if (this.isMouseDown) {this.mouseMoveLength = event.clientX - this.mouseDownStartX;    // 计算滑块拖动的距离if (this.mouseMoveLength > 0 &&this.mouseMoveLength < 360) {// 滑块拖动的最小距离是5px,最大距离是大图的宽度 - 小图的宽度document.getElementById('sliderBlock').style.left = 5 + this.mouseMoveLength + 'px'$("#backImage").css("transform", "rotate(" + (this.mouseMoveLength) + "deg)");}}}document.onmouseup = function (event) {// 鼠标松开后停止拖动if (this.isMouseDown) {this.isMouseDown = false// console.log("小图移动了:" + this.mouseMoveLength);// check(x.replace("px", ""));check(this.mouseMoveLength);}}// dom在浏览器的位置function getElementPosition(element) {let top = element.offsetToplet left = element.offsetLeftlet width = element.offsetWidthlet height = element.offsetHeightvar currentParent = element.offsetParent;while (currentParent !== null) {top += currentParent.offsetTopleft += currentParent.offsetLeftcurrentParent = currentParent.offsetParent}return { top, left, width, height }}function check(x) {$.get("Check?code=" + x + "&id=" + _id, function (data) {var obj = JSON.parse(data);if (obj.code == "0") {alert("验证成功");}else {alert("验证失败");}});}// 设置当前图片function setCurrentImageBase64(imageBase64) {_imageBase64 = imageBase64document.getElementById('backImage').src = _imageBase64}function init() {$.get("Create", function (data) {// 获取两张图片和令牌var obj = JSON.parse(data);_id = obj.data.id;setCurrentImageBase64('data:image/webp;base64,' + obj.data.img);});}
});

效果图:

 

相关文章:

C#实现旋转图片验证码

开发环境&#xff1a;C#&#xff0c;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core 1、建立一个验证码控制器 新建两个方法Create和Check&#xff0c;Create用于创建验证码&#xff08;返回1张图片和令牌&#xff09;&#xff0c;Check用于验证&#xff08;验证图…...

MySQL—缓存

目录标题 为什么要有Buffer Poolbuffer pool有多大buffer pool缓存什么 如何管理Buffer Pool如何管理空闲页如何管理脏页如何提高缓存命中率预读失效buffer pool污染 脏页什么时候会被刷入到磁盘 为什么要有Buffer Pool 虽然说MySQL的数据是存储在磁盘中&#xff0c;但是也不能…...

IP提取器对比器

需求&#xff1a; 一个html 页面 &#xff0c;有两个输入框 第一个输入框输入文本中包含多个ip&#xff0c;输入的ip是不规则的&#xff0c;需要使用正则表达式提取出 输入文本的ip地址 &#xff0c; 然后在第二个输入框中输入内容&#xff0c;并提取出内容的ip &#xff0c;如…...

【Spring Boot】构建RESTful服务 — RESTful简介

RESTful简介 本节将从基础的概念开始介绍什么是RESTful、RESTful的特点、RESTful中的资源、HTTP Method、HTTP Status&#xff0c;还将介绍RESTful和SOAP到底有哪些区别。 1.什么是RESTful RESTful是目前流行的互联网软件服务架构设计风格。REST&#xff08;Representationa…...

模仿火星科技 基于cesium+水平面积测量+可编辑

​ 当您进入Cesium的编辑水平积测量世界&#xff0c;下面是一个详细的操作过程&#xff0c;帮助您顺利使用这些功能&#xff1a; 1. 创建提示窗&#xff1a; 启动Cesium应用&#xff0c;地图场景将打开&#xff0c;欢迎您进入编辑模式。 在屏幕的一角&#xff0c;一个友好的提…...

26.配电网规划——考虑潮流约束的配电网规划

MATLAB代码直达&#xff1a;26.多时段-考虑潮流约束的配电网规划 clc;clear;close all; %% 导入数据 load(data.mat); MGpowerxlsread(MG1-3.xlsx); % 微电网的日负荷曲线 nt3 ; % 变压所个数 Sn25; % 变电所容量 MVA G…...

【云原生】K8S集群

目录 一、调度约束1.1 POT的创建过程1.1调度过程 二、指定节点调度2.1 通过标签选择节点 三、亲和性3.1requiredDuringSchedulingIgnoredDuringExecution&#xff1a;硬策略3.1 preferredDuringSchedulingIgnoredDuringExecution&#xff1a;软策略3.3Pod亲和性与反亲和性3.4使…...

python接口自动化之自动发送测试报告邮件

前言 ​ SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;也就是简单邮件传输协议&#xff0c;是一种提供可靠且有效电子邮件传输的协议。python的smtplib模块就提供了一种很方便的途径发送电子邮件&#xff0c;它对smtp协议进行了简单的封装。 ​ python发邮件主…...

umi出现“Cannot find module ‘umi-build-dev/lib/routes‘“ 错误

确认安装的 Umi 版本是否正确&#xff1a;首先&#xff0c;检查项目中 package.json 文件中的 umi 的版本号是否正确&#xff0c;确保版本号与项目所需的版本一致。清除缓存并重新安装依赖&#xff1a;可以尝试使用以下命令清除 npm 缓存并重新安装依赖&#xff1a; npm cache …...

Redis类型检查与命令多态

Redis中用于操作键的命令基本上可以分为两种类型。 其中一种命令可以对任何类型的键执行&#xff0c;比如说DEL命令、EXPIRE命令 、RENAME命令、TYPE命令、OBJECT命令等。 举个例子&#xff0c;以下代码就展示了使用DEL命令来删除三种不同类型的键: # 字符串键 redis> SE…...

mysql支持的xa具体指的是什么?

在MySQL中&#xff0c;XA指的是一种事务协议&#xff08;eXtended Architecture&#xff09;&#xff0c;用于支持分布式事务。XA协议允许应用程序跨多个独立的数据库资源&#xff08;例如多个MySQL实例&#xff09;执行分布式事务。 具体来说&#xff0c;XA协议提供了以下关键…...

IntelliJ Idea 编译时控制台上中文输出乱码

猜测原因是IDEA启动时未指定编码信息&#xff0c;故与系统编码保持一致&#xff08;windows中文系统默认为GBK编码&#xff09;,当以UTF-8编码进行编译在控制台会以GBK编码输出,从而导致乱码 解决方案 指定Idea启动时JVM的默认编码为UTF-8 Help -> Edit Custom Options P…...

锚框【目标检测】

生成多个锚框 假设输入图像高为h,宽为w,我们以图像每个像素为中心生成不同形状的锚框,缩放比 s∈(0,1],宽高比为r>0。那么锚框的宽度和高度分别为和。当中心位置给定时, 已知宽和高的锚框是确定的。缩放比为锚框高与图像高的比值,然后得到一个正方形锚框面积。 ​​…...

001-Spring boot 启动内置Web容器分析

目录 代码入口上下文容器 加载web容器WebServercreateWebServergetWebServerFactory()&#xff1a;getWebServer(): 执行WebServer#start自动配置读取配置修改配置 代码入口 上下文容器 SpringApplication.run(App.class); //追踪下去发现 context createApplicationContext…...

【Cocos Creator 项目实战 】消灭星星加强版(附带完整源码工程)

本文乃Siliphen原创&#xff0c;转载请注明出处 目录 概述 游戏整体流程 游戏框架设计 单一职责的类 主要流程控制类 核心玩法模块 UI&#xff1a; 游戏世界&#xff1a; 本文项目的代码组织结构 作者项目实践总结 场景只有一个入口脚本 尽量少在节点上挂载脚本 构…...

2023软件测试岗必问的100个面试题【含答案】

一、测试理论 1.什么是软件测试&#xff1f; 答&#xff1a;软件测试是通过执行预定的步骤和使用指定的数据&#xff0c;以确定软件系统在特定条件下是否满足预期的行为。 2.测试驱动开发&#xff08;TDD&#xff09;是什么&#xff1f; 答&#xff1a;测试驱动开发是一种开…...

MediaExtractor MediaCodec手动解码播放音乐

MediaExtractor MediaCodec手动解码播放音乐,笔记 private class DecodeAudio implements Runnable {Overridepublic void run() {//开始播放pcmaudioTrack.play();MediaExtractor extractor null;MediaCodec codec null;Log.i(TAG, "run: init");FileOutputStrea…...

element表格+表单+表单验证结合运用

目录​​​​​​​ 一、结果展示 二、实现代码 一、结果展示 1、图片 2、描述 table中放form表单&#xff0c;放输入框或下拉框或多选框等&#xff1b; 点击添加按钮&#xff0c;首先验证表单&#xff0c;如果存在没填的就验证提醒&#xff0c;都填了就向下添加一行表单表…...

亚马逊云科技发布Amazon HealthScribe,使用生成式AI技术实现临床文档的自动生成

近日&#xff0c;亚马逊云科技在纽约峰会上推出了Amazon HealthScribe&#xff0c;该服务符合HIPAA&#xff08;《健康保险流通与责任法案》&#xff09;的相关要求&#xff0c;可为医疗软件供应商提供一种基于语音和文字识别的生成式AI技术&#xff0c;帮助其创建能够自动生成…...

Windows11安装Linux子系统,并实现服务自启动,局域网访问,磁盘挂载

Windows11安装Linux子系统&#xff0c;并实现服务自启动&#xff0c;局域网访问&#xff0c;磁盘挂载 一、准备工作二、安装Linux子系统(wsl2)三、为Linux子系统设置桥接网络检查wsl版本在 Hyper-V 管理器中创建虚拟交换机创建 WSL 配置文件启动wsl 四、设置Windows开机自启动L…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...