![](https://i-blog.csdnimg.cn/blog_migrate/fb973e2e189896163b8d4558fa3f3cb0.gif)
------------------------
![](https://i-blog.csdnimg.cn/blog_migrate/dc4b1e04441f9cfd71d20133009a6526.gif)
------------------------
![](https://i-blog.csdnimg.cn/blog_migrate/fab23d355847494dbf161ee40c9b2a53.gif)
------------------------
![](https://i-blog.csdnimg.cn/blog_migrate/9faf0659b21ee1f85c38d1ff445ff2e1.gif)
演示网站下载: Click me to DOWNLOAD
验证码多种多样,为了防止被机器识别,通常都会加入干扰元素,如绘制干扰线、干扰点、背景图片,还有让字符扭曲、旋转字符等等。
我个人认为验证扭曲或旋转字符这样的干扰元素比较好,因为加入干扰线,背景图片虽然强悍,但有时可能连人都认不出来,这个会让网站显得很不友好,用户不禁火大:(。
要实现扭曲验证码必须图象大一些(至少要每字符至少要40*40的尺寸)才看地清楚,但有时我们的需求可能不允许让一个如此大尺寸的图象,此时,何不考虑用旋转的形式呢?!
旋转验证码思路不难,分几步就可以完成:
- 遍历随机字符,每个字符生成一个图象
- 旋转每一个字符图象
- 将所有字符图象拼接成一个图象
C# 代码如下:
using
System;
using System.Drawing;
using System.Web;
namespace Oran.Image
{
/// <summary>
/// 旋转的可视验证码图象
/// </summary>
public class RotatedVlidationCode
{
public enum RandomStringMode
{
/// <summary>
/// 小写字母
/// </summary>
LowerLetter,
/// <summary>
/// 大写字母
/// </summary>
UpperLetter,
/// <summary>
/// 混合大小写字母
/// </summary>
Letter,
/// <summary>
/// 数字
/// </summary>
Digital,
/// <summary>
/// 混合数字与大小字母
/// </summary>
Mix
}
public static string GenerateRandomString( int length, RandomStringMode mode)
{
string rndStr = string .Empty;
if (length == 0 )
return rndStr;
// 以数组方式候选字符,可以更方便的剔除不要的字符,如数字 0 与字母 o
char [] digitals = new char [ 10 ] { ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' };
char [] lowerLetters = new char [ 26 ] {
' 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 ' };
char [] upperLetters = new char [ 26 ] {
' 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 ' };
char [] letters = new char [ 52 ]{
' 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 ' ,
' 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 ' };
char [] mix = new char [ 62 ]{
' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' ,
' 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 ' ,
' 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 ' };
int [] range = new int [ 2 ] { 0 , 0 };
Random random = new Random();
switch (mode)
{
case RandomStringMode.Digital:
for ( int i = 0 ; i < length; ++ i)
rndStr += digitals[random.Next( 0 , digitals.Length)];
break ;
case RandomStringMode.LowerLetter:
for ( int i = 0 ; i < length; ++ i)
rndStr += lowerLetters[random.Next( 0 , lowerLetters.Length)];
break ;
case RandomStringMode.UpperLetter:
for ( int i = 0 ; i < length; ++ i)
rndStr += upperLetters[random.Next( 0 , upperLetters.Length)];
break ;
case RandomStringMode.Letter:
for ( int i = 0 ; i < length; ++ i)
rndStr += letters[random.Next( 0 , letters.Length)];
break ;
default :
for ( int i = 0 ; i < length; ++ i)
rndStr += mix[random.Next( 0 , mix.Length)];
break ;
}
return rndStr;
}
/// <summary>
/// 显示验证码
/// </summary>
/// <param name="seed"> 随机数辅助种子 </param>
/// <param name="strLen"> 验证码字符长度 </param>
/// <param name="fontSize"> 字体大小 </param>
/// <param name="mode"> 随机字符模式 </param>
/// <param name="clrFont"> 字体颜色 </param>
/// <param name="clrBg"> 背景颜色 </param>
public static void ShowValidationCode( ref int seed, int strLen, int fontSize, RandomStringMode mode, Color clrFont, Color clrBg)
{
int tmpSeed;
unchecked
{
tmpSeed = ( int )(seed * DateTime.Now.Ticks);
++ seed;
}
Random rnd = new Random(tmpSeed);
string text = GenerateRandomString(strLen, mode);
int height = fontSize * 2 ;
int width = height * text.Length;
Bitmap bmp = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(bmp);
Font font = new Font( " Courier New " , fontSize, FontStyle.Bold);
Brush brush = new SolidBrush(clrFont);
Brush brushBg = new SolidBrush(clrBg);
graphics.FillRectangle(brushBg, 0 , 0 , width, height);
Bitmap tmpBmp = new Bitmap(height, width / text.Length);
Graphics tmpGph = null ;
int degree = 40 ;
Point tmpPoint = new Point();
for ( int i = 0 ; i < text.Length; i ++ )
{
tmpBmp = new Bitmap(height, width / text.Length);
tmpGph = Graphics.FromImage(tmpBmp);
tmpGph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
tmpGph.FillRectangle(brushBg, 0 , 0 , tmpBmp.Width, tmpBmp.Height);
degree = rnd.Next( 20 , 51 ); // [20, 50]随机角度
if (rnd.Next( 0 , 2 ) == 0 )
{
tmpPoint.X = 12 ; // 调整文本坐标以适应旋转后的图象
tmpPoint.Y = - 6 ;
}
else
{
degree = ~ degree + 1 ; // 逆时针旋转
tmpPoint.X = - 10 ;
tmpPoint.Y = 6 ;
}
tmpGph.RotateTransform(degree);
tmpGph.DrawString(text[i].ToString(), font, brush, tmpPoint);
graphics.DrawImage(tmpBmp, i * tmpBmp.Width, 0 ); // 拼接图象
}
// 输出图象
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Gif);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ContentType = " image/gif " ;
HttpContext.Current.Response.BinaryWrite(memoryStream.ToArray());
HttpContext.Current.Response.End();
// 释放资源
font.Dispose();
brush.Dispose();
brushBg.Dispose();
tmpGph.Dispose();
tmpBmp.Dispose();
graphics.Dispose();
bmp.Dispose();
memoryStream.Dispose();
}
}
}
using System.Drawing;
using System.Web;
namespace Oran.Image
{
/// <summary>
/// 旋转的可视验证码图象
/// </summary>
public class RotatedVlidationCode
{
public enum RandomStringMode
{
/// <summary>
/// 小写字母
/// </summary>
LowerLetter,
/// <summary>
/// 大写字母
/// </summary>
UpperLetter,
/// <summary>
/// 混合大小写字母
/// </summary>
Letter,
/// <summary>
/// 数字
/// </summary>
Digital,
/// <summary>
/// 混合数字与大小字母
/// </summary>
Mix
}
public static string GenerateRandomString( int length, RandomStringMode mode)
{
string rndStr = string .Empty;
if (length == 0 )
return rndStr;
// 以数组方式候选字符,可以更方便的剔除不要的字符,如数字 0 与字母 o
char [] digitals = new char [ 10 ] { ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' };
char [] lowerLetters = new char [ 26 ] {
' 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 ' };
char [] upperLetters = new char [ 26 ] {
' 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 ' };
char [] letters = new char [ 52 ]{
' 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 ' ,
' 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 ' };
char [] mix = new char [ 62 ]{
' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' ,
' 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 ' ,
' 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 ' };
int [] range = new int [ 2 ] { 0 , 0 };
Random random = new Random();
switch (mode)
{
case RandomStringMode.Digital:
for ( int i = 0 ; i < length; ++ i)
rndStr += digitals[random.Next( 0 , digitals.Length)];
break ;
case RandomStringMode.LowerLetter:
for ( int i = 0 ; i < length; ++ i)
rndStr += lowerLetters[random.Next( 0 , lowerLetters.Length)];
break ;
case RandomStringMode.UpperLetter:
for ( int i = 0 ; i < length; ++ i)
rndStr += upperLetters[random.Next( 0 , upperLetters.Length)];
break ;
case RandomStringMode.Letter:
for ( int i = 0 ; i < length; ++ i)
rndStr += letters[random.Next( 0 , letters.Length)];
break ;
default :
for ( int i = 0 ; i < length; ++ i)
rndStr += mix[random.Next( 0 , mix.Length)];
break ;
}
return rndStr;
}
/// <summary>
/// 显示验证码
/// </summary>
/// <param name="seed"> 随机数辅助种子 </param>
/// <param name="strLen"> 验证码字符长度 </param>
/// <param name="fontSize"> 字体大小 </param>
/// <param name="mode"> 随机字符模式 </param>
/// <param name="clrFont"> 字体颜色 </param>
/// <param name="clrBg"> 背景颜色 </param>
public static void ShowValidationCode( ref int seed, int strLen, int fontSize, RandomStringMode mode, Color clrFont, Color clrBg)
{
int tmpSeed;
unchecked
{
tmpSeed = ( int )(seed * DateTime.Now.Ticks);
++ seed;
}
Random rnd = new Random(tmpSeed);
string text = GenerateRandomString(strLen, mode);
int height = fontSize * 2 ;
int width = height * text.Length;
Bitmap bmp = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(bmp);
Font font = new Font( " Courier New " , fontSize, FontStyle.Bold);
Brush brush = new SolidBrush(clrFont);
Brush brushBg = new SolidBrush(clrBg);
graphics.FillRectangle(brushBg, 0 , 0 , width, height);
Bitmap tmpBmp = new Bitmap(height, width / text.Length);
Graphics tmpGph = null ;
int degree = 40 ;
Point tmpPoint = new Point();
for ( int i = 0 ; i < text.Length; i ++ )
{
tmpBmp = new Bitmap(height, width / text.Length);
tmpGph = Graphics.FromImage(tmpBmp);
tmpGph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
tmpGph.FillRectangle(brushBg, 0 , 0 , tmpBmp.Width, tmpBmp.Height);
degree = rnd.Next( 20 , 51 ); // [20, 50]随机角度
if (rnd.Next( 0 , 2 ) == 0 )
{
tmpPoint.X = 12 ; // 调整文本坐标以适应旋转后的图象
tmpPoint.Y = - 6 ;
}
else
{
degree = ~ degree + 1 ; // 逆时针旋转
tmpPoint.X = - 10 ;
tmpPoint.Y = 6 ;
}
tmpGph.RotateTransform(degree);
tmpGph.DrawString(text[i].ToString(), font, brush, tmpPoint);
graphics.DrawImage(tmpBmp, i * tmpBmp.Width, 0 ); // 拼接图象
}
// 输出图象
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Gif);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ContentType = " image/gif " ;
HttpContext.Current.Response.BinaryWrite(memoryStream.ToArray());
HttpContext.Current.Response.End();
// 释放资源
font.Dispose();
brush.Dispose();
brushBg.Dispose();
tmpGph.Dispose();
tmpBmp.Dispose();
graphics.Dispose();
bmp.Dispose();
memoryStream.Dispose();
}
}
}