From d92dc98413d6a697b806f07453c2f1c569704d05 Mon Sep 17 00:00:00 2001 From: pojianbing <76243339@qq.com> Date: Sat, 12 Mar 2022 22:05:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=8C=E6=AC=A1=E9=AA=8C=E8=AF=81=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lazy.Captcha.Core/DefaultCaptcha.cs | 70 ++------ Lazy.Captcha.Core/ICaptcha.cs | 26 ++- Lazy.Captcha.Core/Lazy.Captcha.Core.csproj | 4 +- Lazy.Captcha.Core/Storage/DefaultStorage.cs | 57 +----- Lazy.Captcha.Core/Storage/IStorage.cs | 14 +- Lazy.Captcha.Test/Demo1.cs | 101 ----------- Lazy.Captcha.Test/Demo2.cs | 46 ----- Lazy.Captcha.Test/Demo3.cs | 164 ------------------ Lazy.Captcha.Test/Demo4.cs | 28 --- Lazy.Captcha.Test/Demo5.cs | 135 -------------- Lazy.Captcha.Test/Demo6.cs | 63 ------- Lazy.Captcha.Test/Demo7.cs | 49 ------ Lazy.Captcha.Test/Demo8.cs | 76 -------- Lazy.Captcha.Test/Lazy.Captcha.Test.csproj | 20 --- Lazy.Captcha.Test/Program.cs | 13 -- Lazy.Captcha.Test/inputs/fb.jpg | Bin 15787 -> 0 bytes .../Controllers/CaptchaController.cs | 14 +- Lazy.Captcha.Web/appsettings.json | 2 +- LazyCaptcha.sln | 8 +- 19 files changed, 51 insertions(+), 839 deletions(-) delete mode 100644 Lazy.Captcha.Test/Demo1.cs delete mode 100644 Lazy.Captcha.Test/Demo2.cs delete mode 100644 Lazy.Captcha.Test/Demo3.cs delete mode 100644 Lazy.Captcha.Test/Demo4.cs delete mode 100644 Lazy.Captcha.Test/Demo5.cs delete mode 100644 Lazy.Captcha.Test/Demo6.cs delete mode 100644 Lazy.Captcha.Test/Demo7.cs delete mode 100644 Lazy.Captcha.Test/Demo8.cs delete mode 100644 Lazy.Captcha.Test/Lazy.Captcha.Test.csproj delete mode 100644 Lazy.Captcha.Test/Program.cs delete mode 100644 Lazy.Captcha.Test/inputs/fb.jpg diff --git a/Lazy.Captcha.Core/DefaultCaptcha.cs b/Lazy.Captcha.Core/DefaultCaptcha.cs index 942c00c..eba6b6f 100644 --- a/Lazy.Captcha.Core/DefaultCaptcha.cs +++ b/Lazy.Captcha.Core/DefaultCaptcha.cs @@ -6,24 +6,20 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading; using System.Threading.Tasks; namespace Lazy.Captcha.Core { - /// - /// 默认验证码服务 - /// public class DefaultCaptcha : ICaptcha { - private readonly CaptchaOptions _options; + private readonly IOptionsMonitor _options; private readonly IStorage _storage; private readonly ICaptchaCodeGenerator _captchaCodeGenerator; private readonly ICaptchaImageGenerator _captchaImageGenerator; public DefaultCaptcha(IOptionsMonitor options, IStorage storage) { - _options = options.CurrentValue; + _options = options; _storage = storage; _captchaCodeGenerator = new DefaultCaptchaCodeGenerator(options.CurrentValue.CaptchaType); _captchaImageGenerator = new DefaultCaptchaImageGenerator(); @@ -32,66 +28,38 @@ namespace Lazy.Captcha.Core /// /// 生成验证码 /// - public CaptchaData Generate(string captchaId) + /// 验证码id + /// 缓存时间,未设定则使用配置时间 + /// + public CaptchaData Generate(string captchaId, int? expirySeconds = null) { - var (renderText, code) = _captchaCodeGenerator.Generate(_options.CodeLength); - var image = _captchaImageGenerator.Generate(renderText, _options.ImageOption); - _storage.Set(captchaId, code, TimeSpan.FromSeconds(_options.ExpirySeconds)); + var (renderText, code) = _captchaCodeGenerator.Generate(_options.CurrentValue.CodeLength); + var image = _captchaImageGenerator.Generate(renderText, _options.CurrentValue.ImageOption); + expirySeconds = expirySeconds.HasValue ? expirySeconds.Value : _options.CurrentValue.ExpirySeconds; + _storage.Set(captchaId, code, DateTime.Now.AddSeconds(expirySeconds.Value).ToUniversalTime()); return new CaptchaData(captchaId, code, image); } - /// - /// 生成验证码 - /// - public Task GenerateAsync(string captchaId, CancellationToken token = default) - { - return Task.Run(() => Generate(captchaId), token); - } - /// /// 校验 /// - public bool Validate(string captchaId, string code, TimeSpan? delay = null) + /// 验证码id + /// 用户输入的验证码 + /// 校验成功时是否移除缓存(用于多次验证) + /// + public bool Validate(string captchaId, string code, bool removeIfSuccess = true) { var val = _storage.Get(captchaId); - var comparisonType = _options.IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture; - var result = string.Equals(val, code, comparisonType); + var comparisonType = _options.CurrentValue.IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture; + var success = string.Equals(val, code, comparisonType); - // 仅成功并需要延迟移除时 - if (result && delay != null) - { - _storage.RemoveLater(captchaId, delay.Value); - } - // 否则直接移除 - else + if (!success || (success && removeIfSuccess)) { _storage.Remove(captchaId); } - return result; - } - - /// - /// 校验 - /// - public async Task ValidateAsync(string captchaId, string code, TimeSpan? delay = null, CancellationToken token = default) - { - var val = _storage.Get(captchaId); - var comparisonType = _options.IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture; - var result = string.Equals(val, code, comparisonType); - - // 仅成功并需要延迟移除时 - if (result && delay != null) - { - await _storage.RemoveLaterAsync(captchaId, delay.Value, token); - } - // 否则直接移除 - else - { - await _storage.RemoveAsync(captchaId, token); - } - return result; + return success; } } } \ No newline at end of file diff --git a/Lazy.Captcha.Core/ICaptcha.cs b/Lazy.Captcha.Core/ICaptcha.cs index f6a501c..54ace64 100644 --- a/Lazy.Captcha.Core/ICaptcha.cs +++ b/Lazy.Captcha.Core/ICaptcha.cs @@ -2,19 +2,27 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading; using System.Threading.Tasks; namespace Lazy.Captcha.Core -{ +{ public interface ICaptcha { - CaptchaData Generate(string captchaId); + /// + /// 鐢熸垚楠岃瘉鐮 + /// + /// 楠岃瘉鐮乮d + /// 缂撳瓨鏃堕棿锛屾湭璁惧畾鍒欎娇鐢ㄩ厤缃椂闂 + /// + CaptchaData Generate(string captchaId, int? expirySeconds = null); - Task GenerateAsync(string captchaId, CancellationToken token = default); - - bool Validate(string captchaId, string code, TimeSpan? delay = null); - - Task ValidateAsync(string captchaId, string code, TimeSpan? delay = null, CancellationToken token = default); + /// + /// 鏍¢獙 + /// + /// 楠岃瘉鐮乮d + /// 鐢ㄦ埛杈撳叆鐨勯獙璇佺爜 + /// 鏍¢獙鎴愬姛鏃舵槸鍚︾Щ闄ょ紦瀛(鐢ㄤ簬澶氭楠岃瘉) + /// + bool Validate(string captchaId, string code, bool removeIfSuccess = true); } -} \ No newline at end of file +} diff --git a/Lazy.Captcha.Core/Lazy.Captcha.Core.csproj b/Lazy.Captcha.Core/Lazy.Captcha.Core.csproj index e84a301..a10a876 100644 --- a/Lazy.Captcha.Core/Lazy.Captcha.Core.csproj +++ b/Lazy.Captcha.Core/Lazy.Captcha.Core.csproj @@ -6,8 +6,8 @@ https://gitee.com/pojianbing/lazy-captcha https://gitee.com/pojianbing/lazy-captcha git - 1.1.0 - 1.1.0 + 1.1.1 + 1.1.1 diff --git a/Lazy.Captcha.Core/Storage/DefaultStorage.cs b/Lazy.Captcha.Core/Storage/DefaultStorage.cs index 2457970..f93d0f7 100644 --- a/Lazy.Captcha.Core/Storage/DefaultStorage.cs +++ b/Lazy.Captcha.Core/Storage/DefaultStorage.cs @@ -1,6 +1,4 @@ 锘縰sing System; -using System.Threading; -using System.Threading.Tasks; using Lazy.Captcha.Core.Storage; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Options; @@ -28,68 +26,17 @@ namespace Lazy.Captcha.Core.Storeage return _cache.GetString(WrapKey(key)); } - public Task GetAsync(string key, CancellationToken token = default) - { - return _cache.GetStringAsync(WrapKey(key), token); - } - public void Remove(string key) { _cache.Remove(WrapKey(key)); } - public void RemoveLater(string key, TimeSpan expireTimeSpan) - { - var value = _cache.GetString(WrapKey(key)); - if (!string.IsNullOrEmpty(value)) - { - _cache.SetString(WrapKey(key), value, new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = expireTimeSpan - }); - } - } - - /// - /// 閲嶆柊璁剧疆杩囨湡鏃堕棿 TODO锛氱湅鐪嬫湁娌℃湁鍏朵粬浠呰闂竴娆$紦瀛樼殑鏂瑰紡 - /// - public async Task RemoveLaterAsync(string key, TimeSpan expireTimeSpan, CancellationToken token = default) - { - var value = await _cache.GetStringAsync(WrapKey(key), token); - if (!string.IsNullOrEmpty(value)) - { - await _cache.SetStringAsync(WrapKey(key), value, new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = expireTimeSpan - }); - } - } - - public Task RemoveAsync(string key, CancellationToken token = default(CancellationToken)) - { - return _cache.RemoveAsync(key, token); - } - - /// - /// 缂撳瓨楠岃瘉鐮 - /// - public void Set(string key, string value, TimeSpan expireTimeSpan) + public void Set(string key, string value, DateTimeOffset absoluteExpiration) { _cache.SetString(WrapKey(key), value, new DistributedCacheEntryOptions { - SlidingExpiration = expireTimeSpan + AbsoluteExpiration = absoluteExpiration }); } - - /// - /// 缂撳瓨楠岃瘉鐮 - /// - public Task SetAsync(string key, string value, TimeSpan expireTimeSpan, CancellationToken token = default) - { - return _cache.SetStringAsync(WrapKey(key), value, new DistributedCacheEntryOptions - { - SlidingExpiration = expireTimeSpan - }, token); - } } } \ No newline at end of file diff --git a/Lazy.Captcha.Core/Storage/IStorage.cs b/Lazy.Captcha.Core/Storage/IStorage.cs index 4940440..2752285 100644 --- a/Lazy.Captcha.Core/Storage/IStorage.cs +++ b/Lazy.Captcha.Core/Storage/IStorage.cs @@ -1,25 +1,13 @@ 锘縰sing System; -using System.Threading; -using System.Threading.Tasks; namespace Lazy.Captcha.Core.Storage { public interface IStorage { - void Set(string key, string value, TimeSpan expireTimeSpan); + void Set(string key, string value, DateTimeOffset absoluteExpiration); string Get(string key); void Remove(string key); - - Task GetAsync(string key, CancellationToken token = default); - - Task RemoveAsync(string key, CancellationToken token = default); - - Task SetAsync(string key, string value, TimeSpan expireTimeSpan, CancellationToken token = default); - - Task RemoveLaterAsync(string key, TimeSpan expireTimeSpan, CancellationToken token = default); - - void RemoveLater(string key, TimeSpan expireTimeSpan); } } \ No newline at end of file diff --git a/Lazy.Captcha.Test/Demo1.cs b/Lazy.Captcha.Test/Demo1.cs deleted file mode 100644 index 726eeb6..0000000 --- a/Lazy.Captcha.Test/Demo1.cs +++ /dev/null @@ -1,101 +0,0 @@ -锘縰sing SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lazy.Captcha.Test -{ - public static class Demo1 - { - public static void Run() - { - System.IO.Directory.CreateDirectory("output"); - - using (var img = Image.Load("inputs/fb.jpg")) - { - using (var destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 20))) - { - destRound.Save("output/fb.png"); - } - } - } - - private static IImageProcessingContext ConvertToAvatar(this IImageProcessingContext processingContext, Size size, float cornerRadius) - { - return processingContext.Resize(new ResizeOptions - { - Size = size, - Mode = ResizeMode.Crop - }).ApplyRoundedCorners(cornerRadius); - } - - // This method can be seen as an inline implementation of an `IImageProcessor`: - // (The combination of `IImageOperations.Apply()` + this could be replaced with an `IImageProcessor`) - private static IImageProcessingContext ApplyRoundedCorners(this IImageProcessingContext ctx, float cornerRadius) - { - Size size = ctx.GetCurrentSize(); - IPathCollection corners = BuildCorners(size.Width, size.Height, cornerRadius); - - //clear Both the color and the alpha of the destination are cleared. Neither the source nor the destination are used(except for destinations size and other meta - data which is always preserved. - //src The source is copied to the destination.The destination is not used as input, though it is cleared. - //dst The destination is left untouched. The source image is completely ignored. - //src - over The source is composited over the destination. this is the default alpha blending compose method, when neither the compose setting is set, nor is set in the image meta - data. - //dst - over The destination is composited over the source and the result replaces the destination. - //src -in The part of the source lying inside of the destination replaces the destination. - //dst -in The part of the destination lying inside of the source replaces the destination.Areas not overlaid are cleared. - //src -out The part of the source lying outside of the destination replaces the destination. - //dst -out The part of the destination lying outside of the source replaces the destination. - //src - atop The part of the source lying inside of the destination is composited onto the destination. - //dst - atop The part of the destination lying inside of the source is composited over the source and replaces the destination.Areas not overlaid are cleared. - //xor The part of the source that lies outside of the destination is combined with the part of the destination that lies outside of the source.Source or Destination, but not both. - // 1. 浜岄変竴 src, dst - // 2. 浜岄変竴锛屼絾鍙彇閮ㄥ垎 src - in(src鍐呴儴)锛宒st -in锛宻rc -out锛宒st -out - // 3. 浜岄変竴锛屼絾鍙彇閲嶅彔閮ㄥ垎 鍙栧嚭鐨勯儴鍒嗚鐩栧湪Dst src - atop dst - atop - // 4. 涓よ呭彔鍔 src - over dst - over - ctx.SetGraphicsOptions(new GraphicsOptions() - { - Antialias = true, - AlphaCompositionMode = PixelAlphaCompositionMode.DestOut // enforces that any part of this shape that has color is punched out of the background - }); - - // mutating in here as we already have a cloned original - // use any color(not Transparent), so the corners will be clipped - foreach (var c in corners) - { - ctx = ctx.Fill(Color.Red, c); - } - - //ctx.Fill(Color.Red, new Star(x: 100.0f, y: 100.0f, prongs: 5, innerRadii: 20.0f, outerRadii: 30.0f)); - - return ctx; - } - - private static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius) - { - // first create a square - var rect = new RectangularPolygon(-0.5f, -0.5f, cornerRadius, cornerRadius); - - // then cut out of the square a circle so we are left with a corner - IPath cornerTopLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius)); - - // corner is now a corner shape positions top left - //lets make 3 more positioned correctly, we can do that by translating the original around the center of the image - - float rightPos = imageWidth - cornerTopLeft.Bounds.Width + 1; - float bottomPos = imageHeight - cornerTopLeft.Bounds.Height + 1; - - // move it across the width of the image - the width of the shape - IPath cornerTopRight = cornerTopLeft.RotateDegree(90).Translate(rightPos, 0); - IPath cornerBottomLeft = cornerTopLeft.RotateDegree(-90).Translate(0, bottomPos); - IPath cornerBottomRight = cornerTopLeft.RotateDegree(180).Translate(rightPos, bottomPos); - - return new PathCollection(cornerTopLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight); - } - } -} diff --git a/Lazy.Captcha.Test/Demo2.cs b/Lazy.Captcha.Test/Demo2.cs deleted file mode 100644 index dc7f1c7..0000000 --- a/Lazy.Captcha.Test/Demo2.cs +++ /dev/null @@ -1,46 +0,0 @@ -锘縰sing SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.Processing; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lazy.Captcha.Test -{ - public static class Demo2 - { - public static void Run() - { - System.IO.Directory.CreateDirectory("output"); - - using (Image image = Image.Load("inputs/fb.jpg")) - { - var outerRadii = Math.Min(image.Width, image.Height) / 2; - var star = new Star(new PointF(image.Width / 2, image.Height / 2), 5, outerRadii / 2, outerRadii); - - // we want to clone out our source image so we can apply - // various effects to it without mutating the original yet. - using (var clone = image.Clone(p => - { - p.GaussianBlur(15); // apply the effect here you and inside the shape - })) - { - // crop the cloned down to just the size of the shape (this is due to the way ImageBrush works) - clone.Mutate(x => x.Crop((Rectangle)star.Bounds)); - - // use an image brush to apply section of cloned image as the source for filling the shape - var brush = new ImageBrush(clone); - - // now fill the shape with the image brush containing the portion of - // cloned image with the effects applied - image.Mutate(c => c.Fill(brush, star)); - } - - image.Save("output/fb.png"); - } - } - } -} diff --git a/Lazy.Captcha.Test/Demo3.cs b/Lazy.Captcha.Test/Demo3.cs deleted file mode 100644 index 51ba0a5..0000000 --- a/Lazy.Captcha.Test/Demo3.cs +++ /dev/null @@ -1,164 +0,0 @@ -锘縰sing SixLabors.Fonts; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.Processing; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lazy.Captcha.Test -{ - public static class Demo3 - { - const string LongText = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec aliquet lorem at magna mollis, non semper erat aliquet. In leo tellus, sollicitudin non eleifend et, luctus vel magna. Proin at lacinia tortor, malesuada molestie nisl. Quisque mattis dui quis eros ultricies, quis faucibus turpis dapibus. Donec urna ipsum, dignissim eget condimentum at, condimentum non magna. Donec non urna sit amet lectus tincidunt interdum vitae vitae leo. Aliquam in nisl accumsan, feugiat ipsum condimentum, scelerisque diam. Vivamus quam diam, rhoncus ut semper eget, gravida in metus. -Nullam quis malesuada metus. In hac habitasse platea dictumst. Aliquam faucibus eget eros nec vulputate. Quisque sed dolor lacus. Proin non dolor vitae massa rhoncus vestibulum non a arcu. Morbi mollis, arcu id pretium dictum, augue dui cursus eros, eu pharetra arcu ante non lectus. Integer quis tellus ipsum. Integer feugiat augue id tempus rutrum. Ut eget interdum leo, id fermentum lacus. Morbi euismod, mi at tempus finibus, ante risus ornare eros, eu ultrices ipsum dolor vitae risus. Mauris molestie pretium massa vitae maximus. Fusce ut egestas ex, vitae semper nulla. Proin pretium elit libero, et interdum enim molestie ac. -Pellentesque fermentum vitae lacus non aliquet. Sed nulla ipsum, hendrerit sit amet vulputate varius, volutpat eget est. Pellentesque eget ante erat. Vestibulum venenatis ex quis pretium sagittis. Etiam vel nibh sit amet leo gravida efficitur. In hac habitasse platea dictumst. Nullam lobortis euismod sem dapibus aliquam. Proin accumsan velit a magna gravida condimentum. Nam non massa ac nibh viverra rutrum. Phasellus elit tortor, malesuada et purus nec, placerat mattis neque. Proin auctor risus vel libero ultrices, id fringilla erat facilisis. Donec rutrum, enim sit amet faucibus viverra, velit tellus aliquam tellus, et tempus tellus diam sed dui. Integer fringilla convallis nisl venenatis elementum. Sed volutpat massa ut mauris accumsan, mollis finibus tortor pretium."; - const string LongText1 = "abc"; - - - public static void Run() - { - System.IO.Directory.CreateDirectory("output"); - using (var img = Image.Load("inputs/fb.jpg")) - { - // For production application we would recommend you create a FontCollection - // singleton and manually install the ttf fonts yourself as using SystemFonts - // can be expensive and you risk font existing or not existing on a deployment - // by deployment basis. - Font font = SystemFonts.CreateFont("Arial", 10); // for scaling water mark size is largely ignored. - - using (var img2 = img.Clone(ctx => ctx.ApplyScalingWaterMark(font, "A short piece of text", Color.HotPink, 5, false))) - { - img2.Save("output/simple.png"); - } - - - using (var img2 = img.Clone(ctx => ctx.ApplyScalingWaterMark(font, LongText, Color.HotPink, 5, true))) - { - img2.Save("output/wrapped.png"); - } - - // the original `img` object has not been altered at all. - } - } - - private static IImageProcessingContext ApplyScalingWaterMark(this IImageProcessingContext processingContext, - Font font, - string text, - Color color, - float padding, - bool wordwrap) - { - if (wordwrap) - { - return processingContext.ApplyScalingWaterMarkWordWrap(font, text, color, padding); - } - else - { - return processingContext.ApplyScalingWaterMarkSimple(font, text, color, padding); - } - } - - private static IImageProcessingContext ApplyScalingWaterMarkSimple(this IImageProcessingContext processingContext, - Font font, - string text, - Color color, - float padding) - { - Size imgSize = processingContext.GetCurrentSize(); - - float targetWidth = imgSize.Width - (padding * 2); - float targetHeight = imgSize.Height - (padding * 2); - - // measure the text size - FontRectangle size = TextMeasurer.Measure(text, new RendererOptions(font)); - - //find out how much we need to scale the text to fill the space (up or down) - float scalingFactor = Math.Min(imgSize.Width / size.Width, imgSize.Height / size.Height); - - //create a new font - Font scaledFont = new Font(font, scalingFactor * font.Size); - - var center = new PointF(imgSize.Width / 2, imgSize.Height / 2); - var textGraphicOptions = new DrawingOptions() - { - TextOptions = { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center - } - }; - return processingContext.DrawText(textGraphicOptions, text, scaledFont, color, center); - } - - private static IImageProcessingContext ApplyScalingWaterMarkWordWrap(this IImageProcessingContext processingContext, - Font font, - string text, - Color color, - float padding) - { - Size imgSize = processingContext.GetCurrentSize(); - float targetWidth = imgSize.Width - (padding * 2); - float targetHeight = imgSize.Height - (padding * 2); - - float targetMinHeight = imgSize.Height - (padding * 3); // must be with in a margin width of the target height - - // now we are working i 2 dimensions at once and can't just scale because it will cause the text to - // reflow we need to just try multiple times - - var scaledFont = font; - FontRectangle s = new FontRectangle(0, 0, float.MaxValue, float.MaxValue); - - float scaleFactor = (scaledFont.Size / 2); // every time we change direction we half this size - int trapCount = (int)scaledFont.Size * 2; - if (trapCount < 10) - { - trapCount = 10; - } - - bool isTooSmall = false; - - while ((s.Height > targetHeight || s.Height < targetMinHeight) && trapCount > 0) - { - if (s.Height > targetHeight) - { - if (isTooSmall) - { - scaleFactor = scaleFactor / 2; - } - - scaledFont = new Font(scaledFont, scaledFont.Size - scaleFactor); - isTooSmall = false; - } - - if (s.Height < targetMinHeight) - { - if (!isTooSmall) - { - scaleFactor = scaleFactor / 2; - } - scaledFont = new Font(scaledFont, scaledFont.Size + scaleFactor); - isTooSmall = true; - } - trapCount--; - - s = TextMeasurer.Measure(text, new RendererOptions(scaledFont) - { - WrappingWidth = targetWidth - }); - } - - var center = new PointF(padding, imgSize.Height / 2); - var textGraphicOptions = new DrawingOptions() - { - TextOptions = { - HorizontalAlignment = HorizontalAlignment.Left, - VerticalAlignment = VerticalAlignment.Center, - WrapTextWidth = targetWidth - } - }; - return processingContext.DrawText(textGraphicOptions, text, scaledFont, color, center); - } - } -} diff --git a/Lazy.Captcha.Test/Demo4.cs b/Lazy.Captcha.Test/Demo4.cs deleted file mode 100644 index ddff1e9..0000000 --- a/Lazy.Captcha.Test/Demo4.cs +++ /dev/null @@ -1,28 +0,0 @@ -锘縰sing SixLabors.ImageSharp; -using SixLabors.ImageSharp.Processing; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lazy.Captcha.Test -{ - public class Demo4 - { - public static void Run() - { - System.IO.Directory.CreateDirectory("output"); - - using (Image image = Image.Load("inputs/fb.jpg")) - { - image.Mutate(x => x - .Resize(image.Width / 2, image.Height / 2) - .Grayscale() - .BlackWhite()); - - image.Save("output/fb.png"); // Automatic encoder selected based on extension. - } - } - } -} diff --git a/Lazy.Captcha.Test/Demo5.cs b/Lazy.Captcha.Test/Demo5.cs deleted file mode 100644 index 4cb019d..0000000 --- a/Lazy.Captcha.Test/Demo5.cs +++ /dev/null @@ -1,135 +0,0 @@ -锘縰sing SixLabors.ImageSharp; -using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.PixelFormats; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lazy.Captcha.Test -{ - public class Demo5 - { - const int QrCodeSize = 25; - - static bool[,] GetQrPattern() - { - const bool o = true; - const bool _ = false; - return new[,] - { - { _, _, _, _, _, _, _, o, _, _, o, o, o, _, o, _, _, o, _, _, _, _, _, _, _ }, - { _, o, o, o, o, o, _, o, o, o, o, o, o, o, o, o, o, o, _, o, o, o, o, o, _ }, - { _, o, _, _, _, o, _, o, _, o, o, _, _, _, o, _, _, o, _, o, _, _, _, o, _ }, - { _, o, _, _, _, o, _, o, _, _, o, _, o, _, _, _, o, o, _, o, _, _, _, o, _ }, - { _, o, _, _, _, o, _, o, _, _, _, _, o, o, _, o, _, o, _, o, _, _, _, o, _ }, - { _, o, o, o, o, o, _, o, o, _, o, o, _, o, _, o, o, o, _, o, o, o, o, o, _ }, - { _, _, _, _, _, _, _, o, _, o, _, o, _, o, _, o, _, o, _, _, _, _, _, _, _ }, - { o, o, o, o, o, o, o, o, o, _, o, _, o, o, _, _, o, o, o, o, o, o, o, o, o }, - { _, _, _, _, o, o, _, o, _, o, o, o, o, _, _, o, o, _, o, o, _, _, _, o, _ }, - { _, _, o, _, o, o, o, _, _, _, o, o, o, o, _, o, o, o, o, _, o, o, o, _, o }, - { o, o, o, o, _, o, _, _, _, o, o, o, o, _, _, o, _, _, _, o, o, o, o, o, o }, - { o, _, o, o, o, _, o, o, o, o, o, _, _, _, o, _, o, _, o, _, o, _, _, o, o }, - { o, _, o, o, o, o, _, _, o, _, o, _, o, _, _, o, o, _, _, o, _, o, _, _, _ }, - { o, _, o, _, o, o, o, o, _, o, _, _, o, o, o, _, o, o, _, _, _, o, o, o, _ }, - { o, _, o, o, o, _, _, _, o, _, _, o, _, o, o, o, o, _, o, o, _, o, _, _, o }, - { _, o, _, o, _, o, o, o, _, o, o, o, _, o, o, _, o, o, _, _, _, o, o, o, _ }, - { o, o, _, o, o, o, _, o, o, o, _, _, o, o, o, _, _, _, _, _, _, _, _, _, _ }, - { o, o, o, o, o, o, o, o, _, o, _, o, _, o, _, _, _, o, o, o, _, o, _, o, _ }, - { _, _, _, _, _, _, _, o, o, o, o, _, _, _, o, o, _, o, _, o, _, o, _, _, _ }, - { _, o, o, o, o, o, _, o, o, o, _, o, _, o, _, _, _, o, o, o, _, o, o, _, _ }, - { _, o, _, _, _, o, _, o, o, _, _, _, _, _, o, o, _, _, _, _, _, _, o, _, o }, - { _, o, _, _, _, o, _, o, _, o, o, o, _, _, o, _, o, o, _, o, _, _, _, _, _ }, - { _, o, _, _, _, o, _, o, _, _, _, _, _, _, o, _, _, _, _, o, _, o, _, _, o }, - { _, o, o, o, o, o, _, o, _, o, _, o, o, o, o, o, o, _, _, o, _, o, _, o, o }, - { _, _, _, _, _, _, _, o, _, _, o, o, _, o, _, o, o, o, o, _, _, _, _, _, _ }, - }; - } - - public static void Run() - { - - bool[,] pattern = GetQrPattern(); - - // L8 is a grayscale pixel format storing a single 8-bit (1 byte) channel of luminance per pixel. - // Make sure to Dispose() the image in your app! We do it by a using statement in this example: - using Image image = RenderQrCodeToImage(pattern, 10); - - string fileName = Path.Combine(Directory.GetCurrentDirectory(), "qr.png"); - - // Store the result as a grayscale 1 bit per pixel png for maximum compression: - image.SaveAsPng(fileName, new PngEncoder() - { - BitDepth = PngBitDepth.Bit1, - ColorType = PngColorType.Grayscale - }); - Console.WriteLine($"Saved to: {fileName}"); - } - - // ImageSharp 2.0 will break this method: https://github.com/SixLabors/ImageSharp/issues/1739 - // We will update the example after the release. See ImageSharp 2.0 variant in comments. - static Image RenderQrCodeToImage(bool[,] pattern, int pixelSize) - { - int imageSize = pixelSize * QrCodeSize; - Image image = new Image(imageSize, imageSize); - - L8 black = new L8(0); - L8 white = new L8(255); - - // Scan the QR pattern row-by-row - for (int yQr = 0; yQr < QrCodeSize; yQr++) - { - // Fill 'pixelSize' number image rows that correspond to the current QR pattern row: - for (int y = yQr * pixelSize; y < (yQr + 1) * pixelSize; y++) - { - // Get a Span of pixels for the current image row: - //Span pixelRow = image.GetPixelRowSpan(y); - image.DangerousTryGetSinglePixelMemory(out Memory memoryL8); - Span pixelRow = memoryL8.Span; - - // Loop through the values for the current QR pattern row: - for (int xQr = 0; xQr < QrCodeSize; xQr++) - { - L8 color = pattern[xQr, yQr] ? white : black; - - // Fill 'pixelSize' number of image pixels corresponding to the current QR pattern value: - for (int x = xQr * pixelSize; x < (xQr + 1) * pixelSize; x++) - { - pixelRow[x] = color; - } - } - } - } - - // ImageSharp 2.0 variant: - // image.ProcessPixelRows(pixelAccessor => - // { - // // Scan the QR pattern row-by-row - // for (int yQr = 0; yQr < QrCodeSize; yQr++) - // { - // // Fill 'pixelSize' number image rows that correspond to the current QR pattern row: - // for (int y = yQr * pixelSize; y < (yQr + 1) * pixelSize; y++) - // { - // // Get a Span of pixels for the current image row: - // Span pixelRow = pixelAccessor.GetRowSpan(y); - // - // // Loop through the values for the current QR pattern row: - // for (int xQr = 0; xQr < QrCodeSize; xQr++) - // { - // L8 color = pattern[xQr, yQr] ? white : black; - // - // // Fill 'pixelSize' number of image pixels corresponding to the current QR pattern value: - // for (int x = xQr * pixelSize; x < (xQr + 1) * pixelSize; x++) - // { - // pixelRow[x] = color; - // } - // } - // } - // } - // }); - - return image; - } - } -} diff --git a/Lazy.Captcha.Test/Demo6.cs b/Lazy.Captcha.Test/Demo6.cs deleted file mode 100644 index a8178b2..0000000 --- a/Lazy.Captcha.Test/Demo6.cs +++ /dev/null @@ -1,63 +0,0 @@ -锘縰sing SixLabors.Fonts; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lazy.Captcha.Test -{ - public class Demo6 - { - public static void Run() - { - System.IO.Directory.CreateDirectory("output"); - using (Image img = new Image(1500, 500)) - { - PathBuilder pathBuilder = new PathBuilder(); - pathBuilder.SetOrigin(new PointF(500, 0)); - pathBuilder.AddBezier(new PointF(50, 450), new PointF(200, 50), new PointF(300, 50), new PointF(450, 450)); - // add more complex paths and shapes here. - - IPath path = pathBuilder.Build(); - - // For production application we would recomend you create a FontCollection - // singleton and manually install the ttf fonts yourself as using SystemFonts - // can be expensive and you risk font existing or not existing on a deployment - // by deployment basis. - var font = SystemFonts.CreateFont("Arial", 39, FontStyle.Regular); - - string text = "Hello World Hello World Hello World Hello World Hello World"; - var textGraphicsOptions = new DrawingOptions() // draw the text along the path wrapping at the end of the line - { - TextOptions = - { - WrapTextWidth = path.Bounds.Width - } - }; - - // lets generate the text as a set of vectors drawn along the path - var glyphs = TextBuilder.GenerateGlyphs(text, path, new RendererOptions(font, textGraphicsOptions.TextOptions.DpiX, textGraphicsOptions.TextOptions.DpiY) - { - HorizontalAlignment = textGraphicsOptions.TextOptions.HorizontalAlignment, - TabWidth = textGraphicsOptions.TextOptions.TabWidth, - VerticalAlignment = textGraphicsOptions.TextOptions.VerticalAlignment, - WrappingWidth = textGraphicsOptions.TextOptions.WrapTextWidth, - ApplyKerning = textGraphicsOptions.TextOptions.ApplyKerning - }); - - img.Mutate(ctx => ctx - .Fill(Color.White) // white background image - .Draw(Color.Gray, 3, path) // draw the path so we can see what the text is supposed to be following - .Fill(Color.Black, glyphs)); - - img.Save("output/wordart.png"); - } - } - } -} diff --git a/Lazy.Captcha.Test/Demo7.cs b/Lazy.Captcha.Test/Demo7.cs deleted file mode 100644 index c54f44e..0000000 --- a/Lazy.Captcha.Test/Demo7.cs +++ /dev/null @@ -1,49 +0,0 @@ -锘縰sing SixLabors.ImageSharp; -using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.PixelFormats; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lazy.Captcha.Test -{ - public class Demo7 - { - public static void Run() - { - const int width = 100; - const int height = 100; - - // Delay between frames in (1/100) of a second. - const int frameDelay = 100; - - // For demonstration: use images with different colors. - Color[] colors = { - Color.Green, - Color.Red - }; - - // Create empty image. - using Image gif = new(width, height, Color.Blue); - gif.Metadata.GetGifMetadata().RepeatCount = 0; - - for (int i = 0; i < colors.Length; i++) - { - // Create a color image, which will be added to the gif. - using Image image = new(width, height, colors[i]); - - // Set the duration of the frame delay. - GifFrameMetadata metadata1 = image.Frames.RootFrame.Metadata.GetGifMetadata(); - metadata1.FrameDelay = frameDelay; - - // Add the color image to the gif. - gif.Frames.AddFrame(image.Frames.RootFrame); - } - - // Save the final result. - gif.SaveAsGif("a.gif"); - } - } -} diff --git a/Lazy.Captcha.Test/Demo8.cs b/Lazy.Captcha.Test/Demo8.cs deleted file mode 100644 index ef5c342..0000000 --- a/Lazy.Captcha.Test/Demo8.cs +++ /dev/null @@ -1,76 +0,0 @@ -锘縰sing SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing; -using SixLabors.ImageSharp.Drawing.Processing; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lazy.Captcha.Test -{ - public class Demo8 - { - public static void Run() - { - System.IO.Directory.CreateDirectory("output"); - - using (var image = Image.Load("inputs/fb.jpg")) - { - var outerRadii = Math.Min(image.Width, image.Height) / 2; - var star = new Star(new PointF(image.Width / 2, image.Height / 2), 5, outerRadii / 2, outerRadii); - - image.Mutate(x => x.DrawPolygon(Pens.Solid(Color.White, 2), star.Points.ToArray())); - image.Mutate(x => x.FillPolygon(Color.ParseHex("#00000088"), star.Points.ToArray())); - image.Save("cc2.png"); - - //using (var clone = image.Clone(p => - //{ - // p.GaussianBlur(15); - //})) - //{ - // // 瑁佸壀鍖哄煙 - // var rect = new RectangularPolygon(-0.0f, -0.0f, 200, 200); - // clone.Mutate(c => c.Crop((Rectangle)star.Bounds)); - - // clone.Save("cc1.png"); - - // var brush = new ImageBrush(clone); - - // // now fill the shape with the image brush containing the portion of - // // cloned image with the effects applied - // image.Mutate(c => c.Fill(brush, star)); - - // var options = new DrawingOptions() - // { - // GraphicsOptions = new GraphicsOptions - // { - // BlendPercentage = 0.5f - // } - // }; - // image.Mutate(x => x.Draw(options, Color.White, 1, star)); - //} - - //DrawingOptions options = new() - //{ - // GraphicsOptions = new() - // { - // ColorBlendingMode = PixelColorBlendingMode.Multiply, - // } - //}; - - //IBrush brush = Brushes.Horizontal(Color.Red, Color.Blue); - //IPen pen = Pens.DashDot(Color.Green, 5); - //IPath yourPolygon = new Star(x: 100.0f, y: 100.0f, prongs: 5, innerRadii: 20.0f, outerRadii: 30.0f); - - //// Draws a star with horizontal red and blue hatching with a dash dot pattern outline. - //image.Mutate(x => x.Fill(options, brush, yourPolygon) - // .Draw(options, pen, yourPolygon)); - - //image.Save("cc.png"); - } - } - } -} diff --git a/Lazy.Captcha.Test/Lazy.Captcha.Test.csproj b/Lazy.Captcha.Test/Lazy.Captcha.Test.csproj deleted file mode 100644 index 26e60bb..0000000 --- a/Lazy.Captcha.Test/Lazy.Captcha.Test.csproj +++ /dev/null @@ -1,20 +0,0 @@ -锘 - - - Exe - net6.0 - enable - enable - - - - - - - - - Always - - - - diff --git a/Lazy.Captcha.Test/Program.cs b/Lazy.Captcha.Test/Program.cs deleted file mode 100644 index ddf6b15..0000000 --- a/Lazy.Captcha.Test/Program.cs +++ /dev/null @@ -1,13 +0,0 @@ -锘// See https://aka.ms/new-console-template for more information -using Lazy.Captcha.Core; -using Lazy.Captcha.Core.Generator; -using Lazy.Captcha.Core.Generator.Code; -using Lazy.Captcha.Test; -using SixLabors.ImageSharp; -using System.Diagnostics; - -Console.WriteLine("Hello, World!"); - - -Demo8.Run(); - diff --git a/Lazy.Captcha.Test/inputs/fb.jpg b/Lazy.Captcha.Test/inputs/fb.jpg deleted file mode 100644 index 305294f47eee72bcc7fe5ec3fce0d33d39d0b293..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15787 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 [HttpGet("validate")] - public Task Validate(string id, string code) + public bool Validate(string id, string code) { - return _captcha.ValidateAsync(id, code); + return _captcha.Validate(id, code); } /// + /// 涓涓獙璇佺爜澶氭鏍¢獙锛坔ttps://gitee.com/pojianbing/lazy-captcha/issues/I4XHGM锛 /// 婕旂ず鏃朵娇鐢℉ttpGet浼犲弬鏂逛究锛岃繖閲屼粎鍋氳繑鍥炲鐞 /// - [HttpGet("validate_remove_later")] - public Task ValidateAndRemoveLater(string id, string code) + [HttpGet("validate2")] + public bool Validate2(string id, string code) { - // 涓轰簡婕旂ず锛岃繖閲屼粎鍋氳繑鍥炲鐞 涓庝笂闈㈡柟娉曚竴鏍凤紝浣嗘槸杩欓噷鏍¢獙鏃讹紝璁茶繃鏈熸椂闂磋缃负10绉掑悗锛屽鏌ヤ簡涓娆★紝鎬ц兘涓嶅鐩存帴鍒犻櫎 - return _captcha.ValidateAsync(id, code, TimeSpan.FromSeconds(10)); + return _captcha.Validate(id, code, false); } } } \ No newline at end of file diff --git a/Lazy.Captcha.Web/appsettings.json b/Lazy.Captcha.Web/appsettings.json index 3ace6bd..3a5c3e4 100644 --- a/Lazy.Captcha.Web/appsettings.json +++ b/Lazy.Captcha.Web/appsettings.json @@ -20,7 +20,7 @@ "InterferenceLineCount": 4, // 骞叉壈绾挎暟閲 "FontFamily": "kaiti", // 鍖呭惈actionj,epilog,fresnel,headache,lexo,prefix,progbot,ransom,robot,scandal,kaiti "FrameDelay": 15, // 姣忓抚寤惰繜,Animation=true鏃舵湁鏁, 榛樿30 - "BackgroundColor": "#ffff00" // 鏍煎紡: rgb, rgba, rrggbb, or rrggbbaa format to match web syntax, 榛樿#fff + "BackgroundColor": "#ffffff" // 鏍煎紡: rgb, rgba, rrggbb, or rrggbbaa format to match web syntax, 榛樿#fff } } } \ No newline at end of file diff --git a/LazyCaptcha.sln b/LazyCaptcha.sln index c5d601e..12fc604 100644 --- a/LazyCaptcha.sln +++ b/LazyCaptcha.sln @@ -3,15 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32112.339 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lazy.Captcha.Test", "Lazy.Captcha.Test\Lazy.Captcha.Test.csproj", "{78B1B0D1-0ED3-465E-BAC9-A663AE5A3D4E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lazy.Captcha.Core", "Lazy.Captcha.Core\Lazy.Captcha.Core.csproj", "{B640C86B-87E3-4CBE-94A9-2CA3AC704A08}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lazy.Captcha.Web", "Lazy.Captcha.Web\Lazy.Captcha.Web.csproj", "{18C83A51-3ECB-44FE-8ED4-62F59967487B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lazy.Captcha.Redis", "Lazy.Captcha.Redis\Lazy.Captcha.Redis.csproj", "{EC32628E-195E-4277-8026-EFAFA571432A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lazy.Captcha.xUnit", "Lazy.Captcha.xUnit\Lazy.Captcha.xUnit.csproj", "{4E63EE78-CE03-4D89-BF86-7AF2247082F2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lazy.Captcha.xUnit", "Lazy.Captcha.xUnit\Lazy.Captcha.xUnit.csproj", "{4E63EE78-CE03-4D89-BF86-7AF2247082F2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -19,10 +17,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {78B1B0D1-0ED3-465E-BAC9-A663AE5A3D4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78B1B0D1-0ED3-465E-BAC9-A663AE5A3D4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78B1B0D1-0ED3-465E-BAC9-A663AE5A3D4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78B1B0D1-0ED3-465E-BAC9-A663AE5A3D4E}.Release|Any CPU.Build.0 = Release|Any CPU {B640C86B-87E3-4CBE-94A9-2CA3AC704A08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B640C86B-87E3-4CBE-94A9-2CA3AC704A08}.Debug|Any CPU.Build.0 = Debug|Any CPU {B640C86B-87E3-4CBE-94A9-2CA3AC704A08}.Release|Any CPU.ActiveCfg = Release|Any CPU -- Gitee