You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
2.5 KiB
78 lines
2.5 KiB
using CellularManagement.Domain.Services;
|
|
using SkiaSharp;
|
|
|
|
namespace CellularManagement.Infrastructure.Services.Security;
|
|
|
|
public class CaptchaService : ICaptchaService
|
|
{
|
|
private readonly Random _random = new();
|
|
private readonly string[] _fonts = { "Arial", "Verdana", "Times New Roman", "Tahoma" };
|
|
private readonly SKColor[] _colors = {
|
|
SKColors.Black, SKColors.Red, SKColors.Blue, SKColors.Green, SKColors.Purple, SKColors.Orange
|
|
};
|
|
|
|
public (string Code, byte[] ImageBytes) GenerateCaptcha(int length = 4)
|
|
{
|
|
string code = GenerateRandomCode(length);
|
|
int width = Math.Max(120, 10 + length * 25);
|
|
int height = 40;
|
|
|
|
using var bitmap = new SKBitmap(width, height);
|
|
using var canvas = new SKCanvas(bitmap);
|
|
canvas.Clear(SKColors.White);
|
|
|
|
// 干扰线
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
using var paint = new SKPaint
|
|
{
|
|
Color = _colors[_random.Next(_colors.Length)],
|
|
StrokeWidth = 1
|
|
};
|
|
canvas.DrawLine(
|
|
_random.Next(width), _random.Next(height),
|
|
_random.Next(width), _random.Next(height),
|
|
paint
|
|
);
|
|
}
|
|
|
|
// 干扰点
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
using var paint = new SKPaint
|
|
{
|
|
Color = _colors[_random.Next(_colors.Length)],
|
|
StrokeWidth = 1
|
|
};
|
|
canvas.DrawPoint(_random.Next(width), _random.Next(height), paint);
|
|
}
|
|
|
|
// 绘制验证码字符
|
|
for (int i = 0; i < code.Length; i++)
|
|
{
|
|
using var paint = new SKPaint
|
|
{
|
|
Color = _colors[_random.Next(_colors.Length)],
|
|
TextSize = 24,
|
|
IsAntialias = true,
|
|
Typeface = SKTypeface.FromFamilyName(_fonts[_random.Next(_fonts.Length)], SKFontStyle.Bold)
|
|
};
|
|
float x = 10 + i * 25;
|
|
float y = 30 + _random.Next(-5, 5);
|
|
canvas.DrawText(code[i].ToString(), x, y, paint);
|
|
}
|
|
|
|
using var ms = new MemoryStream();
|
|
using var image = SKImage.FromBitmap(bitmap);
|
|
image.Encode(SKEncodedImageFormat.Png, 100).SaveTo(ms);
|
|
|
|
return (code, ms.ToArray());
|
|
}
|
|
|
|
private string GenerateRandomCode(int length)
|
|
{
|
|
const string chars = "2345678ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
return new string(Enumerable.Repeat(chars, length)
|
|
.Select(s => s[_random.Next(s.Length)]).ToArray());
|
|
}
|
|
}
|