看到网络上的图形验证码之后想到以后做网站可能都会用到,所以就从网上搜了一点资料整理了一下,另外因为把验证码存到session里也是不安全的,像csdn 的图形验证码就是存到session里的 所以我用了另外一种存储方式,利用txt文件临时存储这些验证信息,但是要单独指定存放txt 和img的文件夹 图形是png格式的
源代码里的许多方法都是参考网上的源码,作者就很难考究了,但是还是谢谢他们。。。
GraphicAuthentation 类 要增加对System.Drawing 和 System.Configuration 程序集的引用
using
System;
using System.IO;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
/**/ /// <summary>
/// A class to generate authentation image and check if the string input is the same as the text in the image
/// To use this class you may set an safe folder to store the txt files containing the authentation info,and set this path in
/// webconfig appsettings key:"AuthentationTxtFolderPath" value is the physical path and when you want to save the image you should
/// give the image folder path such as Server.MapPath("~/Tem/authentationImgFolder") make sure all the folders above is for authentation
/// only because this class will delete files in the foldes you set
///
/// problems shoot:can't find the image generated :make sure the fullAuthentationImage folder is correct before call the function,because it will
/// create folder if the path dosen't exist this may cause problem
/// the image format is png so make sure to use the correct extension
///
/// many methods is written by others thanks to the author
///
/// @Author ChenGuofeng
/// @Version:1.0
/// @Email : Guofeng31@gmail.com
/// This code is open source you can use it freely but please keep the text above
/// </summary>
public class GraphicAuthentation
... {
public GraphicAuthentation()
...{
this.random = new Random();
this.fontFamilyName = "Arial";
this.textLength = 4;
this.fontSize = 16;
this.imageHeight = 25;
this.textFont = new Font(fontFamilyName, fontSize, FontStyle.Strikeout); //验证码字体
this.charCollection = "2,3,4,5,6,7,8,9,a,s,d,f,g,h,z,c,v,b,n,m,k,q,w,e,r,t,y,u,p"; //定义验证码字符及出现频次 ,避免出现0 o j i l 1 x;
this.pointNum = 8;
this.lineNum = 2;
this.backGroundBrush = new SolidBrush(GetRandomLightColor());
this.textBrush = new SolidBrush(GetRandomDeepColor());
this.interferenceBrush = new SolidBrush(GetRandomLightColor());
this.randomString = GetRandomString();
}
public GraphicAuthentation(Font textFont, int imageWidth, int imageHeight)
: this()
...{
if (null != textFont && imageWidth > 0 && imageHeight > 0)
...{
this.textFont = textFont;
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
}
else
...{
throw (new ArgumentException("Ilegal arguments"));
}
}
properties#region properties
//private System.Drawing.Image image;
private int pointNum; //躁点的数目
private int lineNum; //噪音线的数目
private string imageName;
private string txtFileName;
private string charCollection;
private string randomString;
private string fontFamilyName;
private System.Drawing.Bitmap image;
private Graphics graphics;
private int textLength;
private int fontSize;
private int imageHeight;
private int imageWidth;
private Font textFont;
private Random random;
private Brush backGroundBrush; //图片背景
private Brush textBrush; //字体
private Brush interferenceBrush;//噪音线
/**//// <summary>
/// the back ground of the image
/// </summary>
public Brush BackGroundBrush
...{
get ...{ return backGroundBrush; }
set ...{ backGroundBrush = value; }
}
/**//// <summary>
/// The brush of the text in the image
/// </summary>
public Brush TextBrush
...{
get ...{ return textBrush; }
set ...{ textBrush = value; }
}
/**//// <summary>
/// 噪音线的色刷
/// </summary>
public Brush InterferenceBrush
...{
get ...{ return interferenceBrush; }
set ...{ interferenceBrush = value; }
}
/**//// <summary>
/// The height of the picture
/// </summary>
public int ImageHeight
...{
get ...{ return imageHeight; }
set ...{ imageHeight = value; }
}
public int ImageWidth
...{
get ...{ return imageWidth; }
set ...{ imageWidth = value; }
}
/**//// <summary>
/// The font size of the text
/// </summary>
public int FontSize
...{
get ...{ return fontSize; }
set ...{ fontSize = value; }
}
/**//// <summary>
/// The total number of the authentation text
/// </summary>
public int TextLength
...{
get ...{ return textLength; }
set ...{ textLength = value; }
}
/**//// <summary>
/// The family name of the text
/// </summary>
public string FontFamilyName
...{
get ...{ return fontFamilyName; }
set ...{ fontFamilyName = value; }
}
/**//// <summary>
/// Get the name of the image generate before;
/// It will be generate after calling the method :GetImage() or the property:Image
/// </summary>
public string ImageName
...{
get
...{
return this.imageName;
}
}
public string TxtFileName
...{
get ...{ return this.txtFileName; }
}
public Bitmap Image
...{
get
...{
if (null == this.image)
this.image = GenerateImage();
return this.image;
}
}
#endregion
/**//// <summary>
/// Generate a image and save the random string to a txt file
/// </summary>
/// <returns></returns>
public System.Drawing.Bitmap GenerateImage()
...{
try
...{
//如果为定义宽度,则自动调整
if (imageWidth == 0)
...{
imageWidth = Convert.ToInt32(randomString.Length) * fontSize + fontSize; //验证区宽度,加宽一个字符,为变形预留空间
}
this.image = new System.Drawing.Bitmap(imageWidth, imageHeight); //验证区高度
//在图片框上面建立一个新的空白Graphics
this.graphics = Graphics.FromImage(image);
//填充位图背景
FillBackGround();
//画随机躁点
DrawRandomPoint();
//画随机噪音线
DrawRandomLine();
//画随机文字,并生成随机3D背景
DrawRandomString();
//随机扭曲图片
RandomTwistImage();
//存储图片和验证码信息
SaveImageInfo();
//清理过时的txt文档,img 文件在存储新的img 时进行清理
CleanObsoleteTxtFiles();
return this.image;
}
catch
...{
this.image = null;
return this.image;
}
}
/**//// <summary>
/// Save the random string to a txt file ,the "AuthentationTxtFolder" can be set in the webconfig
/// or the programe will create an folder automaticly the txt file has the same name with the image
/// </summary>
private void SaveImageInfo()
...{
string authentationTxtFolderPath = GetAuthentationTxtFolderPath();
this.imageName = DateTime.Now.Ticks.ToString(); //根据系统时间生成文件名称
this.txtFileName = GetTxtNameFromImageName(ref this.imageName);
if (string.IsNullOrEmpty(authentationTxtFolderPath)) //如果没有在webconfig中配置则在当前盘的根目录下建立AuthentationTxtFolder,此文件夹应禁止浏览者访问
...{
authentationTxtFolderPath = Path.GetFullPath("/") + "AuthentationTxtFolder/";
}
if (!Directory.Exists(authentationTxtFolderPath))
...{
Directory.CreateDirectory(authentationTxtFolderPath);
}
StreamWriter imageInfo = new StreamWriter(authentationTxtFolderPath + this.txtFileName);
imageInfo.WriteLine(this.randomString);
imageInfo.Close();
}
/**//// <summary>
/// Get the authentation image and save the authentation text to a txt file
/// </summary>
/// <param name="fullImageFolderPath">The full path of the imagefolder such as"C:/AuthentationImageFolder/" make sure the folder is only for the authentation image for not deleting other files
/// when clean obsolete files</param>
/// <returns>if succeed return true,else return false</returns>
public bool GenerateAndSaveImage(string fullImageFolderPath)
...{
bool result = false;
// string imageExtention = ".png";
if (fullImageFolderPath.LastIndexOf("/") < fullImageFolderPath.Length - 1) //判断路径是否以"/"结尾,不是则自动补加
...{
fullImageFolderPath += "/";
}
try
...{
this.image = GenerateImage();
if (null != this.image && !string.IsNullOrEmpty(this.imageName))
...{
if (!Directory.Exists(fullImageFolderPath))
...{
Directory.CreateDirectory(fullImageFolderPath);
}
this.image.Save(fullImageFolderPath + this.imageName, ImageFormat.Png);
result = true;
//清理过时的图像文件
CleanObsoleteImageFiles(fullImageFolderPath);
}
else ...{ }
}
catch
...{
}
return result;
}
/**//// <summary>
/// Check the string to a txt file, the "AuthentationTxtFolderPath" can be set in the webconfig
/// or the programe will create an folder automaticly
/// </summary>
/// <param name="imageName"></param>
/// <param name="textToCheck"></param>
/// <returns></returns>
public bool CheckTextInImage(string imageName, string textToCheck)
...{
bool result = false;
imageName = imageName.ToLower(); //不区分大小写
string authentationTxtFolderPath = GetAuthentationTxtFolderPath();
string txtName = GetTxtNameFromImageName(ref imageName);
StreamReader streamReader = new StreamReader(authentationTxtFolderPath + txtName);
if (null != streamReader)
...{
string textInTxtFile = streamReader.ReadLine().Trim();
if (textInTxtFile == textToCheck)
...{
streamReader.Close();
result = true;
}
}
return result;
}
public bool CheckTextAndDelete(string imageName, string textToCheck, string fullImageFolderPath)
...{
if (CheckTextInImage(imageName, textToCheck) && DeleteInfo(fullImageFolderPath, imageName))
return true;
else
return false;
}
public bool DeleteInfo(string fullImageFolderPath, string imageName)
...{
bool result = false;
string authentationTxtFolderPath = GetAuthentationTxtFolderPath(); //txt file has the same name with the image
string txtName = GetTxtNameFromImageName(ref imageName);
if (fullImageFolderPath.LastIndexOf("/") < fullImageFolderPath.Length - 1) //判断路径是否以"/"结尾,不是则自动补加
...{
fullImageFolderPath += "/";
}
try
...{
File.Delete(authentationTxtFolderPath + txtName); //确保扩展名正确
File.Delete(fullImageFolderPath + imageName);
result = true;
}
catch
...{ }
return result;
}
/**//// <summary>
/// Get TxtfileName from the image name and change image name when it is without extention
/// </summary>
/// <param name="imageName"></param>
/// <returns></returns>
private string GetTxtNameFromImageName(ref string imageName)
...{
string txtName = "";
if (imageName.IndexOf(".png") > 0)
txtName = imageName.Substring(0, imageName.IndexOf(".png")) + ".txt";
else
...{
if (imageName.IndexOf(".") > 0) //The extention is incorrect
...{
throw new Exception("图像的扩展名为.png");
}
txtName = imageName + ".txt";
imageName += ".png";
}
return txtName;
}
/**//// <summary>
/// Get the directory used to save the txt file if not exits, the folder will be created
/// the path can be set in the webconfig key :"AuthentationTxtFolderPath"
/// </summary>
/// <returns></returns>
private string GetAuthentationTxtFolderPath()
...{
string authentationTxtFolderPath = System.Configuration.ConfigurationManager.AppSettings["AuthentationTxtFolderPath"];
if (string.IsNullOrEmpty(authentationTxtFolderPath)) //如果没有在webconfig中配置则在当前盘的根目录下建立AuthentationTxtFolder,此文件夹应禁止浏览者访问
...{
authentationTxtFolderPath = Path.GetFullPath("/") + "AuthentationTxtFolder/";
}
if (!Directory.Exists(authentationTxtFolderPath))
...{
Directory.CreateDirectory(authentationTxtFolderPath);
}
return authentationTxtFolderPath;
}
private void FillBackGround()
...{
if (null == this.backGroundBrush)
...{
this.backGroundBrush = new SolidBrush(GetRandomLightColor());
}
this.graphics.FillRectangle(backGroundBrush, 0, 0, image.Width, image.Height);
}
/**//// <summary>
///将全局变换平移(x, y),也就是使画布上将要画的所有内容向左边移动x,向下移动y (not used)
/// </summary>
/// <param name="graphics"></param>
private void TransformGraphics(Graphics graphics)
...{
float left = -15;
float top = -2;
graphics.TranslateTransform(left, top);
//做切变,将原始矩形的下边缘水平移动矩形高度的0.2倍
Matrix textTransform = graphics.Transform;
textTransform.Shear(0.2f, 0);
graphics.Transform = textTransform;
}
/**//// <summary>
/// Get a random string from the collection of chars
/// </summary>
/// <returns></returns>
private string GetRandomString()
...{
string[] randomArray = charCollection.Split(','); //将字符串生成数组
int arrayLength = randomArray.Length;
string randomString = "";
for (int i = 0; i < this.textLength; i++)
...{
randomString += randomArray[random.Next(0, arrayLength)];
}
return randomString; //长度是textLength +1
}
/**//// <summary>
/// 正弦曲线Wave扭曲图片。函数可以迭加使用,以获得不同方式不同程度的效果
/// </summary>
/// <param name="srcBmp">Bitmap to modify</param>
/// <param name="bXDir">扭曲方式,true 垂直,false 水平 </param>
/// <param name="dMultValue">波形的幅度倍数</param>
/// <param name="dPhase">波形的起始相位</param>
/// <returns></returns>
public Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
...{
int leftMargin = 0;
int rightMargin = 0;
int topMargin = 0;
int bottomMargin = 0;
//float PI = 3.14159265358979f;
float PI2 = 6.28318530717959f;
Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
double dBaseAxisLen = bXDir ? Convert.ToDouble(destBmp.Height) : Convert.ToDouble(destBmp.Width);
for (int i = 0; i < destBmp.Width; i++)
...{
for (int j = 0; j < destBmp.Height; j++)
...{
double dx = 0;
dx = bXDir ? PI2 * Convert.ToDouble(j) / dBaseAxisLen : PI2 * Convert.ToDouble(i) / dBaseAxisLen;
dx += dPhase;
double dy = Math.Sin(dx);
//取得当前点的颜色
int nOldX = 0;
int nOldY = 0;
nOldX = bXDir ? i + Convert.ToInt32(dy * dMultValue) : i;
nOldY = bXDir ? j : j + Convert.ToInt32(dy * dMultValue);
System.Drawing.Color color = srcBmp.GetPixel(i, j);
if (nOldX >= leftMargin && nOldX < destBmp.Width - rightMargin && nOldY >= bottomMargin && nOldY < destBmp.Height - topMargin)
...{
destBmp.SetPixel(nOldX, nOldY, color);
}
}
}
return destBmp;
}
/**//// <summary>
/// 生成随机浅颜色
/// </summary>
/// <returns>randomColor</returns>
public Color GetRandomLightColor()
...{
int nRed, nGreen, nBlue; //越大颜色越浅
int low = 180; //色彩的下限
int high = 255; //色彩的上限
nRed = this.random.Next(high) % (high - low) + low;
nGreen = this.random.Next(high) % (high - low) + low;
nBlue = this.random.Next(high) % (high - low) + low;
Color color = Color.FromArgb(nRed, nGreen, nBlue);
return color;
}
/**//// <summary>
/// 生成随机深颜色
/// </summary>
/// <returns></returns>
public Color GetRandomDeepColor()
...{
int nRed, nGreen, nBlue; // nBlue,nRed nGreen 相差大一点 nGreen 小一些
//int high = 255;
int redLow = 120;
int greenLow = 0;
int blueLow = 120;
nRed = this.random.Next(redLow);
nGreen = this.random.Next(greenLow);
nBlue = this.random.Next(blueLow);
Color color = Color.FromArgb(nRed, nGreen, nBlue);
return color;
}
/**//// <summary>
/// 随机输出躁点
/// </summary>
/// <param name="penWidth">The width of the point</param>
/// <returns></returns>
private void DrawRandomPoint()
...{
float x, y;
for (int i = 0; i < this.pointNum; i++)
...{
x = imageWidth * (float)this.random.NextDouble();
y = imageHeight * (float)this.random.NextDouble();
float pointWidth = 2 * (float)this.random.NextDouble(); //随机干扰点大小
graphics.DrawRectangle(new Pen(GetRandomLightColor(), pointWidth), x, y, 1, 1);//draw a rectangle on the graphic
}
}
private void DrawRandomLine()
...{
float x1, x2, y1, y2;
for (; this.lineNum > 0; this.lineNum--)
...{
x1 = image.Width * (float)this.random.NextDouble();
y1 = image.Height * (float)this.random.NextDouble();
x2 = image.Width * (float)this.random.NextDouble();
y2 = image.Height * (float)this.random.NextDouble();
float penWidth = 2 * (float)this.random.NextDouble(); //随机干扰线粗细
this.graphics.DrawLine(new Pen(GetRandomLightColor(), penWidth), x1, y1, x2, y2);
}
}
/**//// <summary>
/// 写入字符串,并随机生成3D背景
/// </summary>
private void DrawRandomString()
...{
//文字的位置
float x = 10 * (float)this.random.NextDouble() + 4; //随机产生X轴位置,增加程序识别难度
float y = 0;
double draw3DProbability = 0.9; //生成3D背景的概率
int distance = Convert.ToInt32(random.NextDouble() * 2);//3D背景偏移的距离
this.graphics.DrawString(this.randomString, this.textFont, this.textBrush, x, y);
if (!(random.NextDouble() > draw3DProbability)) //生成3D背景
...{
this.graphics.DrawString(this.randomString, this.textFont, this.interferenceBrush, x - distance, y + distance);
}
}
private void RandomTwistImage()
...{
//扭曲验证字符。TwistImage参数可自行修改
int twist1, twist2;
double twistProbability = 0.1;//产生扭曲的概率
int twistLeval = 2;
if (this.random.NextDouble() > twistProbability)
...{
twist1 = 0;
twist2 = 0;
}
else
...{
twist1 = Convert.ToInt32(this.random.NextDouble() * twistLeval); //扭曲参数随机生成
twist2 = Convert.ToInt32(this.random.NextDouble() * twistLeval - 1); //扭曲参数随机生成
}
//image = TwistImage(image, true, -twist1, -twist2);
image = TwistImage(image, false, -twist1, -twist2); //多扭曲几次也没关系,只是消耗服务器资源多些
}
/**//// <summary>
/// 如果没有显式的删除文件,临时的验证文件会越来越多,此方法用来清除过时的文件,当文件的创建时间小于服务器时间两小时以上时则被删除
///
/// </summary>
public void CleanObsoleteImageFiles(string fullImageFolderPath)
...{
string[] fileCollections = Directory.GetFiles(fullImageFolderPath);
int filesNum = fileCollections.Length;
for (int i = 0; i < filesNum; i++)
...{
ApplyDeletFile(fileCollections[i]);
}
}
/**//// <summary>
/// 如果不存储Image 则单独进行txt文件的清理
/// </summary>
private void CleanObsoleteTxtFiles()
...{
string[] fileCollections = Directory.GetFiles(GetAuthentationTxtFolderPath());
int filesNum = fileCollections.Length;
for (int i = 0; i < filesNum; i++)
...{
ApplyDeletFile(fileCollections[i]);
}
}
private void ApplyDeletFile(string fullFileName)
...{
double timeSpan = 2;
try
...{
DateTime createTime = File.GetCreationTime(fullFileName);
if (createTime.AddHours(timeSpan) < DateTime.Now)
File.Delete(fullFileName);
}
catch ...{ }
}
}
using System.IO;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
/**/ /// <summary>
/// A class to generate authentation image and check if the string input is the same as the text in the image
/// To use this class you may set an safe folder to store the txt files containing the authentation info,and set this path in
/// webconfig appsettings key:"AuthentationTxtFolderPath" value is the physical path and when you want to save the image you should
/// give the image folder path such as Server.MapPath("~/Tem/authentationImgFolder") make sure all the folders above is for authentation
/// only because this class will delete files in the foldes you set
///
/// problems shoot:can't find the image generated :make sure the fullAuthentationImage folder is correct before call the function,because it will
/// create folder if the path dosen't exist this may cause problem
/// the image format is png so make sure to use the correct extension
///
/// many methods is written by others thanks to the author
///
/// @Author ChenGuofeng
/// @Version:1.0
/// @Email : Guofeng31@gmail.com
/// This code is open source you can use it freely but please keep the text above
/// </summary>
public class GraphicAuthentation
... {
public GraphicAuthentation()
...{
this.random = new Random();
this.fontFamilyName = "Arial";
this.textLength = 4;
this.fontSize = 16;
this.imageHeight = 25;
this.textFont = new Font(fontFamilyName, fontSize, FontStyle.Strikeout); //验证码字体
this.charCollection = "2,3,4,5,6,7,8,9,a,s,d,f,g,h,z,c,v,b,n,m,k,q,w,e,r,t,y,u,p"; //定义验证码字符及出现频次 ,避免出现0 o j i l 1 x;
this.pointNum = 8;
this.lineNum = 2;
this.backGroundBrush = new SolidBrush(GetRandomLightColor());
this.textBrush = new SolidBrush(GetRandomDeepColor());
this.interferenceBrush = new SolidBrush(GetRandomLightColor());
this.randomString = GetRandomString();
}
public GraphicAuthentation(Font textFont, int imageWidth, int imageHeight)
: this()
...{
if (null != textFont && imageWidth > 0 && imageHeight > 0)
...{
this.textFont = textFont;
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
}
else
...{
throw (new ArgumentException("Ilegal arguments"));
}
}
properties#region properties
//private System.Drawing.Image image;
private int pointNum; //躁点的数目
private int lineNum; //噪音线的数目
private string imageName;
private string txtFileName;
private string charCollection;
private string randomString;
private string fontFamilyName;
private System.Drawing.Bitmap image;
private Graphics graphics;
private int textLength;
private int fontSize;
private int imageHeight;
private int imageWidth;
private Font textFont;
private Random random;
private Brush backGroundBrush; //图片背景
private Brush textBrush; //字体
private Brush interferenceBrush;//噪音线
/**//// <summary>
/// the back ground of the image
/// </summary>
public Brush BackGroundBrush
...{
get ...{ return backGroundBrush; }
set ...{ backGroundBrush = value; }
}
/**//// <summary>
/// The brush of the text in the image
/// </summary>
public Brush TextBrush
...{
get ...{ return textBrush; }
set ...{ textBrush = value; }
}
/**//// <summary>
/// 噪音线的色刷
/// </summary>
public Brush InterferenceBrush
...{
get ...{ return interferenceBrush; }
set ...{ interferenceBrush = value; }
}
/**//// <summary>
/// The height of the picture
/// </summary>
public int ImageHeight
...{
get ...{ return imageHeight; }
set ...{ imageHeight = value; }
}
public int ImageWidth
...{
get ...{ return imageWidth; }
set ...{ imageWidth = value; }
}
/**//// <summary>
/// The font size of the text
/// </summary>
public int FontSize
...{
get ...{ return fontSize; }
set ...{ fontSize = value; }
}
/**//// <summary>
/// The total number of the authentation text
/// </summary>
public int TextLength
...{
get ...{ return textLength; }
set ...{ textLength = value; }
}
/**//// <summary>
/// The family name of the text
/// </summary>
public string FontFamilyName
...{
get ...{ return fontFamilyName; }
set ...{ fontFamilyName = value; }
}
/**//// <summary>
/// Get the name of the image generate before;
/// It will be generate after calling the method :GetImage() or the property:Image
/// </summary>
public string ImageName
...{
get
...{
return this.imageName;
}
}
public string TxtFileName
...{
get ...{ return this.txtFileName; }
}
public Bitmap Image
...{
get
...{
if (null == this.image)
this.image = GenerateImage();
return this.image;
}
}
#endregion
/**//// <summary>
/// Generate a image and save the random string to a txt file
/// </summary>
/// <returns></returns>
public System.Drawing.Bitmap GenerateImage()
...{
try
...{
//如果为定义宽度,则自动调整
if (imageWidth == 0)
...{
imageWidth = Convert.ToInt32(randomString.Length) * fontSize + fontSize; //验证区宽度,加宽一个字符,为变形预留空间
}
this.image = new System.Drawing.Bitmap(imageWidth, imageHeight); //验证区高度
//在图片框上面建立一个新的空白Graphics
this.graphics = Graphics.FromImage(image);
//填充位图背景
FillBackGround();
//画随机躁点
DrawRandomPoint();
//画随机噪音线
DrawRandomLine();
//画随机文字,并生成随机3D背景
DrawRandomString();
//随机扭曲图片
RandomTwistImage();
//存储图片和验证码信息
SaveImageInfo();
//清理过时的txt文档,img 文件在存储新的img 时进行清理
CleanObsoleteTxtFiles();
return this.image;
}
catch
...{
this.image = null;
return this.image;
}
}
/**//// <summary>
/// Save the random string to a txt file ,the "AuthentationTxtFolder" can be set in the webconfig
/// or the programe will create an folder automaticly the txt file has the same name with the image
/// </summary>
private void SaveImageInfo()
...{
string authentationTxtFolderPath = GetAuthentationTxtFolderPath();
this.imageName = DateTime.Now.Ticks.ToString(); //根据系统时间生成文件名称
this.txtFileName = GetTxtNameFromImageName(ref this.imageName);
if (string.IsNullOrEmpty(authentationTxtFolderPath)) //如果没有在webconfig中配置则在当前盘的根目录下建立AuthentationTxtFolder,此文件夹应禁止浏览者访问
...{
authentationTxtFolderPath = Path.GetFullPath("/") + "AuthentationTxtFolder/";
}
if (!Directory.Exists(authentationTxtFolderPath))
...{
Directory.CreateDirectory(authentationTxtFolderPath);
}
StreamWriter imageInfo = new StreamWriter(authentationTxtFolderPath + this.txtFileName);
imageInfo.WriteLine(this.randomString);
imageInfo.Close();
}
/**//// <summary>
/// Get the authentation image and save the authentation text to a txt file
/// </summary>
/// <param name="fullImageFolderPath">The full path of the imagefolder such as"C:/AuthentationImageFolder/" make sure the folder is only for the authentation image for not deleting other files
/// when clean obsolete files</param>
/// <returns>if succeed return true,else return false</returns>
public bool GenerateAndSaveImage(string fullImageFolderPath)
...{
bool result = false;
// string imageExtention = ".png";
if (fullImageFolderPath.LastIndexOf("/") < fullImageFolderPath.Length - 1) //判断路径是否以"/"结尾,不是则自动补加
...{
fullImageFolderPath += "/";
}
try
...{
this.image = GenerateImage();
if (null != this.image && !string.IsNullOrEmpty(this.imageName))
...{
if (!Directory.Exists(fullImageFolderPath))
...{
Directory.CreateDirectory(fullImageFolderPath);
}
this.image.Save(fullImageFolderPath + this.imageName, ImageFormat.Png);
result = true;
//清理过时的图像文件
CleanObsoleteImageFiles(fullImageFolderPath);
}
else ...{ }
}
catch
...{
}
return result;
}
/**//// <summary>
/// Check the string to a txt file, the "AuthentationTxtFolderPath" can be set in the webconfig
/// or the programe will create an folder automaticly
/// </summary>
/// <param name="imageName"></param>
/// <param name="textToCheck"></param>
/// <returns></returns>
public bool CheckTextInImage(string imageName, string textToCheck)
...{
bool result = false;
imageName = imageName.ToLower(); //不区分大小写
string authentationTxtFolderPath = GetAuthentationTxtFolderPath();
string txtName = GetTxtNameFromImageName(ref imageName);
StreamReader streamReader = new StreamReader(authentationTxtFolderPath + txtName);
if (null != streamReader)
...{
string textInTxtFile = streamReader.ReadLine().Trim();
if (textInTxtFile == textToCheck)
...{
streamReader.Close();
result = true;
}
}
return result;
}
public bool CheckTextAndDelete(string imageName, string textToCheck, string fullImageFolderPath)
...{
if (CheckTextInImage(imageName, textToCheck) && DeleteInfo(fullImageFolderPath, imageName))
return true;
else
return false;
}
public bool DeleteInfo(string fullImageFolderPath, string imageName)
...{
bool result = false;
string authentationTxtFolderPath = GetAuthentationTxtFolderPath(); //txt file has the same name with the image
string txtName = GetTxtNameFromImageName(ref imageName);
if (fullImageFolderPath.LastIndexOf("/") < fullImageFolderPath.Length - 1) //判断路径是否以"/"结尾,不是则自动补加
...{
fullImageFolderPath += "/";
}
try
...{
File.Delete(authentationTxtFolderPath + txtName); //确保扩展名正确
File.Delete(fullImageFolderPath + imageName);
result = true;
}
catch
...{ }
return result;
}
/**//// <summary>
/// Get TxtfileName from the image name and change image name when it is without extention
/// </summary>
/// <param name="imageName"></param>
/// <returns></returns>
private string GetTxtNameFromImageName(ref string imageName)
...{
string txtName = "";
if (imageName.IndexOf(".png") > 0)
txtName = imageName.Substring(0, imageName.IndexOf(".png")) + ".txt";
else
...{
if (imageName.IndexOf(".") > 0) //The extention is incorrect
...{
throw new Exception("图像的扩展名为.png");
}
txtName = imageName + ".txt";
imageName += ".png";
}
return txtName;
}
/**//// <summary>
/// Get the directory used to save the txt file if not exits, the folder will be created
/// the path can be set in the webconfig key :"AuthentationTxtFolderPath"
/// </summary>
/// <returns></returns>
private string GetAuthentationTxtFolderPath()
...{
string authentationTxtFolderPath = System.Configuration.ConfigurationManager.AppSettings["AuthentationTxtFolderPath"];
if (string.IsNullOrEmpty(authentationTxtFolderPath)) //如果没有在webconfig中配置则在当前盘的根目录下建立AuthentationTxtFolder,此文件夹应禁止浏览者访问
...{
authentationTxtFolderPath = Path.GetFullPath("/") + "AuthentationTxtFolder/";
}
if (!Directory.Exists(authentationTxtFolderPath))
...{
Directory.CreateDirectory(authentationTxtFolderPath);
}
return authentationTxtFolderPath;
}
private void FillBackGround()
...{
if (null == this.backGroundBrush)
...{
this.backGroundBrush = new SolidBrush(GetRandomLightColor());
}
this.graphics.FillRectangle(backGroundBrush, 0, 0, image.Width, image.Height);
}
/**//// <summary>
///将全局变换平移(x, y),也就是使画布上将要画的所有内容向左边移动x,向下移动y (not used)
/// </summary>
/// <param name="graphics"></param>
private void TransformGraphics(Graphics graphics)
...{
float left = -15;
float top = -2;
graphics.TranslateTransform(left, top);
//做切变,将原始矩形的下边缘水平移动矩形高度的0.2倍
Matrix textTransform = graphics.Transform;
textTransform.Shear(0.2f, 0);
graphics.Transform = textTransform;
}
/**//// <summary>
/// Get a random string from the collection of chars
/// </summary>
/// <returns></returns>
private string GetRandomString()
...{
string[] randomArray = charCollection.Split(','); //将字符串生成数组
int arrayLength = randomArray.Length;
string randomString = "";
for (int i = 0; i < this.textLength; i++)
...{
randomString += randomArray[random.Next(0, arrayLength)];
}
return randomString; //长度是textLength +1
}
/**//// <summary>
/// 正弦曲线Wave扭曲图片。函数可以迭加使用,以获得不同方式不同程度的效果
/// </summary>
/// <param name="srcBmp">Bitmap to modify</param>
/// <param name="bXDir">扭曲方式,true 垂直,false 水平 </param>
/// <param name="dMultValue">波形的幅度倍数</param>
/// <param name="dPhase">波形的起始相位</param>
/// <returns></returns>
public Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
...{
int leftMargin = 0;
int rightMargin = 0;
int topMargin = 0;
int bottomMargin = 0;
//float PI = 3.14159265358979f;
float PI2 = 6.28318530717959f;
Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
double dBaseAxisLen = bXDir ? Convert.ToDouble(destBmp.Height) : Convert.ToDouble(destBmp.Width);
for (int i = 0; i < destBmp.Width; i++)
...{
for (int j = 0; j < destBmp.Height; j++)
...{
double dx = 0;
dx = bXDir ? PI2 * Convert.ToDouble(j) / dBaseAxisLen : PI2 * Convert.ToDouble(i) / dBaseAxisLen;
dx += dPhase;
double dy = Math.Sin(dx);
//取得当前点的颜色
int nOldX = 0;
int nOldY = 0;
nOldX = bXDir ? i + Convert.ToInt32(dy * dMultValue) : i;
nOldY = bXDir ? j : j + Convert.ToInt32(dy * dMultValue);
System.Drawing.Color color = srcBmp.GetPixel(i, j);
if (nOldX >= leftMargin && nOldX < destBmp.Width - rightMargin && nOldY >= bottomMargin && nOldY < destBmp.Height - topMargin)
...{
destBmp.SetPixel(nOldX, nOldY, color);
}
}
}
return destBmp;
}
/**//// <summary>
/// 生成随机浅颜色
/// </summary>
/// <returns>randomColor</returns>
public Color GetRandomLightColor()
...{
int nRed, nGreen, nBlue; //越大颜色越浅
int low = 180; //色彩的下限
int high = 255; //色彩的上限
nRed = this.random.Next(high) % (high - low) + low;
nGreen = this.random.Next(high) % (high - low) + low;
nBlue = this.random.Next(high) % (high - low) + low;
Color color = Color.FromArgb(nRed, nGreen, nBlue);
return color;
}
/**//// <summary>
/// 生成随机深颜色
/// </summary>
/// <returns></returns>
public Color GetRandomDeepColor()
...{
int nRed, nGreen, nBlue; // nBlue,nRed nGreen 相差大一点 nGreen 小一些
//int high = 255;
int redLow = 120;
int greenLow = 0;
int blueLow = 120;
nRed = this.random.Next(redLow);
nGreen = this.random.Next(greenLow);
nBlue = this.random.Next(blueLow);
Color color = Color.FromArgb(nRed, nGreen, nBlue);
return color;
}
/**//// <summary>
/// 随机输出躁点
/// </summary>
/// <param name="penWidth">The width of the point</param>
/// <returns></returns>
private void DrawRandomPoint()
...{
float x, y;
for (int i = 0; i < this.pointNum; i++)
...{
x = imageWidth * (float)this.random.NextDouble();
y = imageHeight * (float)this.random.NextDouble();
float pointWidth = 2 * (float)this.random.NextDouble(); //随机干扰点大小
graphics.DrawRectangle(new Pen(GetRandomLightColor(), pointWidth), x, y, 1, 1);//draw a rectangle on the graphic
}
}
private void DrawRandomLine()
...{
float x1, x2, y1, y2;
for (; this.lineNum > 0; this.lineNum--)
...{
x1 = image.Width * (float)this.random.NextDouble();
y1 = image.Height * (float)this.random.NextDouble();
x2 = image.Width * (float)this.random.NextDouble();
y2 = image.Height * (float)this.random.NextDouble();
float penWidth = 2 * (float)this.random.NextDouble(); //随机干扰线粗细
this.graphics.DrawLine(new Pen(GetRandomLightColor(), penWidth), x1, y1, x2, y2);
}
}
/**//// <summary>
/// 写入字符串,并随机生成3D背景
/// </summary>
private void DrawRandomString()
...{
//文字的位置
float x = 10 * (float)this.random.NextDouble() + 4; //随机产生X轴位置,增加程序识别难度
float y = 0;
double draw3DProbability = 0.9; //生成3D背景的概率
int distance = Convert.ToInt32(random.NextDouble() * 2);//3D背景偏移的距离
this.graphics.DrawString(this.randomString, this.textFont, this.textBrush, x, y);
if (!(random.NextDouble() > draw3DProbability)) //生成3D背景
...{
this.graphics.DrawString(this.randomString, this.textFont, this.interferenceBrush, x - distance, y + distance);
}
}
private void RandomTwistImage()
...{
//扭曲验证字符。TwistImage参数可自行修改
int twist1, twist2;
double twistProbability = 0.1;//产生扭曲的概率
int twistLeval = 2;
if (this.random.NextDouble() > twistProbability)
...{
twist1 = 0;
twist2 = 0;
}
else
...{
twist1 = Convert.ToInt32(this.random.NextDouble() * twistLeval); //扭曲参数随机生成
twist2 = Convert.ToInt32(this.random.NextDouble() * twistLeval - 1); //扭曲参数随机生成
}
//image = TwistImage(image, true, -twist1, -twist2);
image = TwistImage(image, false, -twist1, -twist2); //多扭曲几次也没关系,只是消耗服务器资源多些
}
/**//// <summary>
/// 如果没有显式的删除文件,临时的验证文件会越来越多,此方法用来清除过时的文件,当文件的创建时间小于服务器时间两小时以上时则被删除
///
/// </summary>
public void CleanObsoleteImageFiles(string fullImageFolderPath)
...{
string[] fileCollections = Directory.GetFiles(fullImageFolderPath);
int filesNum = fileCollections.Length;
for (int i = 0; i < filesNum; i++)
...{
ApplyDeletFile(fileCollections[i]);
}
}
/**//// <summary>
/// 如果不存储Image 则单独进行txt文件的清理
/// </summary>
private void CleanObsoleteTxtFiles()
...{
string[] fileCollections = Directory.GetFiles(GetAuthentationTxtFolderPath());
int filesNum = fileCollections.Length;
for (int i = 0; i < filesNum; i++)
...{
ApplyDeletFile(fileCollections[i]);
}
}
private void ApplyDeletFile(string fullFileName)
...{
double timeSpan = 2;
try
...{
DateTime createTime = File.GetCreationTime(fullFileName);
if (createTime.AddHours(timeSpan) < DateTime.Now)
File.Delete(fullFileName);
}
catch ...{ }
}
}
default.aspx
<%
...
@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default"
%>
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="Form1" method ="post" runat ="server" >
< div >
< asp:TextBox ID ="TextBox1" runat ="server" ></ asp:TextBox >
< asp:ImageButton ID ="Image1" runat ="server" ImageUrl ="GetAuthentationImage.aspx" />< br >
< img runat ="server" id ="img2" src ="GetAuthentationImage.aspx" onclick = "javascript:this.src ='GetAuthentationImage.aspx'" />
< br >
< asp:Button ID ="Button1" runat ="server" Text ="提交" OnClick ="Button1_Click" />
</ div >
</ form >
</ body >
</ html >
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > Untitled Page </ title >
</ head >
< body >
< form id ="Form1" method ="post" runat ="server" >
< div >
< asp:TextBox ID ="TextBox1" runat ="server" ></ asp:TextBox >
< asp:ImageButton ID ="Image1" runat ="server" ImageUrl ="GetAuthentationImage.aspx" />< br >
< img runat ="server" id ="img2" src ="GetAuthentationImage.aspx" onclick = "javascript:this.src ='GetAuthentationImage.aspx'" />
< br >
< asp:Button ID ="Button1" runat ="server" Text ="提交" OnClick ="Button1_Click" />
</ div >
</ form >
</ body >
</ html >
default.aspx.cs
using
System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
... {
private void Page_Load(object sender, System.EventArgs e)
...{
}
private void Image1_Click(object sender, System.Web.UI.ImageClickEventArgs e)
...{
Image1.ImageUrl = "GetAuthentationImage.aspx";
}
protected void Button1_Click(object sender, EventArgs e)
...{
GraphicAuthentation g = new GraphicAuthentation();
if (g.CheckTextInImage(Session["imageName"].ToString(), Request.Form["textBox1"]))
...{
Response.Write("Success");
}
else
...{
Response.Write("fail");
}
}
}
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
... {
private void Page_Load(object sender, System.EventArgs e)
...{
}
private void Image1_Click(object sender, System.Web.UI.ImageClickEventArgs e)
...{
Image1.ImageUrl = "GetAuthentationImage.aspx";
}
protected void Button1_Click(object sender, EventArgs e)
...{
GraphicAuthentation g = new GraphicAuthentation();
if (g.CheckTextInImage(Session["imageName"].ToString(), Request.Form["textBox1"]))
...{
Response.Write("Success");
}
else
...{
Response.Write("fail");
}
}
}
GetAuthentationImage.aspx.cs
using
System;
using System.IO;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
public partial class GetAuthentationImage : System.Web.UI.Page
... {
private void Page_Load(object sender, System.EventArgs e)
...{
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache); //不缓存
GraphicAuthentation graphicAuthentation = new GraphicAuthentation();
Bitmap image = new Bitmap(70, 25);
string imageName = "";
string path = Server.MapPath("~/Tem/AuthentationImageFolder");
if (graphicAuthentation.GenerateAndSaveImage(path))
...{
imageName = graphicAuthentation.ImageName;
image = graphicAuthentation.Image;
}
Session["imageName"] = imageName;
//string name = graphicAuthentation.GetAuthentationImageUrl();
MemoryStream ms = new MemoryStream();
image.Save(ms, ImageFormat.Png);
Response.ClearContent(); //需要输出图象信息 要修改HTTP头
Response.ContentType = "image/Png";
Response.BinaryWrite(ms.ToArray());
image.Dispose();
Response.End();
}
}
using System.IO;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
public partial class GetAuthentationImage : System.Web.UI.Page
... {
private void Page_Load(object sender, System.EventArgs e)
...{
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache); //不缓存
GraphicAuthentation graphicAuthentation = new GraphicAuthentation();
Bitmap image = new Bitmap(70, 25);
string imageName = "";
string path = Server.MapPath("~/Tem/AuthentationImageFolder");
if (graphicAuthentation.GenerateAndSaveImage(path))
...{
imageName = graphicAuthentation.ImageName;
image = graphicAuthentation.Image;
}
Session["imageName"] = imageName;
//string name = graphicAuthentation.GetAuthentationImageUrl();
MemoryStream ms = new MemoryStream();
image.Save(ms, ImageFormat.Png);
Response.ClearContent(); //需要输出图象信息 要修改HTTP头
Response.ContentType = "image/Png";
Response.BinaryWrite(ms.ToArray());
image.Dispose();
Response.End();
}
}
目录结构
效果
终于贴完了 呵呵 ~~