当前位置: 首页 > 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…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

加密通信 + 行为分析:运营商行业安全防御体系重构

在数字经济蓬勃发展的时代&#xff0c;运营商作为信息通信网络的核心枢纽&#xff0c;承载着海量用户数据与关键业务传输&#xff0c;其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级&#xff0c;传统安全防护体系逐渐暴露出局限性&a…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...

raid存储技术

1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划&#xff0c;涵盖存储系统的布局、数据存储策略等&#xff0c;它明确数据如何存储、管理与访问&#xff0c;为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...

【笔记】AI Agent 项目 SUNA 部署 之 Docker 构建记录

#工作记录 构建过程记录 Microsoft Windows [Version 10.0.27871.1000] (c) Microsoft Corporation. All rights reserved.(suna-py3.12) F:\PythonProjects\suna>python setup.py --admin███████╗██╗ ██╗███╗ ██╗ █████╗ ██╔════╝…...

CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)

漏洞概述 漏洞名称&#xff1a;Apache Kafka Connect JNDI注入导致的远程代码执行漏洞 CVE编号&#xff1a;CVE-2023-25194 CVSS评分&#xff1a;8.8 影响版本&#xff1a;Apache Kafka 2.3.0 - 3.3.2 修复版本&#xff1a;≥ 3.4.0 漏洞类型&#xff1a;反序列化导致的远程代…...