gin图片验证码

在开发的过程中,我们有些接口为了防止被恶意调用,我们会采用加验证码的方式,例如:发送短信的接口,为了防止短信接口被频繁调用造成损失;注册的接口,为了防止恶意注册。在这里为大家推荐一个验证码的类库,方便大家学习使用。

     github.com/dchest/captcha

web端是怎么实现验证码的功能呢?

  • 提供一个路由,先在session里写入键值对(k->v),把值写在图片上,然后生成图片,显示在浏览器上面
  • 前端将图片中的内容发送给后后端,后端根据session中的k取得v,比对校验。如果通过继续下一步的逻辑,失败给出错误提示

API接口验证码实现方式类似,可以把键值对存储在起来,验证的时候把键值对传输过来一起校验。这里我只给出了web端的方法,爱动手的小伙伴可以自己尝试一下。

后端
package mainimport ("bytes""github.com/dchest/captcha""github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie""github.com/gin-gonic/gin""net/http""time"
)// 中间件,处理session
func Session(keyPairs string) gin.HandlerFunc {store := SessionConfig()return sessions.Sessions(keyPairs, store)
}
func SessionConfig() sessions.Store {sessionMaxAge := 3600sessionSecret := "topgoer"var store sessions.Storestore = cookie.NewStore([]byte(sessionSecret))store.Options(sessions.Options{MaxAge: sessionMaxAge, //secondsPath:   "/",})return store
}func Captcha(c *gin.Context, length ...int) {l := captcha.DefaultLenw, h := 107, 36if len(length) == 1 {l = length[0]}if len(length) == 2 {w = length[1]}if len(length) == 3 {h = length[2]}captchaId := captcha.NewLen(l)session := sessions.Default(c)session.Set("captcha", captchaId)_ = session.Save()_ = Serve(c.Writer, c.Request, captchaId, ".png", "zh", false, w, h)
}
func CaptchaVerify(c *gin.Context, code string) bool {session := sessions.Default(c)if captchaId := session.Get("captcha"); captchaId != nil {session.Delete("captcha")_ = session.Save()if captcha.VerifyString(captchaId.(string), code) {return true} else {return false}} else {return false}
}
func Serve(w http.ResponseWriter, r *http.Request, id, ext, lang string, download bool, width, height int) error {w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")w.Header().Set("Pragma", "no-cache")w.Header().Set("Expires", "0")var content bytes.Bufferswitch ext {case ".png":w.Header().Set("Content-Type", "image/png")_ = captcha.WriteImage(&content, id, width, height)case ".wav":w.Header().Set("Content-Type", "audio/x-wav")_ = captcha.WriteAudio(&content, id, lang)default:return captcha.ErrNotFound}if download {w.Header().Set("Content-Type", "application/octet-stream")}http.ServeContent(w, r, id+ext, time.Time{}, bytes.NewReader(content.Bytes()))return nil
}func main() {router := gin.Default()router.LoadHTMLGlob("./*.html")router.Use(Session("topgoer"))router.GET("/captcha", func(c *gin.Context) {Captcha(c, 4)})router.GET("/", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)})router.GET("/captcha/verify/:value", func(c *gin.Context) {value := c.Param("value")if CaptchaVerify(c, value) {c.JSON(http.StatusOK, gin.H{"status": 0, "msg": "success"})} else {c.JSON(http.StatusOK, gin.H{"status": 1, "msg": "failed"})}})router.Run(":8080")
}
前端页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>www.topgoer.com验证码</title>
</head>
<body>
<img src="/captcha" onclick="this.src='/captcha?v='+Math.random()">
</body>
</html>

浏览器访问http://127.0.0.1:8080

访问http://127.0.0.1:8080/captcha/verify/5721 进行验证

    {"msg": "failed","status": 1}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/639160.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++:特殊类的设计和类型转换

特殊类的设计和类型转换 特殊类的设计1.设计一个类&#xff0c;不能被拷贝2.设计一个类&#xff0c;只能在堆上创建对象3.设计一个类&#xff0c;只能在栈上创建对象4.设计一个类&#xff0c;不能被继承5.单例模式 C的类型转换1. C语言中的类型转换2.C语言类型转换的缺点3.C的强…

vue3-模版引用ref

1. 介绍 概念&#xff1a;通过 ref标识 获取真实的 dom对象或者组件实例对象 2. 基本使用 实现步骤&#xff1a; 调用ref函数生成一个ref对象 通过ref标识绑定ref对象到标签 代码如下&#xff1a; 父组件&#xff1a; <script setup> import { onMounted, ref } …

Android Studio 之 菜单 Menu

选项菜单 OptionsMenu 用xml添加&#xff08;更建议使用&#xff09; 创建一个菜单布局 : 在 res文件下新建一个menu 目录&#xff0c;此时的菜单id为&#xff1a;R.menu.option <?xml version"1.0" encoding"utf-8"?> <menu xmlns:android&…

不同开发语言在进程、线程和协程的设计差异

不同开发语言在进程、线程和协程的设计差异 1. 进程、线程和协程上的差异1.1 进程、线程、协程的定义1.2 进程、线程、协程的差异1.3 进程、线程、协程的内存成本1.4 进程、线程、协程的切换成本 2. 线程、协程之间的通信和协作方式2.1 python如何实现线程通信&#xff1f;2.2 …

【Unity】AB包下载

【Unity】AB包下载 1.使用插件打AB包 a.AB包分类 一般地&#xff0c;将预制体作为AB包资源&#xff0c;不仅需要对预制体本身进行归类&#xff0c;还要对其涉及的动画&#xff08;AnimationClip&#xff09;、动画状态机&#xff08;AnimatorController&#xff09;、以及所…

