开发环境:VS2019,.NET Core 3.1,ASP.NET Core API
1、建立一个验证码控制器
新建两个方法Create和Check,Create用于创建验证码,Check用于验证它是否有效。
声明一个静态类变量存放列表,列表中存放包含令牌和验证码的对象。
private static List<VCodeModel> _list = new List<VCodeModel>();
/// <summary>
/// 返回一个图形验证码和令牌.
/// </summary>
/// <returns></returns>
/// <remarks>这一步需要生成一个数字,并将数字放入图片中,并返回一个令牌,下次验证的时候需要核对令牌和数字是否对应,这些东西保存到类变量中.</remarks>
[HttpGet]
public string Create()
{
try
{
VCodeModel model = new VCodeModel();
model.id = Guid.NewGuid().ToString(); // 生成令牌
var vcode = Utils.GetVCode(); // 生成验证码
model.code = vcode;
_list.Add(model); // 记录到缓存中
// 返回对象
VCodeController_Create_Receive result = new VCodeController_Create_Receive();
result.code = "0";
result.data = new VCodeController_Create_Receive.Data();
result.data.id = model.id;
var image = Utils.DrawImage(vcode);
var base64 = Utils.BitmapToBase64Str(image);
result.data.img = base64;
var json = JsonConvert.SerializeObject(result);
return json;
}
catch (Exception ex)
{
_logger.LogError(exception: ex, message: ex.Message);
ReceiveObject result = new ReceiveObject();
result.code = "999999";
result.msg = "系统异常";
var json = JsonConvert.SerializeObject(result);
return json;
}
}
/// <summary>
/// 检查验证码是否有效
/// </summary>
/// <param name="id">令牌.</param>
/// <param name="code">验证码.</param>
/// <returns></returns>
[HttpGet]
public string Check(string id, string code)
{
try
{
var index = _list.FindIndex(m =>
{
if (m.id.Equals(id) && m.code.Equals(code))
{
return true;
}
return false;
});
ReceiveObject result = new ReceiveObject();
if (index >= 0)
{
_list.RemoveAt(index);
result.code = "0";
result.msg = "验证成功";
var json = JsonConvert.SerializeObject(result);
return json;
}
else
{
result.code = "1";
result.msg = "验证失败";
var json = JsonConvert.SerializeObject(result);
return json;
}
}
catch(Exception ex)
{
_logger.LogError(exception: ex, message: ex.Message);
ReceiveObject result = new ReceiveObject();
result.code = "999999";
result.msg = "系统异常";
var json = JsonConvert.SerializeObject(result);
return json;
}
}
2、建立一个验证码模型
验证码模型类包括:令牌和验证码属性。
再创建一个类存放Create方法返回的对象包括:令牌,验证码图片。
/// <summary>
/// VCodeController用到的类变量.
/// </summary>
public class VCodeModel
{
/// <summary>
/// 令牌.
/// </summary>
public string id { get; set; }
/// <summary>
///验证码.
/// </summary>
public string code { get; set; }
}
/// <summary>
/// VCodeController控制器中Create方法的返回对象.
/// </summary>
public class VCodeController_Create_Receive : ReceiveObject
{
public Data data { get; set; }
public class Data
{
/// <summary>
/// 令牌.
/// </summary>
public string id { get; set; }
/// <summary>
/// Base64的验证码图片.
/// </summary>
public string img { get; set; }
}
}
3、建立一个验证码生成器
创建用于生成4位随机数的方法。
创建将随机数绘制成图片的方法。
static readonly char[] list = new char[10] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', };
/// <summary>
/// 获取随机验证码.
/// </summary>
/// <returns></returns>
public static string GetVCode()
{
Random random = new Random();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 4; i++)
{
var index = random.Next(0, list.Length);
builder.Append(list[index]);
}
return builder.ToString();
}
/// <summary>
/// 绘制验证码的图片.
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public static Bitmap DrawImage(string code)
{
Color[] list_color =
{
Color.FromArgb(240, 230, 140), // 黄褐色(亮)
Color.FromArgb(138, 54, 15), // 黄褐色(暗)
Color.FromArgb(51, 161, 201), // 蓝色(亮)
Color.FromArgb(25, 25, 112), // 蓝色(暗)
Color.FromArgb(192, 192, 192), // 灰白(亮)
Color.FromArgb(128, 128, 105), // 灰白(暗)
};
Random random = new Random();
// 创建画板
Bitmap bitmap = new Bitmap(150, 50);
// 创建画笔
Graphics grp = Graphics.FromImage(bitmap);
grp.Clear(Color.White); // 设置背景色为白色
// 绘制噪点
for (int i = 0; i < random.Next(60, 80); i++)
{
int x = random.Next(bitmap.Width);
int y = random.Next(bitmap.Height);
grp.DrawLine(new Pen(Color.LightGray, 1), x, y, x + 1, y);
}
// 绘制随机的线条
grp.DrawLine(
new Pen(list_color[random.Next(list_color.Length)], random.Next(3)),
new Point(random.Next(bitmap.Width / 2), random.Next(bitmap.Height / 2)),
new Point(bitmap.Width / 2 + random.Next(bitmap.Width / 2), bitmap.Height / 2 + random.Next(bitmap.Height / 2))
);
// 绘制验证码
for (int i = 0; i < code.Length; i++)
{
var item = code[i];
grp.DrawString(item.ToString(),
new Font(FontFamily.GenericSansSerif, 25, FontStyle.Bold),
new SolidBrush(list_color[random.Next(list_color.Length)]),
x: (150 / 4) * i,
y: random.Next(5));
}
// 在验证码上绘制噪点
for (int i = 0; i < random.Next(30, 50); i++)
{
int x = random.Next(bitmap.Width);
int y = random.Next(bitmap.Height);
grp.DrawLine(new Pen(list_color[random.Next(list_color.Length)], 1), x, y, x + 1, y);
}
// 绘制随机的线条
grp.DrawLine(
new Pen(list_color[random.Next(list_color.Length)], random.Next(3)),
new Point(random.Next(bitmap.Width / 2), random.Next(bitmap.Height / 2)),
new Point(bitmap.Width / 2 + random.Next(bitmap.Width / 2), bitmap.Height / 2 + random.Next(bitmap.Height / 2))
);
return bitmap;
}
/// <summary>
/// 将图片对象转成Base64的字符串.
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
public static string BitmapToBase64Str(Bitmap bitmap)
{
using (MemoryStream memoryStream = new MemoryStream())
{
bitmap.Save(memoryStream, ImageFormat.Jpeg);
byte[] bytes = memoryStream.ToArray();
return Convert.ToBase64String(memoryStream.ToArray());
}
}
运行效果: