diff --git a/Lazy.Captcha.Core/CaptchaOptions.cs b/Lazy.Captcha.Core/CaptchaOptions.cs index e970eb0c2c23923298d546d252775b576c62b945..c2f9ca465bdbbc479ff111c64195a489cb50f810 100644 --- a/Lazy.Captcha.Core/CaptchaOptions.cs +++ b/Lazy.Captcha.Core/CaptchaOptions.cs @@ -57,6 +57,11 @@ namespace Lazy.Captcha.Core /// public bool IgnoreCase { get; set; } = true; + /// + /// 是否开启开发者模式 + /// + public bool IsDevelopment { get; set; } = false; + /// /// 存储键前缀 /// diff --git a/Lazy.Captcha.Core/DefaultCaptcha.cs b/Lazy.Captcha.Core/DefaultCaptcha.cs index 942c00c1789b4f5ae010e986cc909d85d1d023b1..34b56d670d28e0ed5d8382c6d989e01b836ca395 100644 --- a/Lazy.Captcha.Core/DefaultCaptcha.cs +++ b/Lazy.Captcha.Core/DefaultCaptcha.cs @@ -35,7 +35,7 @@ namespace Lazy.Captcha.Core public CaptchaData Generate(string captchaId) { var (renderText, code) = _captchaCodeGenerator.Generate(_options.CodeLength); - var image = _captchaImageGenerator.Generate(renderText, _options.ImageOption); + var image = _captchaImageGenerator.Generate(renderText, _options.ImageOption, _options.IsDevelopment); _storage.Set(captchaId, code, TimeSpan.FromSeconds(_options.ExpirySeconds)); return new CaptchaData(captchaId, code, image); @@ -54,6 +54,8 @@ namespace Lazy.Captcha.Core /// public bool Validate(string captchaId, string code, TimeSpan? delay = null) { + if (_options.IsDevelopment) return true; + var val = _storage.Get(captchaId); var comparisonType = _options.IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture; var result = string.Equals(val, code, comparisonType); @@ -77,6 +79,8 @@ namespace Lazy.Captcha.Core /// public async Task ValidateAsync(string captchaId, string code, TimeSpan? delay = null, CancellationToken token = default) { + if (_options.IsDevelopment) return true; + var val = _storage.Get(captchaId); var comparisonType = _options.IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture; var result = string.Equals(val, code, comparisonType); diff --git a/Lazy.Captcha.Core/Generator/Image/DefaultCaptchaImageGenerator.cs b/Lazy.Captcha.Core/Generator/Image/DefaultCaptchaImageGenerator.cs index 0695f0bf8a96b27e1380282ca099b7332daa9613..a74fca1735ad095544df55f623faa7c7848777aa 100644 --- a/Lazy.Captcha.Core/Generator/Image/DefaultCaptchaImageGenerator.cs +++ b/Lazy.Captcha.Core/Generator/Image/DefaultCaptchaImageGenerator.cs @@ -25,13 +25,13 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 生成气泡图形描述 /// - /// - /// - /// - /// - /// - /// - /// + /// + /// + /// + /// + /// + /// + /// protected virtual List GenerateBubbleGraphicDescriptions(int width, int height, int count, int minRadius, int maxRadius, float thickness) { var result = new List(); @@ -57,8 +57,8 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 绘制多个气泡 /// - /// 上下文 - /// 气泡图形描述 + /// 上下文 + /// 气泡图形描述 protected virtual void DrawBubbles(IImageProcessingContext ctx, List graphicDescriptions) { graphicDescriptions.ForEach(gd => @@ -77,8 +77,8 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 绘制多个气泡 /// - /// 上下文 - /// 选项 + /// 上下文 + /// 选项 protected virtual void DrawBubbles(IImageProcessingContext ctx, CaptchaImageGeneratorOption option) { var graphicDescriptions = GenerateBubbleGraphicDescriptions(option.Width, option.Height, option.BubbleCount, option.BubbleMinRadius, option.BubbleMaxRadius, option.BubbleThickness); @@ -88,10 +88,10 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 生成干扰线图形描述 /// - /// 宽 - /// 高 - /// 数量 - /// 干扰线图形描述 + /// 宽 + /// 高 + /// 数量 + /// 干扰线图形描述 protected virtual List GenerateInterferenceLineGraphicDescriptions(int width, int height, int count) { var result = new List(); @@ -119,9 +119,9 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 绘制干扰线 /// - /// 上下文 - /// 验证码的宽 - /// 验证码的高 + /// 上下文 + /// 验证码的宽 + /// 验证码的高 protected virtual void DrawInterferenceLines(IImageProcessingContext ctx, List graphicDescriptions) { graphicDescriptions.ForEach(gd => @@ -140,8 +140,8 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 绘制干扰线 /// - /// 上下文 - /// option + /// 上下文 + /// option protected virtual void DrawInterferenceLines(IImageProcessingContext ctx, CaptchaImageGeneratorOption option) { var graphicDescriptions = GenerateInterferenceLineGraphicDescriptions(option.Width, option.Height, option.InterferenceLineCount); @@ -151,11 +151,11 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 生成干扰线图形描述 /// - /// 宽 - /// 高 - /// 文本 - /// 字体 - /// 文本图形描述 + /// 宽 + /// 高 + /// 文本 + /// 字体 + /// 文本图形描述 protected virtual List GenerateTextGraphicDescriptions(int width, int height, string text, Font font) { var result = new List(); @@ -179,8 +179,8 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 绘制干扰线 /// - /// 上下文 - /// 图形描述 + /// 上下文 + /// 图形描述 protected virtual void DrawTexts(IImageProcessingContext ctx, List graphicDescriptions) { graphicDescriptions.ForEach(gd => @@ -199,9 +199,9 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 绘制文本 /// - /// 上下文 - /// - /// + /// 上下文 + /// + /// protected virtual void DrawTexts(IImageProcessingContext ctx, string text, CaptchaImageGeneratorOption option) { var graphicDescriptions = GenerateTextGraphicDescriptions(option.Width, option.Height, text, option.Font); @@ -211,11 +211,11 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 测算文本绘制位置 /// - /// 验证码宽度 - /// 验证码高度 - /// 要绘制的文本 - /// 文本所应用的字体 - /// 返回每个字符的位置 + /// 验证码宽度 + /// 验证码高度 + /// 要绘制的文本 + /// 文本所应用的字体 + /// 返回每个字符的位置 public virtual List MeasureTextPositions(int width, int height, string text, Font font) { var result = new List(); @@ -256,9 +256,9 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 生成 /// - /// - /// - /// + /// + /// + /// public virtual byte[] Generate(string text, CaptchaImageGeneratorOption option) { if (option.Animation) @@ -271,6 +271,19 @@ namespace Lazy.Captcha.Core.Generator.Image } } + public byte[] Generate(string text, CaptchaImageGeneratorOption option, bool isDevelopment) + { + if (!isDevelopment) + { + return Generate(text, option); + } + else + { + option.BackgroundColor = Color.Gray; + return Generate(text, option); + } + } + private byte[] GenerateNormal(string text, CaptchaImageGeneratorOption option) { using (Image img = new Image(option.Width, option.Height, option.BackgroundColor)) @@ -296,10 +309,10 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 计算透明度 /// - /// 帧索引 - /// 文字索引 - /// 验证码长度 - /// 文字的透明度 + /// 帧索引 + /// 文字索引 + /// 验证码长度 + /// 文字的透明度 private float GenerateBlendPercentage(int frameIndex, int textIndex, int len) { int num = frameIndex + textIndex; @@ -311,9 +324,9 @@ namespace Lazy.Captcha.Core.Generator.Image /// /// 生成动图 /// - /// - /// - /// + /// + /// + /// private byte[] GenerateAnimation(string text, CaptchaImageGeneratorOption option) { var texGraphicDescriptions = GenerateTextGraphicDescriptions(option.Width, option.Height, text, option.Font); @@ -376,4 +389,4 @@ namespace Lazy.Captcha.Core.Generator.Image } } } -} +} \ No newline at end of file diff --git a/Lazy.Captcha.Core/Generator/Image/ICaptchaImageGenerator.cs b/Lazy.Captcha.Core/Generator/Image/ICaptchaImageGenerator.cs index e8c9104f618447cade3d45ed8c51d9d6c3f94796..b96a614b2a619895226098d238918e646b838349 100644 --- a/Lazy.Captcha.Core/Generator/Image/ICaptchaImageGenerator.cs +++ b/Lazy.Captcha.Core/Generator/Image/ICaptchaImageGenerator.cs @@ -13,5 +13,7 @@ namespace Lazy.Captcha.Core.Generator.Image public interface ICaptchaImageGenerator { byte[] Generate(string text, CaptchaImageGeneratorOption option); + + byte[] Generate(string text, CaptchaImageGeneratorOption option, bool isDevelopment); } -} +} \ No newline at end of file diff --git a/Lazy.Captcha.Web/Lazy.Captcha.Web.csproj b/Lazy.Captcha.Web/Lazy.Captcha.Web.csproj index 5dd73191034c8f3102a0b4bf81aa1550e10dad0e..b246496ac6276586b2bb07e68bc8ce2cd1e7b519 100644 --- a/Lazy.Captcha.Web/Lazy.Captcha.Web.csproj +++ b/Lazy.Captcha.Web/Lazy.Captcha.Web.csproj @@ -18,4 +18,6 @@ + + diff --git a/Lazy.Captcha.Web/Program.cs b/Lazy.Captcha.Web/Program.cs index d3bc058c3bd0dc4b8cc34fb2114b2202cf29a9b4..d568f7d645932a9fcfef9b450f0585cd206dd3d9 100644 --- a/Lazy.Captcha.Web/Program.cs +++ b/Lazy.Captcha.Web/Program.cs @@ -26,6 +26,8 @@ builder.Services.AddCaptcha(builder.Configuration); // option.IgnoreCase = true; // ȽʱǷԴСд // option.StoreageKeyPrefix = ""; // 洢ǰ׺ +// option.IsDevelopment = false; // Ƿ񿪷ģʽ + // option.ImageOption.Animation = true; // Ƿö // option.ImageOption.FrameDelay = 30; // ÿ֡ӳ,Animation=trueʱЧ, Ĭ30 diff --git a/Lazy.Captcha.Web/appsettings.json b/Lazy.Captcha.Web/appsettings.json index 3ace6bd7dee9eb4ce19706015df62218e0d12abb..ff995f91540538bc9fab20e4d9a92d174b0bc1f7 100644 --- a/Lazy.Captcha.Web/appsettings.json +++ b/Lazy.Captcha.Web/appsettings.json @@ -6,6 +6,7 @@ "CaptchaType": 5, // 验证码类型 0 - 11 //"CodeLength": 4, // 验证码长度, 要放在CaptchaType设置后。 当类型为算术表达式时,长度代表操作的个数,不设置时默认为2。 "ExpirySeconds": 60, // 验证码过期秒数 + "IsDevelopment": false, // 是否开启开发模式 "IgnoreCase": true, // 比较时是否忽略大小写 "StoreageKeyPrefix": "", // 存储键前缀 "ImageOption": { diff --git a/LazyCaptcha.sln b/LazyCaptcha.sln index c5d601e3b21462802838f5a25ae6fdce3a48d4f0..d75d243f53e1e6ca7bf2a82bd206bade42881a22 100644 --- a/LazyCaptcha.sln +++ b/LazyCaptcha.sln @@ -11,7 +11,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lazy.Captcha.Web", "Lazy.Ca 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 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5CE8949E-41C7-4CC6-B9F4-82693212FC1C}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/README.md b/README.md index 9fc08522dd8080ca0602e3aea7c8321fd0805748..1b753f5f9314e37d503f8853f776e9533d5ea425 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ builder.Services.AddCaptcha(builder.Configuration); "CaptchaType": 5, // 验证码类型 "CodeLength": 4, // 验证码长度, 要放在CaptchaType设置后 当类型为算术表达式时,长度代表操作的个数 "ExpirySeconds": 60, // 验证码过期秒数 + "IsDevelopment": false, "IgnoreCase": true, // 比较时是否忽略大小写 "StoreageKeyPrefix": "", // 存储键前缀 "ImageOption": { @@ -121,6 +122,8 @@ builder.Services.AddCaptcha(builder.Configuration, option => option.IgnoreCase = true; // 比较时是否忽略大小写 option.StoreageKeyPrefix = ""; // 存储键前缀 + option.IsDevelopment = false; // 是否开发模式 + option.ImageOption.Animation = true; // 是否启用动画 option.ImageOption.FrameDelay = 30; // 每帧延迟,Animation=true时有效, 默认30