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