ValidateCode.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Drawing2D;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7. using System.Text;
  8. using System.Web;
  9. namespace CommonTool
  10. {
  11. public class ValidateCode
  12. {
  13. public ValidateCode()
  14. {
  15. Code = CreateValidateCode(4);
  16. }
  17. public string Code { get; }
  18. /// <summary>
  19. /// 验证码的最大长度
  20. /// </summary>
  21. public int MaxLength => 10;
  22. /// <summary>
  23. /// 验证码的最小长度
  24. /// </summary>
  25. public int MinLength => 4;
  26. /// <summary>
  27. /// 生成验证码
  28. /// </summary>
  29. /// <param name="length">指定验证码的长度</param>
  30. /// <returns></returns>
  31. public string CreateValidateCode(int length)
  32. {
  33. int[] randMembers = new int[length];
  34. int[] validateNums = new int[length];
  35. string validateNumberStr = "";
  36. //生成起始序列值
  37. int seekSeek = unchecked((int)DateTime.Now.Ticks);
  38. Random seekRand = new Random(seekSeek);
  39. int beginSeek = seekRand.Next(0, Int32.MaxValue - length * 10000);
  40. int[] seeks = new int[length];
  41. for (int i = 0; i < length; i++)
  42. {
  43. beginSeek += 10000;
  44. seeks[i] = beginSeek;
  45. }
  46. //生成随机数字
  47. for (int i = 0; i < length; i++)
  48. {
  49. Random rand = new Random(seeks[i]);
  50. int pownum = 1 * (int)Math.Pow(10, length);
  51. randMembers[i] = rand.Next(pownum, Int32.MaxValue);
  52. }
  53. //抽取随机数字
  54. for (int i = 0; i < length; i++)
  55. {
  56. string numStr = randMembers[i].ToString();
  57. int numLength = numStr.Length;
  58. Random rand = new Random();
  59. int numPosition = rand.Next(0, numLength - 1);
  60. validateNums[i] = Int32.Parse(numStr.Substring(numPosition, 1));
  61. }
  62. //生成验证码
  63. for (int i = 0; i < length; i++)
  64. {
  65. validateNumberStr += validateNums[i].ToString();
  66. }
  67. return validateNumberStr;
  68. }
  69. /// <summary>
  70. /// 创建验证码的图片
  71. /// </summary>
  72. /// <param name="validateCode">验证码</param>
  73. public byte[] CreateValidateGraphic(string validateCode)
  74. {
  75. Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 22);
  76. Graphics g = Graphics.FromImage(image);
  77. try
  78. {
  79. //生成随机生成器
  80. Random random = new Random();
  81. //清空图片背景色
  82. g.Clear(Color.White);
  83. //画图片的干扰线
  84. for (int i = 0; i < 25; i++)
  85. {
  86. int x1 = random.Next(image.Width);
  87. int x2 = random.Next(image.Width);
  88. int y1 = random.Next(image.Height);
  89. int y2 = random.Next(image.Height);
  90. g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
  91. }
  92. Font font = new Font("Arial", 16, (FontStyle.Bold | FontStyle.Italic));
  93. LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),
  94. Color.Blue, Color.DarkRed, 1.2f, true);
  95. g.DrawString(validateCode, font, brush, 3, 2);
  96. //画图片的前景干扰点
  97. for (int i = 0; i < 100; i++)
  98. {
  99. int x = random.Next(image.Width);
  100. int y = random.Next(image.Height);
  101. image.SetPixel(x, y, Color.FromArgb(random.Next()));
  102. }
  103. //画图片的边框线
  104. g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
  105. //保存图片数据
  106. MemoryStream stream = new MemoryStream();
  107. image.Save(stream, ImageFormat.Jpeg);
  108. //输出图片流
  109. return stream.ToArray();
  110. }
  111. finally
  112. {
  113. g.Dispose();
  114. image.Dispose();
  115. }
  116. }
  117. /// <summary>
  118. /// 创建验证码的图片
  119. /// </summary>
  120. /// <param name="validateCode">验证码</param>
  121. /// <param name="context">要输出到的page对象</param>
  122. public void CreateValidateGraphic(string validateCode, HttpContext context)
  123. {
  124. Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 12.0), 22);
  125. Graphics g = Graphics.FromImage(image);
  126. try
  127. {
  128. //生成随机生成器
  129. Random random = new Random();
  130. //清空图片背景色
  131. g.Clear(Color.White);
  132. //画图片的干扰线
  133. for (int i = 0; i < 25; i++)
  134. {
  135. int x1 = random.Next(image.Width);
  136. int x2 = random.Next(image.Width);
  137. int y1 = random.Next(image.Height);
  138. int y2 = random.Next(image.Height);
  139. g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
  140. }
  141. Font font = new Font("Arial", 16, (FontStyle.Bold | FontStyle.Italic));
  142. LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),
  143. Color.Blue, Color.DarkRed, 1.2f, true);
  144. g.DrawString(validateCode, font, brush, 3, 2);
  145. //画图片的前景干扰点
  146. for (int i = 0; i < 100; i++)
  147. {
  148. int x = random.Next(image.Width);
  149. int y = random.Next(image.Height);
  150. image.SetPixel(x, y, Color.FromArgb(random.Next()));
  151. }
  152. //画图片的边框线
  153. g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
  154. //保存图片数据
  155. MemoryStream stream = new MemoryStream();
  156. image.Save(stream, ImageFormat.Jpeg);
  157. //输出图片流
  158. context.Response.Clear();
  159. context.Response.ContentType = "image/jpeg";
  160. context.Response.BinaryWrite(stream.ToArray());
  161. }
  162. finally
  163. {
  164. g.Dispose();
  165. image.Dispose();
  166. }
  167. }
  168. /// <summary>
  169. /// 得到验证码图片的长度
  170. /// </summary>
  171. /// <param name="validateNumLength">验证码的长度</param>
  172. /// <returns></returns>
  173. public static int GetImageWidth(int validateNumLength)
  174. {
  175. return (int)(validateNumLength * 16.0);
  176. }
  177. /// <summary>
  178. /// 得到验证码的高度
  179. /// </summary>
  180. /// <returns></returns>
  181. public static double GetImageHeight()
  182. {
  183. return 24;
  184. }
  185. }
  186. public class ValidateCodePic
  187. {
  188. private readonly List<string> _fuHao;
  189. private readonly List<Color> _color;
  190. private readonly List<Font> _font;
  191. private int _x;
  192. private int _y;
  193. private readonly int _width;
  194. private readonly int _height;
  195. private readonly Random _r = new Random();
  196. public bool IsExp { get; set; }
  197. public Bitmap FileBitmap { get; set; }
  198. public byte[] FileBytes { get; set; }
  199. public string Code { get; set; }
  200. public HttpContext Context { get; set; }
  201. public ValidateCodePic()
  202. {
  203. _width = 100;
  204. _height = 40;
  205. _fuHao = new List<string>() { "加", "减" };
  206. _color = new List<Color>() {Color.Red,Color.Black,Color.Blue,Color.Green,
  207. ColorTranslator.FromHtml("#FF00FF"),
  208. ColorTranslator.FromHtml("#CD0000"),
  209. ColorTranslator.FromHtml("#912CEE"),
  210. ColorTranslator.FromHtml("#00F5FF"),
  211. ColorTranslator.FromHtml("#00FF00")
  212. };
  213. _font = new List<Font>() {
  214. // ReSharper disable once PossibleLossOfFraction
  215. new Font("宋体",_width/8,FontStyle.Bold),
  216. // ReSharper disable once PossibleLossOfFraction
  217. new Font("楷体",_width/8,FontStyle.Italic),
  218. // ReSharper disable once PossibleLossOfFraction
  219. new Font("新宋体",_width/8,FontStyle.Regular)
  220. };
  221. }
  222. /// <summary>
  223. /// 构造函数重载
  224. /// </summary>
  225. /// <param name="isExp">默认 true 公式图片 、falae 字母图片</param>
  226. /// <param name="width"></param>
  227. /// <param name="height"></param>
  228. /// <param name="isByte">默认true返回数据流、false返回图片</param>
  229. public ValidateCodePic(int width, int height, bool isExp=true,bool isByte=true):this()
  230. {
  231. IsExp =isExp;
  232. _width = width;
  233. _height = height;
  234. if (isByte)
  235. {
  236. var tempTupleByte = IsExp ? DrawExpByte() : DrawStrByte();
  237. FileBytes = tempTupleByte.Item1;
  238. Code = tempTupleByte.Item2;
  239. }
  240. else
  241. {
  242. var tempTupleBitmap = IsExp ? DrawExpBitmap() : DrawStrBigmap();
  243. FileBitmap = tempTupleBitmap.Item1;
  244. Code = tempTupleBitmap.Item2;
  245. }
  246. }
  247. public ValidateCodePic(HttpContext content,int width, int height, bool isExp = true) : this()
  248. {
  249. IsExp = isExp;
  250. _width = width;
  251. _height = height;
  252. Context = content;
  253. var tempTupleContext = IsExp ? DrawExp(Context) : DrawStr(Context);
  254. FileBitmap = tempTupleContext.Item1;
  255. Code = tempTupleContext.Item2;
  256. }
  257. //public ValidateCodePic(int width=100, int height=30)
  258. //{
  259. // _width = width;
  260. // _height = height;
  261. // _fuHao = new List<string>() {"加","减"};
  262. // _color = new List<Color>() {Color.Red,Color.Black,Color.Blue,Color.Green,
  263. // ColorTranslator.FromHtml("#6A5ACD"),
  264. // ColorTranslator.FromHtml("#008B8B"),
  265. // ColorTranslator.FromHtml("#556B2F"),
  266. // ColorTranslator.FromHtml("#4B0082"),
  267. // ColorTranslator.FromHtml("#20B2AA"),
  268. // ColorTranslator.FromHtml("#9ACD32"),
  269. // ColorTranslator.FromHtml("#B22222"),
  270. // ColorTranslator.FromHtml("#BA55D3"),
  271. // ColorTranslator.FromHtml("#F0E68C"),
  272. // ColorTranslator.FromHtml("#1E90FF")
  273. // };
  274. // _font = new List<Font>() {
  275. // // ReSharper disable once PossibleLossOfFraction
  276. // new Font("宋体",width/5,FontStyle.Bold),
  277. // // ReSharper disable once PossibleLossOfFraction
  278. // new Font("楷体",width/6,FontStyle.Italic),
  279. // // ReSharper disable once PossibleLossOfFraction
  280. // new Font("新宋体",width/5,FontStyle.Regular)
  281. // };
  282. //}
  283. public Tuple<byte[], string> DrawStrByte()
  284. {
  285. StringBuilder sb = new StringBuilder();
  286. Bitmap b = GetMap(_width, _height);
  287. //生成画布
  288. Graphics g = Graphics.FromImage(b);
  289. try
  290. {
  291. //清空图片背景色
  292. g.Clear(Color.White);
  293. //画背景图
  294. g.FillRectangle(Brushes.Gainsboro, 0, 0, _width, _height);
  295. //画字
  296. for (int i = 0; i < 4; i++)
  297. {
  298. string temp = RandomString();
  299. sb.Append(temp);
  300. DrawString(g, temp);
  301. }
  302. //画干扰线
  303. DrawGanRao(g, 40);
  304. //画干扰点
  305. DrawGanRaoDian(b, 1000);
  306. //画图片的边框线
  307. g.DrawRectangle(new Pen(Color.DarkGray), 0, 0, _width - 1, _height - 1);
  308. //保存图片数据
  309. MemoryStream stream = new MemoryStream();
  310. b.Save(stream, ImageFormat.Jpeg);
  311. //输出图片流
  312. return new Tuple<byte[], string>(stream.ToArray(), sb.ToString());
  313. }
  314. finally
  315. {
  316. g.Dispose();
  317. b.Dispose();
  318. }
  319. }
  320. public Tuple<Bitmap, string> DrawStrBigmap()
  321. {
  322. StringBuilder sb = new StringBuilder();
  323. Bitmap b = GetMap(_width, _height);
  324. //生成画布
  325. Graphics g = Graphics.FromImage(b);
  326. try
  327. {
  328. //清空图片背景色
  329. g.Clear(Color.White);
  330. //画背景图
  331. g.FillRectangle(Brushes.Gainsboro, 0, 0, _width, _height);
  332. //画字
  333. for (int i = 0; i < 4; i++)
  334. {
  335. string temp = RandomString();
  336. sb.Append(temp);
  337. DrawString(g, temp);
  338. }
  339. //画干扰线
  340. DrawGanRao(g, 40);
  341. //画干扰点
  342. DrawGanRaoDian(b, 1000);
  343. //输出图片
  344. return new Tuple<Bitmap, string>(b, sb.ToString());
  345. }
  346. finally
  347. {
  348. g.Dispose();
  349. b.Dispose();
  350. }
  351. }
  352. public Tuple<Bitmap, string> DrawStr(HttpContext context)
  353. {
  354. StringBuilder sb = new StringBuilder();
  355. Bitmap b = GetMap(_width, _height);
  356. //生成画布
  357. Graphics g = Graphics.FromImage(b);
  358. try
  359. {
  360. //清空图片背景色
  361. g.Clear(Color.White);
  362. //画背景图
  363. g.FillRectangle(Brushes.Gainsboro, 0, 0, _width, _height);
  364. //画字
  365. for (int i = 0; i < 4; i++)
  366. {
  367. string temp = RandomString();
  368. sb.Append(temp);
  369. DrawString(g, temp);
  370. }
  371. //画干扰线
  372. DrawGanRao(g, 40);
  373. //画干扰点
  374. DrawGanRaoDian(b, 1000);
  375. //画图片的边框线
  376. g.DrawRectangle(new Pen(Color.DarkGray), 0, 0, _width - 1, _height - 1);
  377. //保存图片数据
  378. MemoryStream stream = new MemoryStream();
  379. b.Save(stream, ImageFormat.Jpeg);
  380. //输出图片流
  381. context.Response.Clear();
  382. context.Response.ContentType = "image/jpeg";
  383. context.Response.BinaryWrite(stream.ToArray());
  384. }
  385. finally
  386. {
  387. g.Dispose();
  388. b.Dispose();
  389. }
  390. return new Tuple<Bitmap, string>(b, sb.ToString());
  391. }
  392. private Bitmap GetMap(int width, int height)
  393. {
  394. Bitmap b = new Bitmap(width, height);
  395. return b;
  396. }
  397. private string RandomString()
  398. {
  399. string s = ((char)_r.Next(65, 90)).ToString();
  400. return s;
  401. }
  402. private void DrawString(Graphics g, string s)
  403. {
  404. Font font = _font[RandomToInt(_font.Count)];
  405. Color color = _color[RandomToInt(_color.Count)];
  406. _x += _width /6;
  407. _y = RandomToInt(_height/6);
  408. g.DrawString(s,
  409. font,
  410. new SolidBrush(color),
  411. new PointF(_x, _y)
  412. );
  413. g.RotateTransform(RandomToInt(6));
  414. }
  415. private void DrawGanRao(Graphics g, int j)
  416. {
  417. for (int i = 0; i < j; i++)
  418. {
  419. g.DrawLine(new Pen(_color[RandomToInt(_color.Count)]),
  420. RandomToInt(_width),
  421. RandomToInt(_height),
  422. RandomToInt(_width),
  423. RandomToInt(_height)
  424. );
  425. }
  426. }
  427. private void DrawGanRaoDian(Bitmap b, int j)
  428. {
  429. for (int i = 0; i < j; i++)
  430. {
  431. b.SetPixel(RandomToInt(_width),
  432. RandomToInt(_height),
  433. _color[RandomToInt(_color.Count)]);
  434. }
  435. }
  436. /// <summary>
  437. /// 随机字符
  438. /// </summary>
  439. /// <returns></returns>
  440. private int RandomToInt(int i)
  441. {
  442. return _r.Next(0, i);
  443. }
  444. public Tuple<byte[], string> DrawExpByte()
  445. {
  446. int frist = GetString();
  447. int scoend = GetString();
  448. string fuhao = _fuHao[RandomToInt(_fuHao.Count)];
  449. Bitmap b = GetMap(_width, _height);
  450. Graphics g = Graphics.FromImage(b);
  451. try
  452. {
  453. //清空图片背景色
  454. g.Clear(Color.White);
  455. g.FillRectangle(Brushes.Gainsboro, 0, 0, _width, _height);
  456. DrawString(g, frist.ToString());
  457. DrawString(g, fuhao);
  458. DrawString(g, scoend.ToString());
  459. DrawString(g, " = ? ");
  460. //画图片的边框线
  461. //g.DrawRectangle(new Pen(Color.CornflowerBlue), 0, 0, _width - 1, _height - 1);
  462. //保存图片数据
  463. MemoryStream stream = new MemoryStream();
  464. b.Save(stream, ImageFormat.Jpeg);
  465. //输出图片流
  466. return new Tuple<byte[], string>(stream.ToArray(), GetResult(fuhao, frist, scoend).ToString());
  467. }
  468. finally
  469. {
  470. g.Dispose();
  471. b.Dispose();
  472. }
  473. }
  474. public Tuple<Bitmap, string> DrawExpBitmap()
  475. {
  476. int frist = GetString();
  477. int scoend = GetString();
  478. string fuhao = _fuHao[RandomToInt(_fuHao.Count)];
  479. Bitmap b = GetMap(_width, _height);
  480. Graphics g = Graphics.FromImage(b);
  481. try
  482. {
  483. //清空图片背景色
  484. g.Clear(Color.White);
  485. g.FillRectangle(Brushes.Gainsboro, 0, 0, _width, _height);
  486. DrawString(g, frist.ToString());
  487. DrawString(g, fuhao);
  488. DrawString(g, scoend.ToString());
  489. DrawString(g, " = ? ");
  490. //画图片的边框线
  491. //g.DrawRectangle(new Pen(Color.CornflowerBlue), 0, 0, _width - 1, _height - 1);
  492. //保存图片数据
  493. MemoryStream stream = new MemoryStream();
  494. b.Save(stream, ImageFormat.Jpeg);
  495. //输出图片流
  496. return new Tuple<Bitmap, string>(b, GetResult(fuhao, frist, scoend).ToString());
  497. }
  498. finally
  499. {
  500. g.Dispose();
  501. b.Dispose();
  502. }
  503. }
  504. public Tuple<Bitmap, string> DrawExp(HttpContext context)
  505. {
  506. int frist = GetString();
  507. int scoend = GetString();
  508. string fuhao = _fuHao[RandomToInt(_fuHao.Count)];
  509. Bitmap b = GetMap(_width, _height);
  510. Graphics g = Graphics.FromImage(b);
  511. try
  512. {
  513. g.Clear(Color.White);
  514. g.FillRectangle(Brushes.Gainsboro, 0, 0, _width, _height);
  515. DrawString(g, frist.ToString());
  516. DrawString(g, fuhao);
  517. DrawString(g, scoend.ToString());
  518. DrawString(g, "=?");
  519. //画图片的边框线
  520. g.DrawRectangle(new Pen(Color.DarkGray), 0, 0, _width - 1, _height - 1);
  521. //保存图片数据
  522. MemoryStream stream = new MemoryStream();
  523. b.Save(stream, ImageFormat.Jpeg);
  524. //输出图片流
  525. context.Response.Clear();
  526. context.Response.ContentType = "image/jpeg";
  527. context.Response.BinaryWrite(stream.ToArray());
  528. }
  529. finally
  530. {
  531. g.Dispose();
  532. b.Dispose();
  533. }
  534. return new Tuple<Bitmap,string>(b, GetResult(fuhao, frist, scoend).ToString());
  535. }
  536. /// <summary>
  537. /// 随机得到数字
  538. /// </summary>
  539. /// <returns></returns>
  540. private int GetString()
  541. {
  542. return RandomToInt(50);
  543. }
  544. private int GetResult(string fuhao, int frist, int scoend)
  545. {
  546. int result = frist + scoend;
  547. switch (fuhao)
  548. {
  549. case "加": result = frist + scoend; break;
  550. case "减": result = frist - scoend; break;
  551. }
  552. return result;
  553. }
  554. }
  555. }