图片验证码生成Servlet源代码
- 格式:pdf
- 大小:188.85 KB
- 文档页数:7
i用Ajax制作带图形验证码的登录页面作者:Steel.MaMail: steel.ma@steel.ma@MSN: Motorola_8088@Blog: /iamsteelma/steelma一、前言在本笔记的前篇《自定义标签制作》中,已经详细描述了环境的配置以及一个最简单的自定义标签的制作方法,本篇将讲如何制作一个最常用的,带参数的自定义的标签。
本处,为了使用图形界面,必须先下载kaptcha图形验证组件,可以在/p/kaptcha/ 下载。
目前最新版本是2.3版。
二、配置Kaptcha的使用环境Kaptcha的配置是非常简单的,将其释放出来后,在文件夹下会有Kaptcha-2.3.jar和Kaptcha-2.3-jdk1.4.jar 2个jar包,如果用的是JDK1.4,则必须用后者,JDK1.5开始,用前者。
Kaptcha安装也比较简单,直接拷贝到webapps/xxx/web-inf/lib下即可。
然后修改web.xml,加入对Kaptcha的映射配置<servlet><servlet-name>Kaptcha</servlet-name><servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servle t-class></servlet><servlet-mapping><servlet-name>Kaptcha</servlet-name><url-pattern>/kaptcha.jpg</url-pattern></servlet-mapping>以上就完成了对Kaptcha的配置。
使用起来也很方便,在html/jsp中,直接用<img src="kaptcha.jpg" />即可显示图形验证码图片,在servlet中,调用 String xxx = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY)即可取得真实的验证码文本。
使⽤img标签显⽰⽤base64编码的验证码图⽚使⽤img标签显⽰⽤base64编码的验证码图⽚在以下代码的括号处改成对应的base64字符串,即可显⽰<img src="data:image/png;base64,(此处写base64编码字符串2)">相关内容<img src="data:,(⽂本数据)" ><img src="data:text/plain,(⽂本数据)" ><img src="data:text/html,(HTML代码)" ><img src="data:text/html;base64,(base64编码的HTML代码)" ><img src="data:text/css,(CSS代码)" ><img src="data:text/css;base64,(base64编码的CSS代码)" ><img src="data:text/javascript,(Javascript代码)" ><img src="data:text/javascript;base64,(base64编码的Javascript代码)" ><img src="data:image/gif;base64,(base64编码的gif图⽚数据)" ><img src="data:image/png;base64,(base64编码的png图⽚数据)" ><img src="data:image/jpeg;base64,(base64编码的jpeg图⽚数据)" ><img src="data:image/x-icon;base64,(base64编码的icon图⽚数据)" >。
什么是servlet?servlet的作⽤
看到这个问题以前我学习javaEE的时候开发步骤(这⾥是⼤致配置和流程):
1.在web.xml中配置servlet和servletMapping
2.书写servlet标签⾥⾯配置的类,类需要继承HttpServlet,然后复写⾥⾯的doget,dopos⽅法(当然还有init,destory⽅法)
3.启动tomcat服务器,访问对应的路径就能访问到对应的doget,dopost⽅法
但是这个web.xml和对应的类以及tomcat到底有什么关系呢?在后⾯到底做了什么呢?
⾸先我们要理清⼀个逻辑:浏览器http请求------》tomcat服务器-------》到达servlet-----》执⾏doget,dopost⽅法----》返回数据从这个逻辑可以看出tomcat才是和客户端打交道的:
他监听了端⼝,请求过来后,根据url信息和web.xml配置⽂件匹配,确定要将请求交给哪个servlet去处理,servlet处理请求然后返回给tomcat,tomcat在把数据返回给⽤户。
在看servlet源代码:
在看httpServlet:
从名字我们就不难理解,HttpServlet是Servlet对http请求协议处理的实现
那我们就可以得出Servlet接⼝就是处理⽹络请求的⼀套规范,他负责连接web服务器(如tomcat服务器),交互式的⽣成动态的web 内容。
python中captcha的用法Captcha是一种用来防止网络机器人恶意攻击的技术,它一般应用在需登录的应用程序或网站上,以确保用户的真实性和安全性。
Python是一个强大的编程语言,它可以使用不同的库和框架来生成、显示和验证Captcha。
在本文中,我们将介绍Python中Captcha的用法,其中包括Captcha的生成、显示和验证。
一、生成Captcha的库在Python中有许多库可以用来生成Captcha,比如:1. captcha:Captcha为Python提供了一种生成验证码图像的方法,其中包括数字、字母、数字和字母。
这个库使用Pillow图像库来生成Captcha图像。
```pythonpip install captcha``````pythonfrom captcha.image import ImageCaptchaimport randomcaptcha_text = ''for i in range(4):captcha_text += str(random.randint(0, 9))image = ImageCaptcha(width=100, height=40)captcha_image = image.generate(captcha_text)captcha_image_file = open('captcha_image.png', 'wb')captcha_image_file.write(captcha_image)captcha_image_file.close()```2. Pillow:```pythonfrom PIL import Image, ImageDraw, ImageFontimport randomfrom io import BytesIOfrom flask import Flask, request, send_fileapp = Flask(__name__)在上面的代码中,我们创建了一个Flask应用程序,它为生成图像的URL提供了一个路由。
DAY6图形验证码以及短信验证码的处理到我们点击项⽬⾸页的注册时,会弹出⼀个注册页⾯,⾥⾯需要我们后台提供图形验证码以及⼿机验证码下⾯我们来依次处理图形验证码的处理我们先来简单的做个分析⾸先当我们点击注册时,我们需要给到通过浏览器给服务器发送⼀个随机码来进⾏下次请求时双⽅的校验,⽤浏览器的Javascript⽣成UUID来解决,通过GET请求发送(通过两个⽅⾯来考虑,第⼀个这个本⾝不需要加密,第⼆个是通过img标签⾥src默认为GET)当我们给服务器发送了UUID之后,服务器对UUID进⾏保存,然后校验UUID,然后⽣成图⽚验证码(图⽚验证码分为三个部分,⽣成的图⽚验证码名字,图⽚⾥的验证码⽂本,画上了验证码的图⽚),我们需要把UUID保存在redis中,且作为保存值的键,然后提取图⽚验证码的验证码⽂本作为保存的值。
然后我们再给浏览器返回画上了验证码的图⽚就可以了。
这样当⽤户通过返回的图形验证码图⽚⾥的⽂字输⼊了⽂本验证码后再次给到服务器,这⾥浏览器还需要将UUID和输⼊⽂本的⽂本验证码⼀起给到服务器。
因为服务器需要通过给到的UUID作为取值的键来取上次保存的数据,也是做进⼀步的校验和实现状态保存,你是上次给我UUID的那个浏览器。
只有当两次请求给到服务器的UUID⼀致时才能够进⾏上次⽣成图⽚验证码⽂本的提取⼤致分析完之后我们就开始写代码浏览器前端的处理:我们来到我们⾸页的HTML⽂件,打开我们项⽬下的index.html,然后找到我们图形验证码的相关内容,最初⽂件的img标签, src ⾥⾯有⼀堆数据,我们先复制⼀下最初的img标签,复制了然后注释掉,然后再进⾏删除然后Ctrl加左键点击函数来到函数的内容页⾯,这⾥⾯就有我们图⽚验证码的相关内容:最初的⽂件⾥function generateImageCode() {}⾥⾯是空的,这⾥我把代码补充了,代码我也复制再下⾯并做个简单的解释;function generateImageCode() {imageCodeId = generateUUID() #⽣成UUID,⽂件的最下⾯有⽣成UUID的函数,这⾥只是函数的调⽤和⽤新的变量来对imageCOdeId变量进⾏覆盖var url = "/passport/imageCode?imageCodeId="+ imageCodeId #⾃定义⼀个URL地址的变量,后台先创建对应的视图,然后再填写对应的视图URL加上?kv 将UUID通过GET请求给到服务器后台$(".get_pic_code").attr("src",url) #将构造好的URL给到url}⽂件后⾯⽣成UUID的函数后台创造新的视图函数:⾸先在我们的moduls⽂件夹⾥⾯再创建⼀个新的Python⽂件夹(passport)⽤来存放我们登录注册相关的相关内容,然后建⽴⼀个叫views 的Python⽂件来存放相关的视图函数然后就是在__init__⾥⾯写⼊蓝图三步,这⾥我们需要在实例化的时候加⼊url_prefix,也就是前缀,⼀定要记得在前缀最开始加上反斜杠/完成之后再在我们项⽬的info的__init__⽂件夹,然后导⼊注册蓝图完成之后来到我们的视图函数页⾯进⾏视图函数的编写,这⾥先简单的编写⼀下路由和函数就可以了,后⾯我们再进⾏补全,这⾥主要是为了补全我们前端的URL地址:当我们完成对前端⽂件的修改后,再次执⾏主⽂件并点击主页⾯的注册,然后后端查看请求就可以看到我们的UUID 了,当点击图⽚验证码时会刷新请求出现携带不同的UUID的请求 :这样我们图形验证码前端HTML⽂件的修改就完成了后端代码的处理(对应视图函数的编写):当我们去写项⽬的视图函数时需要在我们函数的⽂本注释⾥⾯写上我们的思路以及相应的实现步骤,这样⽅便我们后续代码的编写,这是⼗分重要的。
验证码实现原理验证码实现原理验证码是指在用户注册、登录、找回密码等操作中,为了防止机器人恶意攻击或者恶意注册,需要进行验证的一种方式。
常见的验证码包括数字验证码、图形验证码、短信验证码等。
那么验证码是如何实现的呢?一、数字验证码的实现原理数字验证码一般是由4-6个数字组成的,下面介绍数字验证码的实现原理:1.生成验证码:服务器生成一个不重复的随机验证码,并将此验证码存入session中,同时将验证码展示在客户端需要填写验证码的位置上。
2.验证验证码:当用户填写验证码提交表单时,客户端通过AJAX将客户端填写的验证码发送到服务器端进行验证,服务器通过session中存储的验证码进行比对,如果一致则验证通过,否则验证失败。
二、图形验证码的实现原理图形验证码一般是显示一张由数字、字母或图形组成的图片,并要求用户输入正确的验证码。
下面介绍图形验证码的实现原理:1.生成验证码:服务器生成一个不重复的随机字符串,然后将这段字符串绘制成一张图片,并将此验证码存入session中,同时将验证码图片展示在客户端需要填写验证码的位置上。
2.验证验证码:当用户填写验证码提交表单时,客户端通过AJAX将客户端填写的验证码发送到服务器端进行验证,服务器通过session中存储的验证码进行比对,如果一致则验证通过,否则验证失败。
三、短信验证码的实现原理短信验证码是指向用户发送一条短信,短信中包含验证码,并让用户填写正确的验证码。
下面介绍短信验证码的实现原理:1.生成验证码:服务器生成一个不重复的随机数字,并将此验证码存入session中,同时向用户注册的手机号发送一条短信,短信中包含验证码。
2.验证验证码:用户填写收到的短信验证码,并提交表单,客户端通过AJAX将客户端填写的验证码发送到服务器端进行验证,服务器通过session中存储的验证码进行比对,如果一致则验证通过,否则验证失败。
总结:以上就是常见验证码实现的原理,不同的验证码实现方式有不同的验证过程,但都是为了防止机器人恶意攻击或者恶意注册而设置的。
captcha.image 验证码原理验证码作为一种常用的安全机制,在许多互联网应用中发挥着重要的作用。
captcha.image验证码作为其中的一种,它通过生成并显示包含复杂图案和数字的图像,要求用户进行识别和输入,以防止自动化脚本的攻击。
本文将介绍captcha.image验证码的原理及其实现方式。
一、基本原理captcha.image验证码的基本原理是通过设计一组随机产生的图像、文本、数字、线条和形状等元素,并在其中隐藏一定的规则或规律,使得用户难以通过自动化工具进行识别。
验证码生成器会根据预设的规则生成一组验证码图片,并存储在服务器端。
当用户提交表单时,服务器端会获取到用户输入的验证码,并与生成的验证码进行比对,以验证用户是否为真实的人。
二、生成过程captcha.image验证码的生成过程主要包括以下几个步骤:1.随机选择验证码图片尺寸和背景颜色,可以使用常见的白色或黑色背景。
2.根据预设规则随机生成图像元素,包括线条、形状、字符、数字等。
可以使用各种算法和技术来确保生成的验证码具有足够的复杂性和难以识别的特点。
3.在生成的图像中添加干扰元素,例如随机位置的线条、随机大小和颜色的噪点等,以提高验证码的不可预测性和安全性。
4.将生成的验证码图片保存到服务器端,供用户查看和输入。
三、识别过程用户在查看验证码图片后,需要输入正确的验证码并提交表单。
服务器端会对用户输入的验证码进行验证,并与生成的验证码进行比对。
如果用户输入的验证码与生成的验证码一致,则验证通过;否则验证失败。
captcha.image验证码的实现方式有多种,其中一种常见的方法是使用图像处理库和机器学习算法。
图像处理库可以用于生成和优化验证码图片,而机器学习算法则可以用于训练模型,以便自动识别验证码图片中的字符和数字。
此外,还可以使用其他技术,如哈希算法和加密技术来保护验证码图片的安全性。
四、优化与挑战captcha.image验证码虽然具有一定的安全性和有效性,但在实际应用中仍存在一些挑战和优化空间:1.验证码图片的复杂性和难以识别程度需要适度平衡,否则可能导致用户体验下降。
python识别验证码ocr_Python爬⾍过程中验证码识别的三种解决⽅案在Python爬⾍过程中,有些⽹站需要验证码通过后⽅可进⼊⽹页,⽬的很简单,就是区分是⼈阅读访问还是机器爬⾍。
验证码问题看似简单,想做到准确率很⾼,也是⼀件不容易的事情。
为了更好学习爬⾍,后续推⽂中将会更多介绍爬⾍问题的解决⽅案。
本篇推⽂将分享三种解决验证码的⽅法,如果你有⽐较好的⽅案,欢迎留⾔区讨论交流,共同进步。
1.pytesseract很多⼈学习python,不知道从何学起。
很多⼈学习python,掌握了基本语法过后,不知道在哪⾥寻找案例上⼿。
很多已经做案例的⼈,却不知道如何去学习更加⾼深的知识。
pytesseract是google做的ocr库,可以识别图⽚中的⽂字,⼀般⽤在爬⾍登录时验证码的识别,在安装pytesseract环境过程中会遇到各种坑的事情,如果你需要安装,可以按照如下流程去做,避免踩坑。
下⾯以 mac为例。
1.安装⽅法pip install pytesseract2.此外,还需安装Tesseract,它是⼀个开源的OCR引擎,能识别100多种语⾔。
brew install tesseract3.查看安装位置为brew list tesseract/usr/local/Cellar/tesseract/4.1.1/bin/tesseract/usr/local/Cellar/tesseract/4.1.1/include/tesseract/ (19 files)/usr/local/Cellar/tesseract/4.1.1/lib/libtesseract.4.dylib/usr/local/Cellar/tesseract/4.1.1/lib/pkgconfig/tesseract.pc/usr/local/Cellar/tesseract/4.1.1/lib/ (2 other files)/usr/local/Cellar/tesseract/4.1.1/share/tessdata/ (35 files)4.配置环境变量export TESSDATA_PREFIX=/usr/local/Cellar/tesseract/4.1.1/share/tessdataexport PATH=PATH:TESSDATA_PREFIX5.如何出现如下报错'TesseractNotFoundError: tesseract is not installed or it's not in your PATH'6.修改pytesseract.py的cmd'tesseract_cmd = '/usr/local/Cellar/tesseract/4.1.1/bin/tesseract''先验证⼀个简单的验证码代码如下from PIL import Image,ImageFilterimport pytesseractpath ='/Users/****/***.jpg'captcha = Image.open(path)result = pytesseract.image_to_string(captcha)print(result)51188再换⼀张试⼀下输⼊代码后,结果错误输出为1364由此看出,pytesseract对于简单⽅法有效,并不像有些⼈写的这么好,当然可以通过灰度、⼆值等⽅法,效果并不是很理想,稍微复杂的需要寻找其他解决⽅案,如果解决上述问题呢,我们看下⾯的解决⽅案。
core配合vue实现后端验证码逻辑⽬录概述部分原理源码概述⽹上的前端验证码逻辑总感觉不安全,验证码建议还是使⽤后端配合验证。
如果产品确定可以上⽹的话,就可以使⽤腾讯,百度等第三⽅验证,对接⽅便。
但是产品可能内⽹部署,就必须⾃⼰写了。
本⽂章就是基于这⼀点来实现的。
前端验证码显⽰⼀个图⽚,后端⽣成图⽚。
部分原理1.前端调⽤⽣端获取图⽚时,传⼊⼀个roomID,后端⽣成⼀个4位验征码,放⼊redis中。
然后⽣成⼀个图⽚返回。
2.前端显⽰图⽚,登录时将roomID和填写的验证码,⼀并提交,登录接⼝根据roomId从redis中取出验证码判断是否正确。
这样就相当于后端验证了。
⼤家觉得有问题什么,可以进⾏评论。
谢谢。
源码前端部分代码<template><div class="login-container"><vue-particlescolor="#ffffff":particleOpacity="0.7":particlesNumber="50"shapeType="circle":particleSize="4"linesColor="#dedede":linesWidth="1":lineLinked="true":lineOpacity="0.4":linesDistance="150":moveSpeed="2":hoverEffect="true"hoverMode="grab":clickEffect="true"clickMode="push"></vue-particles><el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left"><div class="title-container"><h3 class="title">智能综合管理系统</h3></div><el-form-item prop="username"><span class="svg-container"><svg-icon icon-class="user" /></span><el-input ref="username" v-model="ername" placeholder="⽤户名" name="username" type="text" tabindex="1" autocomplete="on" /> </el-form-item><el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual><el-form-item prop="password"><span class="svg-container"><svg-icon icon-class="password" /></span><el-input:key="passwordType"ref="password"v-model="loginForm.password":type="passwordType"placeholder="密码"name="password"tabindex="2"autocomplete="on"@keyup.native="checkCapslock"@blur="capsTooltip = false"@keyup.enter.native="handleLogin"/><span class="show-pwd" @click="showPwd"><svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /></span></el-form-item></el-tooltip><el-form-item prop="yzm"><span class="svg-container"><svg-icon icon-class="password" /></span><el-input type="text" v-model="loginForm.verifyCode" maxlength="4" placeholder="验证码" /><div class="identifyCode" @click="refreshCode"><el-image :src="verifyImageUrl"></el-image></div></el-form-item><el-button :loading="loading" type="primary" style="width: 100%; margin-bottom: 30px" @click.native.prevent="handleLogin">登录</el-button> </el-form></div></template><script>import { validUsername } from '@/utils/validate'import Identify from './components/Identify'import { uuid } from 'vue-uuid'; // uuid object is also exported to things// outside Vue instance.export default {name: 'Login',components: { Identify },data() {const validateUsername = (rule, value, callback) => {if (!validUsername(value)) {callback(new Error('请输⼊正确的⽤户名'))} else {callback()}}const validatePassword = (rule, value, callback) => {if (value.length < 6) {callback(new Error('密码最少6位'))} else {callback()}}return {loginForm: {username: 'admin',password: '111111',roomId: '',verifyCode: ''},loginRules: {username: [{ required: true, trigger: 'blur', validator: validateUsername }],password: [{ required: true, trigger: 'blur', validator: validatePassword }]},passwordType: 'password',capsTooltip: false,loading: false,showDialog: false,redirect: undefined,otherQuery: {},identifyCodes: '1234567890',identifyCode: '',// verifyImageRoomId: '',verifyImageUrl: '',}},watch: {$route: {handler: function (route) {const query = route.queryif (query) {this.redirect = query.redirectthis.otherQuery = this.getOtherQuery(query)}},immediate: true}},created() {// window.addEventListener('storage', this.afterQRScan)// this.identifyCode = ''// this.makeCode(this.identifyCodes, 4)this.refreshCode()},mounted() {if (ername === '') {this.$ername.focus()} else if (this.loginForm.password === '') {this.$refs.password.focus()}},destroyed() {// window.removeEventListener('storage', this.afterQRScan)},methods: {checkCapslock(e) {const { key } = ethis.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z')},showPwd() {if (this.passwordType === 'password') {this.passwordType = ''} else {this.passwordType = 'password'}this.$nextTick(() => {this.$refs.password.focus()})},createUuid() {let uuidV4 = uuid.v4().replace('-', '').replace('-', '').replace('-', '').replace('-', '')this.verifyImageRoomId = uuidV4this.verifyImageUrl = '/api/Operator/getCaptchaImage/120/40/' + this.verifyImageRoomId console.log(uuidV4)},handleLogin() {this.$refs.loginForm.validate(valid => {if (valid) {this.loading = truethis.$store.dispatch('user/login', this.loginForm).then(() => {this.$router.push({ path: this.redirect || '/', query: this.otherQuery })this.loading = false}).catch(() => {this.loading = false})} else {console.log('error submit!!')return false}})},getOtherQuery(query) {return Object.keys(query).reduce((acc, cur) => {if (cur !== 'redirect') {acc[cur] = query[cur]}return acc}, {})},// ⽣成随机数randomNum(min, max) {return Math.floor(Math.random() * (max - min) + min)},// 切换验证码refreshCode() {let uuidV4 = uuid.v4().replace('-', '').replace('-', '').replace('-', '').replace('-', '')this.loginForm.roomId = uuidV4this.verifyImageUrl = '/api/Operator/getCaptchaImage/120/40/' + this.loginForm.roomId console.log(uuidV4)},// ⽣成四位随机验证码makeCode(o, l) {for (let i = 0; i < l; i++) {this.identifyCode += this.identifyCodes[this.randomNum(0, this.identifyCodes.length)]}console.log(this.identifyCode)}}}</script><style lang="scss">/* 修复input 背景不协调和光标变⾊ *//* Detail see https:///PanJiaChen/vue-element-admin/pull/927 */ $bg: #283443;$light_gray: #fff;$cursor: #fff;@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {.login-container .el-input input {color: $cursor;}}/* reset element-ui css */.login-container {background: url("~@/assets/background.jpg") no-repeat;min-height: 100vh;.el-input {display: inline-block;height: 47px;width: 85%;input {background: transparent;border: 0px;-webkit-appearance: none;border-radius: 0px;padding: 12px 5px 12px 15px;color: $light_gray;height: 47px;caret-color: $cursor;&:-webkit-autofill {box-shadow: 0 0 0px 1000px $bg inset !important;-webkit-text-fill-color: $cursor !important;}}}.el-form-item {border: 1px solid rgba(255, 255, 255, 0.1);background: rgba(0, 0, 0, 0.1);border-radius: 5px;color: #454545;.el-form-item__error {color: rgb(223, 223, 176);}}}</style><style lang="scss" scoped>$bg: #2d3a4b;$dark_gray: #889aa4;$light_gray: #eee;.login-container {min-height: 100%;width: 100%;background-color: $bg;overflow: hidden;.login-form {position: absolute;left: 0;right: 0;top: 0;bottom: 0;margin: auto;width: 520px;max-width: 100%;padding: 160px 35px 0;margin: 0 auto;overflow: hidden;}.tips {font-size: 14px;color: #fff;margin-bottom: 10px;span {&:first-of-type {margin-right: 16px;}}}.svg-container {padding: 6px 5px 6px 15px;color: $dark_gray;vertical-align: middle;width: 30px;display: inline-block;}.title-container {position: relative;.title {font-size: 42px;color: $light_gray;margin: 0px auto 40px auto;text-align: center;font-weight: bold;}}.show-pwd {position: absolute;right: 10px;top: 7px;font-size: 16px;color: $dark_gray;cursor: pointer;user-select: none;}.identifyCode {position: absolute;right: 10px;top: 5px;}.thirdparty-button {position: absolute;right: 0;bottom: 6px;}@media only screen and (max-width: 470px) {.thirdparty-button {display: none;}}}</style>后端接⼝/// <summary>/// 获取验证码/// </summary>/// <returns></returns>[HttpGet("getCaptchaImage/{width:int}/{height:int}/{roomId}")]public IActionResult GetCaptchaImage(int width, int height, string roomId){Console.WriteLine(roomId);//int width = 100;//int height = 36;var captchaCode = Captcha.GenerateCaptchaCode();var result = Captcha.GenerateCaptchaImage(width, height, captchaCode);string redisKey = "VerifyCode_" + roomId;Startup.redisDb.StringSet(redisKey, captchaCode, new TimeSpan(0, 5, 0));Stream s = new MemoryStream(result.CaptchaByteData);return new FileStreamResult(s, "image/png");}/// <summary>/// 登录/// </summary>/// <returns></returns>[HttpPost("login")]public ApiResponseData Login(LoginDto loginInfo){if (string.IsNullOrWhiteSpace(ername))return ApiResponse.Error("⽤户名不能为空");if (string.IsNullOrWhiteSpace(loginInfo.password))return ApiResponse.Error("密码不能为空");Entity.BaseOperator operInfo = Db.Select<BaseOperator>().Where(a => a.OperatorCode == ername && a.Password == loginInfo.password.ToLower() && a.Status == 1 && a.IsDel == false).ToOne(); if (operInfo == null)return ApiResponse.Error("⽤户名或者密码不正确");bool verifyResult = Captcha.ValidateCaptchaCode(loginInfo.RoomId, loginInfo.VerifyCode);if(verifyResult == false)return ApiResponse.Error("验证码不正确");//登录时重新⽣成token,⼀个⽤户只能在⼀个地⽅登录string token = System.Guid.NewGuid().ToString().Replace("-", "");Db.Update<BaseOperator>(operInfo.OperatorId).Set(a => a.Token, token).ExecuteAffrows();dynamic outJson = new ExpandoObject();//初始化⼀个不包含任何成员的ExpandoObjectoutJson.token = token;//存⼊redisstring redisKey = "UserInfo_" + token;Startup.redisDb.StringSet(redisKey, operInfo.OperatorId, new TimeSpan(24, 0, 0));return ApiResponse.Succ(outJson);}到此这篇关于 core配合vue实现后端验证码逻辑的⽂章就介绍到这了,更多相关 core验证码内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
简单易学的用VB制作验证码,不含有api函数。
只需掌握简单的VB知识就可学会制作。
第一步,建立一个新的标准exe文件。
然后在form1上拉出一个picture框。
用于输出验证码。
第二步,建立一个commmand控件,用于进行验证码的获取和刷新第三步,创建一个textbox,用于输入验证验证码的载入第四步,建立command2,用于验证所输入验证验证码是否正确第五步,进行代码编写Dim k(1 To 4) As LongPrivate Sub Command1_Click()Command1.Caption = "刷新验证码"Picture1.ClsRandomizeFor j = 1 To 4l = 200 * Rndo = 200 * Rndp = 200 * RndPicture1.ForeColor = RGB(l, o, p)Picture1.FontSize = 30 + Int(Rnd * 24)a = Int(Rnd * 2)b = Int(Rnd * 2)c = Int(Rnd * 2)If a = 1 ThenPicture1.FontBold = TrueElsePicture1.FontBold = FalseEnd IfIf b = 1 ThenPicture1.FontStrikethru = TrueElsePicture1.FontStrikethru = FalseEnd IfIf c = 1 ThenPicture1.FontItalic = TrueElsePicture1.FontItalic = FalseEnd IfPicture1.CurrentX = -0.35 * j + 0.7Picture1.CurrentY = 1g = Int(Rnd * 3)Select Case gCase 1k(j) = (Int(Rnd * 10) + 48)Picture1.Print Chr(k(j))Case 0k(j) = (Int(Rnd * 24) + 97)Picture1.Print Chr(k(j))Case 2k(j) = (Int(Rnd * 24) + 65)Picture1.Print Chr(k(j))End SelectNext jFor i = 1 To 1000Picture1.DrawWidth = 2x = Rnd * 2 - 1y = Rnd * 2 - 1r = 135 * Rnd + 100b = 135 * Rnd + 100g = 135 * Rnd + 100Picture1.PSet (x, y), RGB(r, b, g)Next iEnd SubPrivate Sub Command2_Click()If Len(Text1.Text) <> 4 Thenmystr = MsgBox("验证码错误", 1 + 48, "提示")Elsec1 = Mid(Text1.Text, 1, 1)c2 = Mid(Text1.Text, 2, 1)c3 = Mid(Text1.Text, 3, 1)c4 = Mid(Text1.Text, 4, 1)If (Chr(k(4)) = LCase(c1) Or Chr(k(4)) = UCase(c1)) And (Chr(k(3)) = UCase(c2) Or Chr(k(3)) = LCase(c2)) And (Chr(k(2)) = UCase(c3) Or Chr(k(2)) = LCase(c3)) And (Chr(k(1)) = UCase(c4) Or Chr(k(1)) = LCase(c4)) Thenmystr = MsgBox("验证码正确", 1 + 64, "提示")Elsemystr = MsgBox("验证码错误", 1 + 48, "提示")End IfEnd IfEnd SubPrivate Sub Form_Load()Picture1.Scale (-1, 1)-(1, -1)End Sub第六步,已经完成编写。
验证码大全什么是验证码验证码(CAPTCHA)是Completely Automated Public Turing test to tell Computers and Humans Apart的缩写,意为完全自动区分计算机和人类的图灵测试。
它是一种用于验证用户是否为真实人类而不是机器的方法。
验证码是由一系列随机生成的字符、数字或图形组成,用户需要识别并输入正确的组合才能通过验证。
通过使用验证码,网站可以防止恶意软件、机器人和其他自动化工具进行恶意活动,提高网站的安全性和用户体验。
常见的验证码类型1. 文本验证码文本验证码是最基本和常见的验证码类型之一。
它由一串随机生成的字符组成,用户需要输入正确的字符组合以通过验证。
文本验证码可以是纯数字、英文字符或是数字和英文字符的组合。
例子:验证码:A4F6T92. 数学计算验证码数学计算验证码是一种要求用户解决简单数学问题的验证码类型。
通常会给出一个简单的数学算式,用户需要计算出结果并输入。
例子:验证码:5 + 7 = ?3. 图片验证码图片验证码是一种使用图像形式呈现的验证码类型。
图像可以是数字、字母、图形、动物等。
用户需要从一组图片中选择与提示信息相匹配的图片。
例子:验证码:选择包含自行车的图片4. 声音验证码声音验证码是一种使用声音进行验证码验证的类型。
它通常会播放一段随机生成的语音内容,用户需要听取并正确输入该语音内容。
例子:验证码:听取语音输入数字5. 滑动验证码滑动验证码是一种需要用户通过滑动或拖动滑块以完成验证的类型。
用户需要按照提示将滑块滑动到指定位置,以通过验证。
例子:验证码:将滑块滑动到右侧位置以通过验证验证码的优点和应用•防止恶意注册:验证码可以防止自动化机器人进行大量恶意注册,保护网站的用户数据库安全。
•防止暴力破解:验证码可以阻止暴力破解者通过尝试大量可能的组合来猜解密码,提高网站的安全性。
•防止恶意爬虫:验证码可以防止恶意爬虫通过自动化方式抓取网页内容,保护网站的独特信息和数据。
⽤户注册(⼀)之注册页⾯以及图形验证码⼀、⽤户模型设计(⽤户表的设计) 1. ⽤户表字段分析 1)⽤户名 2)密码 3)⼿机号 4)邮箱 5)邮箱是否有效 2. ⽤户模型设计 django设计模型开发效率极⾼,内置了许多功能,包括权限验证等等,也有⾃定义的User模型。
因此我们需要继承已经写好的抽象模型类AbstractBaseUser,它有已经封装好的各种⽅法,约定俗成的凡是抽象模型类起名都以Abstract来开头,但是判断该模型类是否是抽象模型类的依据是,类中需要定义class Meta:abstract = True 这才证明它是⼀个抽象模型类。
在我们继承了django⾃带的⽤户模型类之后,我们使⽤时进⾏扩充字段即可。
3. 在User这个app中的models.py页⾯来填写我们的需要的User模型类 1)继承抽象模型类,添加⽤户新字段,重写管理器,⽅便我们创建⽤户,并制定我们的User模型使⽤我们⾃定义的管理器# user/models.py ⽂件from django.db import modelsfrom django.contrib.auth.models import AbstractUser, UserManager as _UserManager# Create your models here.# ⾃定义管理器(功能:创建⽤户时可以不⽤填写email)class UserManager(_UserManager):def create_superuser(self, username, password, email=None, **extra_fields):super().create_superuser(username=username, password=password, email=email, **extra_fields)class User(AbstractUser):"""⾃定义的User模型,添加moblie,email_active字段"""# 添加⼿机字段, 第⼀个'⼿机号'是数据库中备注信息,max_length是该字段的最⼤长度# unique是该字段唯⼀,不能重复,help_text是在我们的admin后台来提⽰的字段信息# error_messages是当插⼊字段出错时提⽰的报错信息mobile = models.CharField('⼿机号',max_length=11, unique=True,help_text='⼿机号', error_messages={'unique':'此⼿机号已注册'})# 添加⼀个邮箱是否激活的字段,默认值为False,及该邮箱未激活email_active = models.BooleanField('邮箱激活状态',default=False)# 源信息,内嵌类,可以给我们的model定义元数据class Meta:db_table = 'tb_user'# 指定数据库表名verbose_name = '⽤户'# 在admin站点显⽰的名称verbose_name_plural = verbose_name # 复数# 为了⽅便在我们调⽤该类时可以看到我们创建的⽤户名称def__str__(self):return ername# 通过 createsuperuser 这个命令创建⽤户时,需要的字段# 该参数⾥⾯的内容需要和我们上⽅唇膏就的字段名相同REQUIRED_FIELDS = ['mobile']# user模型相当强⼤,还有修改必须输出email这个⾏为# 这时候就需要⽤到我们的管理器了object,可以查看AbstractUser这个模型类中的管理器 objects = UserManager()# UserManager这个就是管理器的内容,我们可以进⾏重写部分模块,来达到我们的⾃定义管理器的⽬的# 因为我们需要创建⽤户时不需要必须填写email,我们创建⽤户时⼜需要⽤到createsuperuser这个命令# 所以我们需要复写UserManager这个类中的create_superuser的⽅法,因为我们创建⽤户时,调⽤的就是这个⽅法# 因为我们创建的⾃定义管理器不能和继承⾃带管理器的类同名,所以我们给继承的django的管理器起⼀个别名,再进⾏继承# 在上⽅复写好了我们⾃定义的管理器后,需要在User模型类中指定该⾃定义管理器objects = UserManager() 2)位置在apps⽂件夹中User应⽤中的models.py⽂件中 3)在主⽬录下的settings⽂件中添加我们⾃定义模型类的地址(告诉整个项⽬我们的⽤户模型类已经修改了,并且位置在XXX)# 注明我们的User模型的导⼊路径AUTH_USER_MODEL = 'er'# er这个地址是因为我们创建的⽤户模型类是在user这个app下的User这个类作为⽤户模型类 4)在pycharm中进⾏远程连接我们的虚拟机 找到菜单栏中的Tools下⾯的start SSH session ,然后选择我们的远程主机地址连接即可。
实例讲解网络验证码的破解所谓验证码,就是将一串随机产生的数字或符号,生成一幅图片,图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。
不少网站为了防止用户利用机器人自动注册、登录、灌水,都采用了验证码技术。
很多验证码实现都有问题。
比如直接给出用验证码在网页和cookies中。
验证码在网页中的例子://验证用户输入是否和验证码一致if(isset($HTTP_POST_V ARS[’authinput’if(strcmp($HTTP_POST_V ARS[’authnum’],$HTTP_POST_V ARS[’authinput’echo "验证成功!echo "验证失败!//生成新的四位整数验证码请输入验证码:print("校验码不正确第二种要比上一种聪明一点,把验证码值存放在用户Cookies中。
可是由于Cookies是用户可读可写,所以也极易被突破。
curl /index.php -c common_cookie # 接受服务器的初始curl /get_code.php -c $username.cook -b common_cookie # 得到验证码,从cookies中curl /login.php -b $username.cook -d authnum=$authnum -d username=$username -d password=$password # 使用cookies中的验证码登陆更高级的验证码。
(好像本论坛的就是这种。
)有一类验证码比以上两种验证码要高级一些,它使用如下算法:1。
服务器生成一个随机hash。
2。
使用某个算法(不可逆,破解难度高的)将hash转化成为验证码数字,再转化成图片。
3。
hash在cookie中被发送到客户端3。
客户以图片输入验证码,进行登录。
服务器检查f(hash)=验证码。
java将图⽚转为base64返回给前端本⽂实例为⼤家分享了java将图⽚转为base64返回给前端的具体代码,供⼤家参考,具体内容如下⼀、controller端代码@RequestMapping(value = "/captcha")public void imagecode(HttpServletRequest request, HttpServletResponse response) throws Exception {JSONObject object = new JSONObject();CaptchaGenerator vcg = new CaptchaGenerator();String vcode = vcg.generatorVCode();BufferedImage vcodeImage = vcg.generatorVCodeImage(vcode, true);response.setDateHeader("Expires", 0);response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");response.addHeader("Cache-Control", "post-check=0, pre-check=0");response.setHeader("Pragma", "no-cache");ByteArrayOutputStream outputStream = new ByteArrayOutputStream();response.addHeader("code", vcode.toLowerCase());try {ImageIO.write(vcodeImage, "png", outputStream);BASE64Encoder encoder = new BASE64Encoder();String base64 = encoder.encodeBuffer(outputStream.toByteArray()).trim();base64 = base64.replaceAll("\n", "").replaceAll("\r", "");object.put("code", "data:image/jpg;base64," + base64);response.getWriter().write(object.toString());} catch (IOException e) {response.getWriter().write("");} finally {if (outputStream != null) {outputStream.flush();outputStream.close();response.getWriter().close();}}}⼆、⽣成验证码的代码(从某博客拷过来直接⽤的)package com.kinth.security.web.util;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.image.BufferedImage;import java.util.Random;/*** 验证码⽣成器***/public class CaptchaGenerator {/*** 验证码来源*/final private char[] code = {'2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j','k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v','w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F','G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R','S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};/**"Verdana", "Times", "Tahoma", "Georgia"};/*** 字体样式*/final private int[] fontStyles = new int[]{Font.BOLD, Font.ITALIC|Font.BOLD};/*** 验证码长度* 默认4个字符*/private int vcodeLen = 4;/*** 验证码图⽚字体⼤⼩* 默认17*/private int fontsize = 21;/*** 验证码图⽚宽度*/private int width = (fontsize+1)*vcodeLen+10;/*** 验证码图⽚⾼度*/private int height = fontsize+12;/*** ⼲扰线条数* 默认3条*/private int disturbline = 3;public CaptchaGenerator(){}/*** 指定验证码长度* @param vcodeLen 验证码长度*/public CaptchaGenerator(int vcodeLen) {this.vcodeLen = vcodeLen;this.width = (fontsize+1)*vcodeLen+10;}/*** ⽣成验证码图⽚* @param vcode 要画的验证码* @param drawline 是否画⼲扰线* @return*/public BufferedImage generatorVCodeImage(String vcode, boolean drawline){//创建验证码图⽚BufferedImage vcodeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = vcodeImage.getGraphics();//填充背景⾊g.setColor(new Color(246, 240, 250));g.fillRect(0, 0, width, height);if(drawline){drawDisturbLine(g);}//⽤于⽣成伪随机数Random ran = new Random();//在图⽚上画验证码for(int i = 0;i < vcode.length();i++){//设置字体g.setFont(new Font(fontNames[ran.nextInt(fontNames.length)], fontStyles[ran.nextInt(fontStyles.length)], fontsize)); //随机⽣成颜⾊g.setColor(getRandomColor());//画验证码g.drawString(vcode.charAt(i)+"", i*fontsize+10, fontsize+5);}//释放此图形的上下⽂以及它使⽤的所有系统资源* 获得旋转字体的验证码图⽚* @param vcode* @param drawline 是否画⼲扰线* @return*/public BufferedImage generatorRotateVCodeImage(String vcode, boolean drawline){//创建验证码图⽚BufferedImage rotateVcodeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = rotateVcodeImage.createGraphics();//填充背景⾊g2d.setColor(new Color(246, 240, 250));g2d.fillRect(0, 0, width, height);if(drawline){drawDisturbLine(g2d);}//在图⽚上画验证码for(int i = 0;i < vcode.length();i++){BufferedImage rotateImage = getRotateImage(vcode.charAt(i));g2d.drawImage(rotateImage, null, (int) (this.height * 0.7) * i, 0);}g2d.dispose();return rotateVcodeImage;}/*** ⽣成验证码* @return 验证码*/public String generatorVCode(){int len = code.length;Random ran = new Random();StringBuffer sb = new StringBuffer();for(int i = 0;i < vcodeLen;i++){int index = ran.nextInt(len);sb.append(code[index]);}return sb.toString();}/*** 为验证码图⽚画⼀些⼲扰线* @param g*/private void drawDisturbLine(Graphics g){Random ran = new Random();for(int i = 0;i < disturbline;i++){int x1 = ran.nextInt(width);int y1 = ran.nextInt(height);int x2 = ran.nextInt(width);int y2 = ran.nextInt(height);g.setColor(getRandomColor());//画⼲扰线g.drawLine(x1, y1, x2, y2);}}/*** 获取⼀张旋转的图⽚* @param c 要画的字符* @return*/private BufferedImage getRotateImage(char c){BufferedImage rotateImage = new BufferedImage(height, height, BufferedImage.TYPE_INT_ARGB);Graphics2D g2d = rotateImage.createGraphics();//设置透明度为0g2d.setColor(new Color(255, 255, 255, 0));g2d.fillRect(0, 0, height, height);Random ran = new Random();g2d.setFont(new Font(fontNames[ran.nextInt(fontNames.length)], fontStyles[ran.nextInt(fontStyles.length)], fontsize)); g2d.setColor(getRandomColor());double theta = getTheta();//旋转图⽚g2d.rotate(theta, height/2, height/2);g2d.drawString(Character.toString(c), (height-fontsize)/2, fontsize+5);* @return 返回⼀个随机颜⾊*/private Color getRandomColor(){Random ran = new Random();return new Color(ran.nextInt(220), ran.nextInt(220), ran.nextInt(220)); }/*** @return ⾓度*/private double getTheta(){return ((int) (Math.random()*1000) % 2 == 0 ? -1 : 1)*Math.random(); }/*** @return 验证码字符个数*/public int getVcodeLen() {return vcodeLen;}/*** 设置验证码字符个数* @param vcodeLen*/public void setVcodeLen(int vcodeLen) {this.width = (fontsize+3)*vcodeLen+10;this.vcodeLen = vcodeLen;}/*** @return 字体⼤⼩*/public int getFontsize() {return fontsize;}/*** 设置字体⼤⼩* @param fontsize*/public void setFontsize(int fontsize) {this.width = (fontsize+3)*vcodeLen+10;this.height = fontsize+15;this.fontsize = fontsize;}/*** @return 图⽚宽度*/public int getWidth() {return width;}/*** 设置图⽚宽度* @param width*/public void setWidth(int width) {this.width = width;}/*** @return 图⽚⾼度*/public int getHeight() {return height;}/*** 设置图⽚⾼度* @param height*/public void setHeight(int height) {this.height = height;}/*** @return ⼲扰线条数*/* 设置⼲扰线条数* @param disturbline*/public void setDisturbline(int disturbline) {this.disturbline = disturbline;}}三、前端显⽰<%@ page language="java" contentType="text/html; charset=ISO-8859-1"pageEncoding="ISO-8859-1"%><!DOCTYPE html><html><head><meta charset="ISO-8859-1"><title>Insert title here</title><script src="../static/model/js/jquery-1.11.2.min.js"></script></head><body><img id="randomImage" src="" /><script type="text/javascript">$(function() {refreshimg();})function refreshimg() {$.ajax({type : "POST",dataType : "json",url : "../article/captcha",success : function(data) {console.log('base64=' + data.codePic);$('#randomImage').attr('src', data.code);},error : function() {}});$("#randomImage").click(refreshimg)}</script></body></html>以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
idea 2023servlet项目创建流程创建一个2023servlet项目的流程如下:1. 安装Java开发环境:首先,确保你的计算机上已经安装了Java Development Kit (JDK)。
你可以从Oracle官网下载并安装合适版本的JDK。
2. 创建项目目录:在任意合适的文件夹中创建一个新目录,用于存放你的servlet项目。
3. 建立文件结构:在项目目录中创建以下文件夹和文件结构:- src: 用于存放Java源代码文件。
- web: 用于存放Web相关文件,如HTML、CSS、JavaScript 等。
- lib: 用于存放项目所需的外部库文件,如servlet API。
- WEB-INF: 用于存放Web应用程序的配置文件和资源。
- build: 用于存放编译生成的class文件。
4. 创建web.xml文件:在WEB-INF目录下创建一个名为web.xml的文件,该文件用于配置servlet和其他Web应用程序的相关设置。
web.xml文件是一个XML文件,你可以在其中定义servlet、URL映射等。
5. 创建Java源代码文件:在src目录下创建一个Java文件,用于编写servlet的代码。
你可以创建一个类继承HttpServlet 类,并实现doGet()或doPost()方法来处理HTTP请求。
在其中编写你的业务逻辑。
6. 配置构建工具:如果你想使用构建工具来构建和管理项目,可以在项目根目录中创建适当的构建配置文件,如Maven的pom.xml或Gradle的build.gradle文件,并配置相关依赖项。
7. 编译和打包项目:使用命令行工具,进入项目根目录,并执行相应命令来编译和打包项目。
根据你的构建工具和项目结构,命令可能会有所不同。
例如,如果你使用Maven,可以执行mvn compile命令来编译项目。
8. 配置服务器:选择一个合适的Web服务器,如Apache Tomcat,并将打包好的项目部署到服务器中。
模拟精灵是首个公开最有效的验证码识别技术的软件,使用模拟精灵制作了大量的免费、商用群发软件,对很多复杂BT的验证码都能成功的识别。
但是验证码仍然需要精湛的技术与足够的耐心。
请牢记这一点。
验证码识别不适合浮躁的人去做。
验证码识别是一项特殊的技术,任何一个公开的验证码识别代码都会很快的失效。
因为代码的公开后相关网站都会很快的更改验证码。
所以下面我只会介绍其原理。
在这里讨论验证码识别技术纯粹基于技术研究目的。
公开此技术也是为了让更多的网站采取更有效的防范措施。
禁止任何人利用这里介绍的验证码识别技术滥发垃圾信息。
本文介绍的验证码识别适用于比较复杂的图片验证码,也是大多数网站采用的方法。
有一些网站的验证码极简单,例如在网页中直接显示验证码字符而不是图片,或者图片的文件名直接就是验证码上的字符。
或者有其他规律可循,或者有其他明显的漏洞可以利用(例如通过改写访问验证码页面的源代码使验证码不刷新)。
这一类的验证码识别极其简单,只要熟练掌握web库、element库的函数即可,不需要使用下面介绍的方法。
一、下载验证码样本打开c:\test文件夹,选“查看缩略图”,然后重复运行下面的LAScript脚本,每运行一次,就查看c:\test下自动生成的图片,把图片上的字符改为文件名.例如图片上面显示5,就把文件名改为5.jpg.如果变化比较复杂的验证码,可以对每个字符多用几个样本,第一个字符为验证码字符,第二个字符可以为任意字符。
例如:5a.jpg , 5b.jpg , 5c.jpg ...........等等。
样本多就会识别能力就越强。
img = image.new();--下载图像,没有后缀名要显示指定*.bmp格式img:getURL("http://www.***.com/test.asp","*.png");assert(img:ok(),"下载验证码失败");img:Crop(4 ,3 , 56 ,18 )img:save("c:\\test\\test.jpg") --保存到硬盘--折分图片,指定一行四列img2,img3,img4,img5 = img:split(1,4);img2:save("c:\\test\\0001.jpg")img3:save("c:\\test\\0002.jpg")img4:save("c:\\test\\0003.jpg")img5:save("c:\\test\\0004.jpg")image.del(img);如何确定图片后缀名在整个验证码识别过程中,格式与后缀名一定不能搞错,否则就会失败。
uniapp解决图形验证码问题及arraybuffer⼆进制转base64格式图⽚须知:浏览器端⽹站请求接⼝时,会⾃动携带token。
所以浏览器⽹站没有此问题,⽆需从获取图形验证码的接⼝获取token,因为浏览器⾃动传的,不需⼿动操作。
获取图形验证码时直接将接⼝请求地址赋值给src即可,如下:现在的问题是:在uniapp中包含⼩程序及app端的情况,请求接⼝时是不会⾃动携带token的,需要⼿动添加。
所以我们就需要先从获取图形验证码的接⼝获取token,才能在验证图形验证码时额外⼿动添加token。
步骤及说明:先在请求图形验证码的接⼝拿到图形验证码信息,包括token和乱码的图形验证码图⽚信息。
如下(data⾥是图⽚信息,cookies⾥包含的就是token了)以上⽅式肯定是拿不到图形验证码的图⽚的。
我们需要经过以下处理1、请求获取图形码接⼝时设置响应类型reponseType为arraybuffer2、使⽤uni.arrayBufferToBase64(arrayBuffer)此api处理请求结果。
此处注意base64转码后的字符串需要添加data:image/png;base64,前缀3、请求验证接⼝时给Cookie⾥添加token直接上代码<script>export default{data(){verifyCodeImg:'', //验证码图⽚verifyCodeToken:'', //图形验证码的验证tokenisVerifyCodeTure:false, //验证码输⼊是否正确},onLoad(){this.getVerifyCodeImg()},methods:{//获取图形验证码及其验证tokengetVerifyCodeImg(){uni.request({url: `${this.$baseUrl}/api-user/getVerification?t=${Math.random()}`,method: 'GET',responseType: 'arraybuffer', //设置响应类型success: res => {//将 ArrayBuffer 对象转成 Base64 字符串const arrayBuffer = new Uint8Array(res.data)const base64 = "data:image/png;base64,"+uni.arrayBufferToBase64(arrayBuffer) //这⾥需要添加前缀this.verifyCodeImg=base64//需要注意的是,微信⼩程序与app端的数据返回格式是略有不同的的,所以请以⼀下这种⽅式获取token,⽽不要⽤this.verifyCodeToken=res.cookies[0](具体格式见下图) this.verifyCodeToken=res.header["Set-Cookie"]},fail: () => {},});},//检查图形验证码对错checkVerifyCode(){if(this.verifyCode.length>=4){let headers={"Token": this.verifyCodeToken //将token信息添加⾄请求头⾥}uni.request({url: `${this.$baseUrl}/api-user/checkVerification?code=${this.verifyCode}`,method: 'GET',header: headers,success: res => {if(res.data.code==200){this.isVerifyCodeTure=true}else{this.isVerifyCodeTure=falsethis.verifyCode=''this.getVerifyCodeImg()uni.showToast({title: '图形验证码输⼊错误',icon:'none'});}},fail: () => {},});}else{this.isVerifyCodeTure=false}},}}</script>微信⼩程序端图形验证码的数据返回格式app端图形验证码的数据返回格式请求头中cookie设置以这种形式。
图片验证码生成: 摆渡恋人 Web.xml文件配置: This is the description of my J2EE component This is the display name of my J2EE component ImageCheckServlet check.servlet.ImageCheckServlet width 800 height 400 codeCount 4
ImageCheckServlet /servlet/ImageCheckServlet
Package check.servlet; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.Random;
import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
public class ImageCheckServlet extends HttpServlet { /** * */ private static final long serialVersionUID = -1475131268628773633L;
/** * 验证码图片的宽度。 */ private int width = 80;
/** * 验证码图片的高度。 */ private int height = 40;
/** * 验证码字符个数 */ private int codeCount = 4;
/** * 字体高度 */ private int fontHeight;
private int codeX = 0; private int codeY = 0;
char[] codeSequence = { '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' }; /** * 初始化验证图片属性 */ public void init() throws ServletException { /**
* 从web.xml中获取初始信息 */ /** * 宽度 */ String strWidth = this.getInitParameter("width"); /** * 高度 */ String strHeight = this.getInitParameter("height"); /** * 字符个数 */ String strCodeCount = this.getInitParameter("codeCount");
/** * 将配置的信息转换成数值 */ try { if (strWidth != null && strWidth.length() != 0) { width = Integer.parseInt(strWidth); } if (strHeight != null && strHeight.length() != 0) { height = Integer.parseInt(strHeight); } if (strCodeCount != null && strCodeCount.length() != 0) { codeCount = Integer.parseInt(strCodeCount);
/** * 在这里限制验证码字符的个数确定范围在4-10个之间 * */ if (codeCount > 8) { codeCount = 8; } if (codeCount < 4) { codeCount = 4; }
} } catch (NumberFormatException e) { e.printStackTrace(); } System.out.println("width:" + width); System.out.println("height:" + height);
/** * 字体大小应该是画布高减去上沿和下沿 * * 上下沿分别是5 */ fontHeight = (int) (height * 0.8F); /**
* 字体的X坐标 */ codeX = width / (codeCount + 1); /** * 字体的Y坐标 */ codeY = (int) (height * 0.8F); System.out.println("codeX:" + codeX); System.out.println("codeY:" + codeY);
} protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException {
/** * 定义图像buffer */ BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = buffImg.createGraphics(); /** * 将图像填充为白色 */ g.setColor(Color.WHITE); g.fillRect(0, 0, width, height);
/** * 创建字体,字体的大小应该根据图片的高度来定。 */ Font font = new Font("宋体", Font.ROMAN_BASELINE, fontHeight); /**
* 设置字体。 */ g.setFont(font);
/** * 画边框。 */ g.setColor(Color.BLACK);
/** * drawRect(x,y,width,height); *
* x,y矩形的位置 * * width,height矩形的大小 */ g.drawRect(5, 5, width - 10, height - 10);
/** * 创建一个随机数生成器类 */ Random random = new Random();
/** * 随机产生160条干扰线,使图象中的认证码不易被其它程序探测到。 */
for (int i = 0; i < 100; i++) { g.setColor(randomColor()); int x1 = random.nextInt(width); int y1 = random.nextInt(height); int x2 = random.nextInt(width); int y2 = random.nextInt(height); /**
* 在此图形上下文的坐标系中,使用当前颜色在点 (x1, y1) 和 (x2, y2) 之间画一条线 */ g.drawLine(x1, y1, x2, y2); } /**
* randomCode用于保存随机产生的验证码,以便进行验证。 */ StringBuffer randomCode = new StringBuffer();
// 随机产生codeCount数字的验证码。 for (int i = 0; i < codeCount; i++) { /**
* 得到随机产生的验证码数字。 */ String strRand = String.valueOf(codeSequence[random.nextInt(36)]); /**
* 设置验证码的随机颜色值 */ g.setColor(randomColor()); /**
* 将验证码画到画布上去 */ g.drawString(strRand, (i + 1) * codeX - (int) (buffImg.getWidth() * 0.65F / codeCount), codeY); /** * 将产生的四个随机数组合在一起,在验证的时候使用 */ randomCode.append(strRand); } /** * 将四位数字的验证码保存到Session中。 */ HttpSession session = req.getSession(); session.setAttribute("validateCode",