驗證碼方式
1、隨機字母或者數字,純文本驗證碼
這種非常容易破解 ,市場上有大量的現成接口或者工具,背景越復雜難度越高。
2、題庫驗證碼
要破解這種驗證碼,需要人工收集題庫才可以破解,可以免疫不是專門針對你一個網站的黑客,所以我偏愛這種驗證碼
•1+1=? •本論壇的域名是? •今天是星期幾? •復雜點的數學運算
但是他到底是不是就不能破解了呢?
缺點:數量有限。破解方式也很簡單,多刷新幾次,建立題庫和對應的答案,用正則從網頁里抓取問題,尋找匹配的答案后破解。也有些用隨機生成的數學公式,比如 隨機數 [+-*/]隨機運算符 隨機數=?,小學生水平的程序員也可以搞定……
題庫越多高全系數越高
3、干擾型題庫驗證碼
將文字顯示進行處理起到干擾效果,就算你有正確題庫也不能輕易破解
今天正好身體不舒服請了天假整理了這么一個可以實現上面三種驗證碼的類
效果圖
實現步驟
1、MVC Action 或者 WebForm的 pageLoad寫以下代碼
public void ValidateImg()
{
VerifyCodeSugar v = new VerifyCodeSugar();
//是否隨機字體顏色
v.SetIsRandomColor = true;
//隨機碼的旋轉角度
v.SetRandomAngle = 4;
//文字大小
v.SetFontSize = 15;
//背景色
//v.SetBackgroundColor
//前景噪點數量
//v.SetForeNoisePointCount = 3;
//v.SetFontColor =Color.Red;
//...還有更多設置不介紹了
var questionList = new Dictionary<string, string>()
{
{"1+1=?","2"},
{"喜羊羊主角叫什么名字?","喜羊羊" },
{"【我愛你】中間的那個字?","愛" },
};
var questionItem = v.GetQuestion();//不賦值為隨機驗證碼 例如: 1*2=? 這種
//指定驗證文本
//v.SetVerifyCodeText
v.SetVerifyCodeText = questionItem.Key;
Session["VerifyCode"] = questionItem.Value;
//輸出圖片
v.OutputImage(System.Web.HttpContext.Current.Response);
}
2、前台設用action或者pageload頁面地址,js給src更換url添加隨機參數 達到刷新驗證碼的功能
<img src="/File/ValidateImg" />
3、完整封裝類
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
namespace Idea.Models
{
/// <summary>
/// 驗證碼類
/// </summary>
public class VerifyCodeSugar
{
private Random objRandom = new Random();
#region setting
/// <summary>
/// //驗證碼長度
/// </summary>
public int SetLength = 4;
/// <summary>
/// 驗證碼字符串
/// </summary>
public string SetVerifyCodeText { get; set; }
/// <summary>
/// 是否加入小寫字母
/// </summary>
public bool SetAddLowerLetter = false;
/// <summary>
/// 是否加入大寫字母
/// </summary>
public bool SetAddUpperLetter = false;
/// <summary>
/// 字體大小
/// </summary>
public int SetFontSize = 18;
/// <summary>
/// //字體顏色
/// </summary>
public Color SetFontColor = Color.Blue;
/// <summary>
/// 字體類型
/// </summary>
public string SetFontFamily = "Verdana";
/// <summary>
/// 背景色
/// </summary>
public Color SetBackgroundColor = Color.AliceBlue;
/// <summary>
/// 前景噪點數量
/// </summary>
public int SetForeNoisePointCount = 2;
/// <summary>
/// 隨機碼的旋轉角度
/// </summary>
public int SetRandomAngle = 40;
/// <summary>
/// 是否隨機字體顏色
/// </summary>
public bool SetIsRandomColor = false;
/// <summary>
/// 圖片寬度
/// </summary>
private int SetWith
{
get
{
return this.SetVerifyCodeText.Length * SetFontSize;
}
}
/// <summary>
/// 圖片高度
/// </summary>
private int SetHeight
{
get
{
return Convert.ToInt32((60.0 / 100) * SetFontSize + SetFontSize);
}
}
#endregion
#region Constructor Method
public VerifyCodeSugar()
{
this.GetVerifyCodeText();
}
#endregion
#region Private Method
/// <summary>
/// 得到驗證碼字符串
/// </summary>
private void GetVerifyCodeText()
{
//沒有外部輸入驗證碼時隨機生成
if (String.IsNullOrEmpty(this.SetVerifyCodeText))
{
StringBuilder objStringBuilder = new StringBuilder();
//加入數字1-9
for (int i = 1; i <= 9; i++)
{
objStringBuilder.Append(i.ToString());
}
//加入大寫字母A-Z,不包括O
if (this.SetAddUpperLetter)
{
char temp = ' ';
for (int i = 0; i < 26; i++)
{
temp = Convert.ToChar(i + 65);
//如果生成的字母不是'O'
if (!temp.Equals('O'))
{
objStringBuilder.Append(temp);
}
}
}
//加入小寫字母a-z,不包括o
if (this.SetAddLowerLetter)
{
char temp = ' ';
for (int i = 0; i < 26; i++)
{
temp = Convert.ToChar(i + 97);
//如果生成的字母不是'o'
if (!temp.Equals('o'))
{
objStringBuilder.Append(temp);
}
}
}
//生成驗證碼字符串
{
int index = 0;
for (int i = 0; i < SetLength; i++)
{
index = objRandom.Next(0, objStringBuilder.Length);
this.SetVerifyCodeText += objStringBuilder[index];
objStringBuilder.Remove(index, 1);
}
}
}
}
/// <summary>
/// 得到驗證碼圖片
/// </summary>
private Bitmap GetVerifyCodeImage()
{
Bitmap result = null;
//創建繪圖
result = new Bitmap(SetWith, SetHeight);
using (Graphics objGraphics = Graphics.FromImage(result))
{
objGraphics.SmoothingMode = SmoothingMode.HighQuality;
//清除整個繪圖面並以指定背景色填充
objGraphics.Clear(this.SetBackgroundColor);
//創建畫筆
using (SolidBrush objSolidBrush = new SolidBrush(this.SetFontColor))
{
this.AddForeNoisePoint(result);
this.AddBackgroundNoisePoint(result, objGraphics);
//文字居中
StringFormat objStringFormat = new StringFormat(StringFormatFlags.NoClip);
objStringFormat.Alignment = StringAlignment.Center;
objStringFormat.LineAlignment = StringAlignment.Center;
//字體樣式
Font objFont = new Font(this.SetFontFamily, objRandom.Next(this.SetFontSize - 3, this.SetFontSize), FontStyle.Regular);
//驗證碼旋轉,防止機器識別
char[] chars = this.SetVerifyCodeText.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
//轉動的度數
float angle = objRandom.Next(-this.SetRandomAngle, this.SetRandomAngle);
objGraphics.TranslateTransform(12, 12);
objGraphics.RotateTransform(angle);
objGraphics.DrawString(chars[i].ToString(), objFont, objSolidBrush, -2, 2, objStringFormat);
objGraphics.RotateTransform(-angle);
objGraphics.TranslateTransform(2, -12);
}
}
}
return result;
}
/// <summary>
/// 添加前景噪點
/// </summary>
/// <param name="objBitmap"></param>
private void AddForeNoisePoint(Bitmap objBitmap)
{
for (int i = 0; i < objBitmap.Width * this.SetForeNoisePointCount; i++)
{
objBitmap.SetPixel(objRandom.Next(objBitmap.Width), objRandom.Next(objBitmap.Height), this.SetFontColor);
}
}
/// <summary>
/// 添加背景噪點
/// </summary>
/// <param name="objBitmap"></param>
/// <param name="objGraphics"></param>
private void AddBackgroundNoisePoint(Bitmap objBitmap, Graphics objGraphics)
{
using (Pen objPen = new Pen(Color.Azure, 0))
{
for (int i = 0; i < objBitmap.Width * 2; i++)
{
objGraphics.DrawRectangle(objPen, objRandom.Next(objBitmap.Width), objRandom.Next(objBitmap.Height), 1, 1);
}
}
}
/// <summary>
/// 獲取隨機顏色
/// </summary>
/// <returns></returns>
private Color GetRandomColor()
{
Random RandomNum_First = new Random((int)DateTime.Now.Ticks);
// 對於C#的隨機數,沒什么好說的
System.Threading.Thread.Sleep(RandomNum_First.Next(50));
Random RandomNum_Sencond = new Random((int)DateTime.Now.Ticks);
// 為了在白色背景上顯示,盡量生成深色
int int_Red = RandomNum_First.Next(256);
int int_Green = RandomNum_Sencond.Next(256);
int int_Blue = (int_Red + int_Green > 400) ? 0 : 400 - int_Red - int_Green;
int_Blue = (int_Blue > 255) ? 255 : int_Blue;
return Color.FromArgb(int_Red, int_Green, int_Blue);
}
#endregion
#region Public Method
/// <summary>
/// 輸出驗證碼圖片
/// </summary>
/// <param name="objHttpResponse">Http響應實例</param>
/// <returns>輸出是否成功</returns>
public bool OutputImage(HttpResponse objHttpResponse)
{
bool result = false;
if (this.SetIsRandomColor)
{
this.SetFontColor = GetRandomColor(); ;
}
using (Bitmap objBitmap = this.GetVerifyCodeImage())
{
if (objBitmap != null)
{
using (MemoryStream objMS = new MemoryStream())
{
objBitmap.Save(objMS, ImageFormat.Jpeg);
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ContentType = "image/Jpeg";
HttpContext.Current.Response.BinaryWrite(objMS.ToArray());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
result = true;
}
}
}
return result;
}
/// <summary>
/// 獲取問題
/// </summary>
/// <param name="questionList">默認數字加減驗證</param>
/// <returns></returns>
public KeyValuePair<string, string> GetQuestion(Dictionary<string, string> questionList = null)
{
if (questionList == null)
{
questionList = new Dictionary<string, string>();
var operArray = new string[] { "+", "*", "num" };
var left = objRandom.Next(0, 10);
var right = objRandom.Next(0, 10);
var oper = operArray[objRandom.Next(0, operArray.Length)];
if (oper == "+")
{
string key = string.Format("{0}+{1}=?", left, right);
string val = (left + right).ToString();
questionList.Add(key, val);
}
else if (oper == "*")
{
string key = string.Format("{0}×{1}=?", left, right);
string val = (left * right).ToString();
questionList.Add(key, val);
}
else
{
var num = objRandom.Next(1000, 9999); ;
questionList.Add(num.ToString(), num.ToString());
}
}
return questionList.ToList()[objRandom.Next(0, questionList.Count)];
}
#endregion
}
}
為嘛就一個類寫這么多,沒排版博客園不給推薦到首頁。。




