2024-10-12 07:40:55
导读:今天首席CTO笔记来给各位分享关于django中怎么添加验证码的相关内容,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
python怎么批量提交验证码现在的网页中,为了防止机器人提交表单,图片验证码是很常见的应对手段之一。这里就不详细介绍了,相信大家都遇到过。
现在就给出用Python的PIL库实现验证码图片的代码。代码中有详细注释。
#!/usr/bin/envpython
#coding=utf-8
importrandom
fromPILimportImage,ImageDraw,ImageFont,ImageFilter
_letter_cases="abcdefghjkmnpqrstuvwxy"#小写字母,去除可能干扰的i,l,o,z
_upper_cases=_letter_cases.upper()#大写字母
_numbers=''.join(map(str,range(3,10)))#数字
init_chars=''.join((_letter_cases,_upper_cases,_numbers))
defcreate_validate_code(size=(120,30),
chars=init_chars,
img_type="GIF",
mode="RGB",
bg_color=(255,255,255),
fg_color=(0,0,255),
font_size=18,
font_type="ae_AlArabiya.ttf",
length=4,
draw_lines=True,
n_line=(1,2),
draw_points=True,
point_chance=2):
'''
@todo:生成验证码图片
@paramsize:图片的大小,格式(宽,高),默认为(120,30)
@paramchars:允许的字符集合,格式字符串
@paramimg_type:图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
@parammode:图片模式,默认为RGB
@parambg_color:背景颜色,默认为白色
@paramfg_color:前景色,验证码字符颜色,默认为蓝色#0000FF
@paramfont_size:验证码字体大小
@paramfont_type:验证码字体,默认为ae_AlArabiya.ttf
@paramlength:验证码字符个数
@paramdraw_lines:是否划干扰线
@paramn_lines:干扰线的条数范围,格式元组,默认为(1,2),只有draw_lines为True时有效
@paramdraw_points:是否画干扰点
@parampoint_chance:干扰点出现的概率,大小范围[0,100]
@return:[0]:PILImage实例
@return:[1]:验证码图片中的字符串
'''
width,height=size#宽,高
img=Image.new(mode,size,bg_color)#创建图形
draw=ImageDraw.Draw(img)#创建画笔
defget_chars():
'''生成给定长度的字符串,返回列表格式'''
returnrandom.sample(chars,length)
defcreate_lines():
'''绘制干扰线'''
line_num=random.randint(*n_line)#干扰线条数
foriinrange(line_num):
#起始点
begin=(random.randint(0,size[0]),random.randint(0,size[1]))
#结束点
end=(random.randint(0,size[0]),random.randint(0,size[1]))
draw.line([begin,end],fill=(0,0,0))
defcreate_points():
'''绘制干扰点'''
chance=min(100,max(0,int(point_chance)))#大小限制在[0,100]
forwinxrange(width):
forhinxrange(height):
tmp=random.randint(0,100)
iftmp100-chance:
draw.point((w,h),fill=(0,0,0))
defcreate_strs():
'''绘制验证码字符'''
c_chars=get_chars()
strs='%s'%''.join(c_chars)#每个字符前后以空格隔开
font=ImageFont.truetype(font_type,font_size)
font_width,font_height=font.getsize(strs)
draw.text(((width-font_width)/3,(height-font_height)/3),
strs,font=font,fill=fg_color)
return''.join(c_chars)
ifdraw_lines:
create_lines()
ifdraw_points:
create_points()
strs=create_strs()
#图形扭曲参数
params=[1-float(random.randint(1,2))/100,
0,
0,
0,
1-float(random.randint(1,10))/100,
float(random.randint(1,2))/500,
0.001,
float(random.randint(1,2))/500
]
img=img.transform(size,Image.PERSPECTIVE,params)#创建扭曲
img=img.filter(ImageFilter.EDGE_ENHANCE_MORE)#滤镜,边界加强(阈值更大)
returnimg,strs
if__name__=="__main__":
code_img=create_validate_code()
code_img.save("validate.gif","GIF")
最后结果返回一个元组,第一个返回值是Image类的实例,第二个参数是图片中的字符串(比较是否正确的作用)。
最后结果返回一个元组,第一个返回值是Image类的实例,第二个参数是图片中的字符串(比较是否正确的作用)。
需要提醒的是,如果在生成ImageFont.truetype实例的时候抛出IOError异常,有可能是运行代码的电脑没有包含指定的字体,需要下载安装。
生成的验证码图片效果:
这时候,细心的同学可能要问,如果每次生成验证码,都要先保存生成的图片,再显示到页面。这么做让人太不能接受了。这个时候,我们需要使用python内置的StringIO模块,它有着类似file对象的行为,但是它操作的是内存文件。于是,我们可以这么写代码:
try:
importcStringIOasStringIO
exceptImportError:
importStringIO
mstream=StringIO.StringIO()
img=create_validate_code()[0]
img.save(mstream,"GIF")
这样,我们需要输出的图片的时候只要使用“mstream.getvalue()”即可。比如在Django里,我们首先定义这样的url:
fromdjango.conf.urls.defaultsimport*
urlpatterns=patterns('example.views',
url(r'^validate/$','validate',name='validate'),
)
在views中,我们把正确的字符串保存在session中,这样当用户提交表单的时候,就可以和session中的正确字符串进行比较。
fromdjango.shortcutsimportHttpResponse
fromvalidateimportcreate_validate_code
defvalidate(request):
mstream=StringIO.StringIO()
validate_code=create_validate_code()
img=validate_code[0]
img.save(mstream,"GIF")
request.session['validate']=validate_code[1]
returnHttpResponse(mstream.getvalue(),"image/gif")
django验证码用returnrender_to_response('bb.html',{'news':buf.getvalue()})不能正常显示图片!render_to_response('bb.html',{'news':(buf.getvalue(),'image/gif')})
这一句呢有些问题。bb.html模板形式返回结果。如果我没有理解错的话,只能返回html格式,也许可以返回css,js。但是原则上不能返回image格式。
另外你的bb.html里的内容是什么呢?是不是只有一句话呢?
如果是。可以这样。
r=render_to_response('bb.html',{'news':(buf.getvalue(),'image/gif')})
然后引用r,试图改写它的Content-Type为'image/gif'
也许可以成功。只是也许。
Java如何实现验证码验证功能
Java如何实现验证码验证功能呢?日常生活中,验证码随处可见,他可以在一定程度上保护账号安全,那么他是怎么实现的呢?
Java实现验证码验证功能其实非常简单:用到了一个Graphics类在画板上绘制字母,随机选取一定数量的字母随机生成,然后在画板上随机生成几条干扰线。
首先,写一个验证码生成帮助类,用来绘制随机字母:
import?java.awt.Color;
import?java.awt.Font;
import?java.awt.Graphics;
import?java.awt.image.BufferedImage;
import?java.io.IOException;
import?java.io.OutputStream;
import?java.util.Random;
import?javax.imageio.ImageIO;
public?final?class?GraphicHelper?{
/**
*?以字符串形式返回生成的验证码,同时输出一个图片
*
*?@param?width
*????????????图片的宽度
*?@param?height
*????????????图片的高度
*?@param?imgType
*????????????图片的类型
*?@param?output
*????????????图片的输出流(图片将输出到这个流中)
*?@return?返回所生成的验证码(字符串)
*/
public?static?String?create(final?int?width,?final?int?height,?final?String?imgType,?OutputStream?output)?{
StringBuffer?sb?=?new?StringBuffer();
Random?random?=?new?Random();
BufferedImage?image?=?new?BufferedImage(width,?height,?BufferedImage.TYPE_INT_RGB);
Graphics?graphic?=?image.getGraphics();
graphic.setColor(Color.getColor("F8F8F8"));
graphic.fillRect(0,?0,?width,?height);
Color[]?colors?=?new?Color[]?{?Color.BLUE,?Color.GRAY,?Color.GREEN,?Color.RED,?Color.BLACK,?Color.ORANGE,
Color.CYAN?};
//?在?"画板"上生成干扰线条?(?50?是线条个数)
for?(int?i?=?0;?i??50;?i++)?{
graphic.setColor(colors[random.nextInt(colors.length)]);
final?int?x?=?random.nextInt(width);
final?int?y?=?random.nextInt(height);
final?int?w?=?random.nextInt(20);
final?int?h?=?random.nextInt(20);
final?int?signA?=?random.nextBoolean()???1?:?-1;
final?int?signB?=?random.nextBoolean()???1?:?-1;
graphic.drawLine(x,?y,?x?+?w?*?signA,?y?+?h?*?signB);
}
//?在?"画板"上绘制字母
graphic.setFont(new?Font("Comic?Sans?MS",?Font.BOLD,?30));
for?(int?i?=?0;?i??6;?i++)?{
final?int?temp?=?random.nextInt(26)?+?97;
String?s?=?String.valueOf((char)?temp);
sb.append(s);
graphic.setColor(colors[random.nextInt(colors.length)]);
graphic.drawString(s,?i?*?(width?/?6),?height?-?(height?/?3));
}
graphic.dispose();
try?{
ImageIO.write(image,?imgType,?output);
}?catch?(IOException?e)?{
e.printStackTrace();
}
return?sb.toString();
}
}?
接着,创建一个servlet,用来固定图片大小,以及处理验证码的使用场景,以及捕获页面生成的验证码(捕获到的二维码与用户输入的验证码一致才能通过)。
import?java.io.OutputStream;
import?javax.servlet.ServletException;
import?javax.servlet.annotation.WebServlet;
import?javax.servlet.http.HttpServlet;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?javax.servlet.http.HttpSession;
@WebServlet(urlPatterns?=?"/verify/regist.do"?)
public?class?VerifyCodeServlet?extends?HttpServlet?{
private?static?final?long?serialVersionUID?=?3398560501558431737L;
@Override
protected?void?service(HttpServletRequest?request,?HttpServletResponse?response)
throws?ServletException,?IOException?{
//?获得?当前请求?对应的?会话对象
HttpSession?session?=?request.getSession();
//?从请求中获得?URI?(?统一资源标识符?)
String?uri?=?request.getRequestURI();
System.out.println("hello?:?"?+?uri);
final?int?width?=?180;?//?图片宽度
final?int?height?=?40;?//?图片高度
final?String?imgType?=?"jpeg";?//?指定图片格式?(不是指MIME类型)
final?OutputStream?output?=?response.getOutputStream();?//?获得可以向客户端返回图片的输出流
//?(字节流)
//?创建验证码图片并返回图片上的字符串
String?code?=?GraphicHelper.create(width,?height,?imgType,?output);
System.out.println("验证码内容:?"?+?code);
//?建立?uri?和?相应的?验证码?的关联?(?存储到当前会话对象的属性中?)
session.setAttribute(uri,?code);
System.out.println(session.getAttribute(uri));
}
}?
接着写一个HTML注册页面用来检验一下:
html
head
meta?charset="UTF-8"
title注册/title
link?rel="stylesheet"?href="styles/general.css"
link?rel="stylesheet"?href="styles/cell.css"
link?rel="stylesheet"?href="styles/form.css"
script?type="text/javascript"?src="js/ref.js"/script
style?type="text/css"?
.logo-container?{
margin-top:?50px?;
}
.logo-container?img?{
width:?100px?;
}
.message-container?{
height:?80px?;
}
.link-container?{
height:?40px?;
line-height:?40px?;
}
.link-container?a?{
text-decoration:?none?;
}
/style
/head
body
div?class="container?form-container"
form?action="/wendao/regist.do"?method="post"
div?class="form"?!--?注册表单开始?--
div?class="form-row"
span?class="cell-1"
i?class="fa?fa-user"/i
/span
span?class="cell-11"?style="text-align:?left;"
input?type="text"?name="username"?placeholder="请输入用户名"
/span
/div
div?class="form-row"
span?class="cell-1"
i?class="fa?fa-key"/i
/span
span?class="cell-11"?style="text-align:?left;"
input?type="password"?name="password"?placeholder="请输入密码"
/span
/div
div?class="