我已经这样做了:
添加对 System.Drawing.Common 的引用
如果在 linux 上安装 linux 库:
sudo apt install libc6-dev
sudo apt install libgdiplus
- 在 AccountController 中
[AllowAnonymous]
public async Task<IActionResult> GetCaptchaImage()
{
var validate = "";
var bmp = ImageCaptcha.Generate(200, 150, out validate);
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(ms.ToArray());
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
SetCookie("CV", validate.Hash()+"");
return File(ms.ToArray(),"image/png");
}
}
// move to base controller
public void SetCookie(string key, string value, int? expireTime = null)
{
CookieOptions option = new CookieOptions();
if (expireTime.HasValue)
option.Expires = DateTime.Now.AddMinutes(expireTime.Value);
else
option.Expires = DateTime.Now.AddMilliseconds(5 * 60 * 1000);
Response.Cookies.Append(key, value, option);
}
将此类添加到项目中 - 在 mem 中生成随机旋转的字母 bmp:
public static class ImageCaptcha
{
public static Bitmap Generate(int w, int h, out string validate)
{
Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bmp);
var brush = new[] { Brushes.Brown, Brushes.LawnGreen, Brushes.Blue, Brushes.Coral};
var rand = new Random((int)DateTime.Now.Ticks);
validate = null;
using (Graphics g = Graphics.FromImage(bmp))
{
for (int i = 0; i < 4; i++)
{
var text = Convert.ToChar( rand.Next(97, 122)).ToString();
validate += text;
if(i==0) g.TranslateTransform(bmp.Width / 2, bmp.Height / 2);
g.RotateTransform(40 * 5 * rand.Next(1, 6));
var font = new Font("Arial", h * 0.25f + 8 * rand.Next(1, 6), FontStyle.Bold);
SizeF textSize = g.MeasureString(text, font);
g.DrawString(text, font, brush[i],15*(i+1) -(textSize.Width / 2), -(textSize.Height / 2));
}
}
return bmp;
}
}
添加此实用程序类以轻松获取 md5 哈希:
public static partial class H
{
public static int Hash(this string value)
{
MD5 md5Hasher = MD5.Create();
var hashed = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(value));
var ivalue = BitConverter.ToInt32(hashed, 0);
return ivalue;
}
}
- 对此进行更改注册操作,请参阅 cmets - 添加、更改:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
var validCaptchaText = Request.Cookies["cv"]; //added
if (ModelState.IsValid && model.UserCaptchaText.Hash()+""==validCaptchaText) //changed
{
var user = new AppUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation("User created a new account with password.");
return RedirectToLocal(returnUrl);
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
- 在“确认密码”之后的注册视图中
<div class="form-group">
<label>Captcha</label><br />
<img style="width:100%; border:solid 1px #ced4da" height="150" src="@Url.Action("GetCaptchaImage")" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
<ul style="list-style-type:none">
<li style="width:24px;height:12px; display:inline-block; background-color:#a52a2a "></li>
<li style="width:24px;height:12px; display:inline-block; background-color:#7cfc00 "></li>
<li style="width:24px;height:12px; display:inline-block; background-color:#0000ff "></li>
<li style="width:24px;height:12px; display:inline-block; background-color:#ff7f50 "></li>
</ul>
</div>
<div class="form-group">
<label asp-for="UserCaptchaText"></label>
<input asp-for="UserCaptchaText" class="form-control" />
</div>
<button style="color:white; background-color:#4a7dbc" type="submit" class="btn btn-default">Register</button>
完成了。