图形验证码---pillow
图片验证码逻辑
- 客户端发起GET连接请求,并随机生成UUID,绑定图片
UUID
:通用唯一识别码(Universally Unique Identifier
),目的,是让分布式系统中的所有元素,都能有唯一的辨识信息,每个人都可以创建不与其它人冲突的UUID
- 服务端生成图片验证码,图片存入内存并返回到客户端
- 服务端存储源字符串到
session
中,也可以存入缓存中,例memcached
、redis
- 客户端表单填写验证码原值
- 移出表单框时间触发异步
post
请求验证,访问时,图片uuid
作为属性绑定到表单属性中,作为post
提交的数据一部分 - 服务端验证时通过
UUID
为key
,表单值为value进行图片验证码校验
图片验证码使用
下载pillow
pip install pillow
在使用的时候需要设置pillow需要的字体。需要复制到django项目中
设置字体文件的路径
FONTS_DIRS = os.path.join(BASE_DIR, 'fonts',) #找到字体文件的路径
setting.py
生成图片
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path("generate_image_code/<str:generate_image_id>/",views.generate_image_code), ]
urls.py
from PIL import Image, ImageDraw, ImageFont
from shiyanloupro.settings import *
from django.http.response import HttpResponse def generate_image_code(request, generate_image_id):
'''
本地图片验证码生成函数
'''
bgcolor = (random.randrange(20, 100), random.randrange(
20, 100), random.randrange(20, 100))
width = 110
height = 40
# 创建画面对象
im = Image.new('RGB', (width, height), bgcolor)
# 创建画笔对象
draw = ImageDraw.Draw(im)
# 调用画笔的point()函数绘制噪点
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
draw.point(xy, fill=fill)
# 定义验证码的备选值
str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
# 随机选取4个值作为验证码
rand_str = ''
for i in range(0, 4):
rand_str += str[random.randrange(0, len(str))]
# 构造字体对象 fonts_files = os.path.join(
FONTS_DIRS, 'SourceCodePro-Bold.ttf')
font = ImageFont.truetype(fonts_files, 30)
# 构造字体颜色
fontcolor1 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor2 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor3 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor4 = (255, random.randrange(0, 255), random.randrange(0, 255))
# 绘制4个字
draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1)
draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2)
draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3)
draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4)
# 释放画笔
del draw
# 存入缓存,用于做进一步验证,并设置超时时间为10分组
cache.set(generate_image_id,rand_str,60*10)
buf = io.BytesIO()
# 将图片保存在内存中,文件类型为png
im.save(buf, 'png')
# 将内存中的图片数据返回给客户端,MIME类型为图片png!
return HttpResponse(buf.getvalue(), 'image/png')
views.py
vue生成uuid
generate_uuid: function() {
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); //use high-precision timer if available
}
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
}
);
return uuid;
},
regist.vue
vue请求图片验证码
<template>
<div> <p><img @click="refresh()" :src="'http://127.0.0.1:8000/user/generate_image_code/' + uuid" /></p>
<p>验证码<input type="text" v-model="code"></p> </div>
</template> <script>
import axios from 'axios'
export default {
name:"regist",
data() {
return {
code:'',
uuid:'',
}
},
methods: {
generate_uuid: function() {
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); //use high-precision timer if available
}
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
}
);
return uuid;
},
refresh(){
this.uuid = this.generate_uuid()
}
},
mounted() {
this.uuid = this.generate_uuid()
},
}
</script>
带图片验证码的用户注册
<template>
<div>
<p>用户名:<input type="text" v-model="name"></p>
<p>密码:<input type="password" v-model="pwd"></p>
<p>手机号:<input type="text" v-model="phone"></p>
<p>邮箱:<input type="email" v-model="email"></p>
<p><img @click="refresh()" :src="'http://127.0.0.1:8000/user/generate_image_code/' + uuid" /></p>
<p>验证码<input type="text" v-model="code" @blur="check"></p>
<p><button @click="regist_user()">注册</button></p> </div>
</template> <script>
import axios from 'axios'
export default {
name:"regist",
data() {
return {
code:'',
name:'',
pwd:'',
phone:'',
email:'',
uuid:'',
is_ok:false }
},
methods: {
generate_uuid: function() {
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); //use high-precision timer if available
}
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
}
);
return uuid;
},
refresh(){
this.uuid = this.generate_uuid()
},
check(){
let post_data = new FormData()
post_data.append('generate_image_id',this.uuid)
post_data.append('user_code',this.code)
axios({
url: 'http://127.0.0.1:8000/user/check/',
method: 'post',
data: post_data,
}).then(res=>{
console.log(res.data)
if (res.data.code==200){
this.is_ok=true
}else{
this.is_ok=false
}
}) },
regist_user(){
if(this.is_ok==true){
var form_data = new FormData()
form_data.append("username",this.name)
form_data.append("password",this.pwd)
form_data.append("phone",this.phone)
form_data.append("email",this.email)
axios({
url: 'http://127.0.0.1:8000/user/users/',
method: 'post',
data: form_data,
}).then(res=>{
console.log(res.data)
sessionStorage.setItem("jwt_token",res.data.token)
alert("注册成功") })
}else{
alert("注册前请输入正确的用户码")
} }
},
mounted() {
this.uuid = this.generate_uuid()
},
}
</script>
regist.vue
"""
Django settings for shiyanloupro project. Generated by 'django-admin startproject' using Django 2.2.7. For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/ For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
""" import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'f84z(fu2k-n^*38fn+o5xbx0wyxq*hrk-rs7__75p0ux$x8s2*' # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'corsheaders',
'rest_framework.authtoken',
'userapp'
] MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
] ROOT_URLCONF = 'shiyanloupro.urls' TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
] WSGI_APPLICATION = 'shiyanloupro.wsgi.application' # Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': 'root', # 数据库用户密码
'NAME': 'shiyanlou' # 数据库名字
}
} # Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
] # Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/ STATIC_URL = '/static/' CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = ()
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
) CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
) FONTS_DIRS = os.path.join(BASE_DIR, 'fonts',)
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}
AUTH_USER_MODEL='userapp.User'
REST_FRAMEWORK = {
# 身份认证
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
), #全局配置接口权限
# 'DEFAULT_PERMISSION_CLASSES': (
# 'rest_framework.permissions.IsAuthenticated',
# ), } import datetime JWT_AUTH = {
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_RESPONSE_PAYLOAD_HANDLER':
'users.views.jwt_response_payload_handler', # 重新login登录返回函数
}
setting.py
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path("generate_image_code/<str:generate_image_id>/",views.generate_image_code),
path("check/",views.CheckCode.as_view()),
path("users/",views.UserView.as_view()), ]
user/urls.py
from rest_framework_jwt.settings import api_settings
from rest_framework import serializers
from userapp.models import User class UserSerializer(serializers.Serializer):
id =serializers.IntegerField(read_only=True)
username = serializers.CharField()
password = serializers.CharField()
phone = serializers.CharField()
email = serializers.CharField()
token = serializers.CharField(read_only=True) def create(self, data):
user = User.objects.create(**data)
#数据库里密码的加密(固定的步骤)
user.set_password(data.get('password'))
user.save() # 补充生成记录登录状态的token 固定的格式,用过来生成jwt的token
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload) #把token发放在user里返回
user.token = token
return user
user/serializers.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here. class User(AbstractUser):
username = models.CharField(max_length=64, unique=True)
password = models.CharField(max_length=255)
phone = models.CharField(max_length=64)
email = models.CharField(max_length=64)
user/model.py
from django.http.response import HttpResponse
from PIL import Image, ImageDraw, ImageFont
from shiyanloupro.settings import *
from django.core.cache import cache
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import UserSerializer
import random,os,io def generate_image_code(request, generate_image_id):
'''
本地图片验证码生成函数
'''
bgcolor = (random.randrange(20, 100), random.randrange(
20, 100), random.randrange(20, 100))
width = 110
height = 40
# 创建画面对象
im = Image.new('RGB', (width, height), bgcolor)
# 创建画笔对象
draw = ImageDraw.Draw(im)
# 调用画笔的point()函数绘制噪点
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
draw.point(xy, fill=fill)
# 定义验证码的备选值
str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
# 随机选取4个值作为验证码
rand_str = ''
for i in range(0, 4):
rand_str += str[random.randrange(0, len(str))]
# 构造字体对象 fonts_files = os.path.join(
FONTS_DIRS, 'SourceCodePro-Bold.ttf')
font = ImageFont.truetype(fonts_files, 30)
# 构造字体颜色
fontcolor1 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor2 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor3 = (255, random.randrange(0, 255), random.randrange(0, 255))
fontcolor4 = (255, random.randrange(0, 255), random.randrange(0, 255))
# 绘制4个字
draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1)
draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2)
draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3)
draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4)
# 释放画笔
del draw
# 存入缓存,用于做进一步验证,并设置超时时间为10分组
cache.set(generate_image_id,rand_str,60*10)
buf = io.BytesIO()
# 将图片保存在内存中,文件类型为png
im.save(buf, 'png')
# 将内存中的图片数据返回给客户端,MIME类型为图片png!
return HttpResponse(buf.getvalue(), 'image/png') class CheckCode(APIView):
def post(self,request):
generate_image_id = request.data.get('generate_image_id',"")
data_code = cache.get(generate_image_id)
user_code = request.data.get('user_code',"")
if data_code and user_code:
print(data_code,user_code)
if data_code.lower() == user_code.lower():
return Response({'code':200})
return Response({'code':201}) class UserView(APIView):
def post(self,request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=200)
return Response(serializer.errors, status=200)
user/views.py
图形验证码---pillow的更多相关文章
- 图形验证码 tesserocr pillow
利用tesserocr和pil生成图形验证码 import tesserocr from PIL import Image image = Image.open('222.jpg') image = ...
- Tornado框架实现图形验证码功能
图形验证码是项目开发过程中经常遇到的一个功能,在很多语言中都有对应的不同形式的图形验证码功能的封装,python 中同样也有类似的封装操作,通过绘制生成一个指定的图形数据,让前端HTML页面通过链接获 ...
- 一百一十四:CMS系统之图形验证码生成
安装Pillow库,用于生成图形验证码:pip install Pillow 字体文件来源 生成一个验证码图片 import randomimport stringfrom PIL import Im ...
- 爬虫(十二):图形验证码的识别、滑动验证码的识别(B站滑动验证码)
1. 验证码识别 随着爬虫的发展,越来越多的网站开始采用各种各样的措施来反爬虫,其中一个措施便是使用验证码.随着技术的发展,验证码也越来越花里胡哨的了.最开始就是几个数字随机组成的图像验证码,后来加入 ...
- mac使用python识别图形验证码
前言 最近在研究验证码相关的操作,所以准备记录下安装以及使用的过程.虽然之前对验证码的破解有所了解的,但是之前都是简单使用之后就不用了,没有记录一个详细的过程,所以后面再用起来也要重新从网上查找资料比 ...
- 【无私分享:ASP.NET CORE 项目实战(第十四章)】图形验证码的实现
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 很长时间没有来更新博客了,一是,最近有些忙,二是,Core也是一直在摸索中,其实已经完成了一个框架了,并且正在准备在生产环境中 ...
- C#生成图形验证码
先看效果: 再上代码 public class CaptchaHelper { private static Random rand = new Random(); private static in ...
- php 图形验证码的3种方法
生成图形验证码需要使用php GD库来生成,如果你没开户GD库我们需要在php.ini文件找到extension=php_gd2.dll 去掉前面的;就行了,然后重启apache 或iis环境即可 检 ...
- PHP5 GD库生成图形验证码(汉字)
PHP5 GD库生成图形验证码且带有汉字的实例分享. 1,利用GD库函数生成图片,并在图片上写指定字符imagecreatetruecolor 新建一个真彩色图像imagecolorallocate ...
随机推荐
- EntityFramework Core上下文实例池原理分析
前言 无论是在我个人博客还是著作中,对于上下文实例池都只是通过大量文字描述来讲解其基本原理,而且也是浅尝辄止,导致我们对其认识仍是一知半解,本文我们摆源码,从源头开始分析.希望通过本文从源码的分析,我 ...
- 9.集合set和frozenset冻结集合函数
集合set set和dict类似,也是一组key的集合,但不存储value.由于key不能重复,所以在set中没有重复的key. 集合中的元素要求是不可变的并且还是唯一的,我们就利用它是唯一来做去重. ...
- 分布式文档存储数据库之MongoDB访问控制
上一篇博客主要聊了下mongodb的分片机制以及分片集群的搭建,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13958295.html:今天我们来了解下mon ...
- JS如何判断表单中用户选择哪个哪个选项?
JS如何判断表单中用户选择哪个哪个选项? HTML代码: <form name="form1" onsubmit="return foo();"> ...
- Java 实例化接口或抽象类
1. 实例化接口: 某一天,我们想通过反射调用一个类的方法,但发现方法参数中有一个接口,我们都知道接口不能被实例化,这该怎么办呢? 举例: public class TestLib { public ...
- 痞子衡嵌入式:JLink Script文件基础及其在IAR下调用方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是JLink Script文件基础及其在IAR下调用方法. JLink可以说是MCU开发者最熟悉的调试工具了,相比于其他调试器(比如DAP ...
- 基于udp的scoket通信
1.udp例子1 udpserver.py # udp的server,不需要进行监听也不需要建立连接 # 在启动服务之后只能被动的等待客户端发送消息过来 # 客户端发送消息的同时还会自带地址信息 # ...
- Ramnit蠕虫病毒分析和查杀
Ramnit是一种蠕虫病毒.拥有多种传播方式,不仅可以通过网页进行传播,还可以通过感染计算机内可执行文件进行传播.该病毒在2010年第一次被安全研究者发现,从网络威胁监控中可以看出目前仍然有大量的主机 ...
- jboss反序列化漏洞实战渗透笔记
一.利用shodan,fofa或谷歌搜索关键字:8080/jmx-console/ 二.下载java反序列化终极测试工具进行验证漏洞 三.记住User Current Directory: C:\j ...
- C++深拷贝与浅拷贝区别
浅拷贝只是对指针的拷贝,浅拷贝后两个指针指向同一个内存空间: 深拷贝不仅对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针. 当对一个已知对象进行拷贝时,编译系统会 ...