Files
squad-rain-ops-mini/Helpers/CaptchaHelper.cs

92 lines
3.2 KiB
C#

using System;
using System.Text;
using System.Security.Cryptography;
namespace RainOpsMini.Helpers
{
public static class CaptchaHelper
{
private static readonly char[] Chars = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ".ToCharArray();
public static (string Code, string Svg) GenerateCaptcha(int width = 120, int height = 40)
{
var code = GenerateRandomCode(4);
var svg = GenerateSvg(code, width, height);
return (code, svg);
}
private static string GenerateRandomCode(int length)
{
var sb = new StringBuilder(length);
var data = new byte[length];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(data);
}
foreach (var b in data)
{
sb.Append(Chars[b % Chars.Length]);
}
return sb.ToString();
}
private static string GenerateSvg(string code, int width, int height)
{
var sb = new StringBuilder();
var random = new Random();
sb.Append($"<svg width=\"{width}\" height=\"{height}\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 {width} {height}\">");
// Background
sb.Append($"<rect width=\"100%\" height=\"100%\" fill=\"#f2f2f2\"/>");
// Noise lines
for (int i = 0; i < 5; i++)
{
int x1 = random.Next(0, width);
int y1 = random.Next(0, height);
int x2 = random.Next(0, width);
int y2 = random.Next(0, height);
string color = GetRandomColor(random);
sb.Append($"<line x1=\"{x1}\" y1=\"{y1}\" x2=\"{x2}\" y2=\"{y2}\" stroke=\"{color}\" stroke-width=\"1\" opacity=\"0.5\"/>");
}
// Dots
for (int i = 0; i < 50; i++)
{
int cx = random.Next(0, width);
int cy = random.Next(0, height);
string color = GetRandomColor(random);
sb.Append($"<circle cx=\"{cx}\" cy=\"{cy}\" r=\"1\" fill=\"{color}\" opacity=\"0.5\"/>");
}
// Text
int charWidth = width / code.Length;
for (int i = 0; i < code.Length; i++)
{
int x = i * charWidth + random.Next(5, 10);
int y = height / 2 + random.Next(5, 10);
int fontSize = random.Next(20, 28);
string color = GetRandomDarkColor(random);
int rotate = random.Next(-20, 20);
sb.Append($"<text x=\"{x}\" y=\"{y}\" font-family=\"Arial, sans-serif\" font-size=\"{fontSize}\" font-weight=\"bold\" fill=\"{color}\" transform=\"rotate({rotate} {x} {y})\">{code[i]}</text>");
}
sb.Append("</svg>");
return sb.ToString();
}
private static string GetRandomColor(Random random)
{
return $"rgb({random.Next(0, 256)},{random.Next(0, 256)},{random.Next(0, 256)})";
}
private static string GetRandomDarkColor(Random random)
{
return $"rgb({random.Next(0, 150)},{random.Next(0, 150)},{random.Next(0, 150)})";
}
}
}