144.二叉树的前序遍历

递归 public List<Integer> preorderTraversal(TreeNode root) {List<Integer> list new ArrayList<>();traversal(root, list);return list;}public void traversal(TreeNode t, List<Integer> list) {if (t null) {return;}list.add(t.val);trave…

《A++ 敏捷开发》- 5 量化管理从个人开始

我&#xff1a;你们管理层和客户都比较关心项目的进度&#xff0c;项目是否能按时完成&#xff1f;请问你们过去的项目如何&#xff1f; 开发&#xff1a;我们现在就是走敏捷开发&#xff0c;两周一个迭代。每次迭代前&#xff0c;我们聚一起开会&#xff0c;把所有用户故事按优…

2024.1.19力扣每日一题——使数组和小于等于 x 的最少时间

2024.1.19 题目来源我的题解方法一 动态规划方法二 动态规划&#xff08;空间优化&#xff09; 题目来源 力扣每日一题&#xff1b;题序&#xff1a;2809 我的题解 题解参考官方题解。 方法一 动态规划 若能找到一个最小的时间t使得数组和小于等于x&#xff0c;则最多在一轮…

Dubbo 3.2版本分析Provider启动时操作

Dubbo 3.2版本分析Provider启动时操作 前言例子分析onStarting 模块doStart 模块 小结 前言 上一篇文章&#xff0c;我们分析了 Dubbo 3.2 版本在 Provider 启动前的操作流程&#xff0c;这次我们具体分析具体它的启动过程&#xff0c;揭开它的神秘面纱。 例子 这里我们还是…

【ZYNQ入门】第八篇、基于Lwip构建TCP服务器

目录 第一部分、基础知识 1、小白入门必看文章 2、什么是Lwip&#xff1f; 3、什么是TCP/IP协议&#xff1f; 4、MAC地址、IP地址、子网掩码、网关 4.1、MAC地址 4.2、IP地址 4.3、子网掩码 4.4、网关 第二部分、硬件搭建 第三部分、软件代码 1、SDK工程的建立 2、…

数据结构与算法-二叉树-从中序与后序遍历序列构造二叉树

从中序与后序遍历序列构造二叉树 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7], postorder …

云盘后端分析

1.验证码 用的是外面找的 2.发送邮箱验证码 配置邮箱的授权码 我们在发送邮箱的时候&#xff0c;需要把那个值传到数据库中&#xff0c;数据库中有它的状态&#xff0c;我们需要根据状态判断它是注册还是找回密码 我们在发送邮箱之前&#xff0c;先从session里面得到我们验证…

Rocky Linux 8.9 安装图解

风险告知 本人及本篇博文不为任何人及任何行为的任何风险承担责任&#xff0c;图解仅供参考&#xff0c;请悉知&#xff01;本次安装图解是在一个全新的演示环境下进行的&#xff0c;演示环境中没有任何有价值的数据&#xff0c;但这并不代表摆在你面前的环境也是如此。生产环境…

某度网盘提取下载链接JS逆向分析(一)

本次目标网址如下&#xff0c;使用base64解码后获得 aHR0cHM6Ly9wYW4uYmFpZHUuY29tL3MvMUZsaDBPeGpZamZJTFVZWUQzTm9fVnc 链接提取码为&#xff1a;ly12 本次逆向分析分为上下两篇文章说明&#xff0c;一为讲解如何从原链接通过逆向拿到下载链接&#xff0c;二为逆向登录拿到co…

flink结合Yarn进行部署

1. 什么是Yarn模式部署Flink 独立&#xff08;Standalone&#xff09;模式由 Flink 自身提供资源&#xff0c;无需其他框架&#xff0c;这种方式降低了和其他第三方资源框架的耦合性&#xff0c;独立性非常强。但我们知道&#xff0c;Flink 是大数据计算框架&#xff0c;不是资…

编程笔记 html5cssjs 044 CSS显示

编程笔记 html5&css&js 044 CSS显示 一、display 属性二、块级元素&#xff08;block element&#xff09;三、行内元素&#xff08;inline element&#xff09;四、disply属性设置&#xff08;一&#xff09;Display: none;&#xff08;二&#xff09;覆盖默认的 Disp…

C++学习笔记——指针

1&#xff0c;指针的基本概念 指针的作用&#xff1a;可以通过指针间接访问内存 内存的编号是从0开始记录的&#xff0c;一般用十六进制数字表示可以利用指针变量保存地址 上图中的p就是a变量的指针&#xff0c;也可以记作*a 2&#xff0c;指针变量的定义和使用 指针变量定…

Linux操作系统——理解文件系统

预备知识 到目前为止&#xff0c;我们所学习到的关于文件的操作&#xff0c;全部都是基于文件被打开&#xff0c;被访问&#xff0c;访问期间比较重要的有重定向&#xff0c;缓冲区&#xff0c;一切皆文件&#xff0c;当我们访问完毕的时候需要将文件关闭&#xff0c;关闭时那…

3.RHCSA脚本配置及通过node2改密码

运行脚本发现node2不成功 脚本破解 选第二个 Ctrl x 换行 破解成功后做node2的改密码题 回到redhat, 发现检测程序检测密码题成功,得了8分.

DBA技术栈MongoDB: 数据增改删除

该博文主要介绍mongoDB对文档数据的增加、更新、删除操作。 1.插入数据 以下案例演示了插入单个文档、多个文档、指定_id、指定多个索引以及插入大量文档的情况。在实际使用中&#xff0c;根据需求选择适合的插入方式。 案例1&#xff1a;插入单个文档 db.visitor.insert({…