diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index dbf0fba..7801117 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,7 +16,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 6.0.x + dotnet-version: 8.0.x - name: Restore Lib run: dotnet restore ./Src diff --git a/README.md b/README.md index 5748a5f..bce8f9a 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,12 @@ [CaptchaN-DI-Microsoft-SvgUrl]: https://img.shields.io/nuget/v/CaptchaN.DI.Microsoft.svg [CaptchaN-DI-Microsoft-NugetUrl]: https://www.nuget.org/packages/CaptchaN.DI.Microsoft -![Image Demo](https://github.com/LeaFrock/CaptchaN/blob/main/Images/name.jpeg) +![Image Demo](https://raw.githubusercontent.com/LeaFrock/CaptchaN/main/Images/name.jpeg) Generate captcha images based on [ImageSharp][ImageSharpUrl] and .NET. >基于[ImageSharp][ImageSharpUrl]项目和.NET,生成图形验证码。 -[![.NET 6](https://img.shields.io/badge/.NET-6-brightgreen)][DotNetUrl] +[![.NET 8](https://img.shields.io/badge/.NET-8-brightgreen)][DotNetUrl] ![License](https://img.shields.io/badge/License-MIT-green) ## Packages |Nuget包 diff --git a/Samples/CaptchaN.WebApi/CaptchaN.WebApi.csproj b/Samples/CaptchaN.WebApi/CaptchaN.WebApi.csproj index c9495e4..a5a5a15 100644 --- a/Samples/CaptchaN.WebApi/CaptchaN.WebApi.csproj +++ b/Samples/CaptchaN.WebApi/CaptchaN.WebApi.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 enable diff --git a/Samples/CaptchaN.WebApi/Controllers/CaptchaController.cs b/Samples/CaptchaN.WebApi/Controllers/CaptchaController.cs deleted file mode 100644 index cf272d3..0000000 --- a/Samples/CaptchaN.WebApi/Controllers/CaptchaController.cs +++ /dev/null @@ -1,33 +0,0 @@ -using CaptchaN.Abstractions; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; - -namespace CaptchaN.WebApi.Controllers -{ - [ApiController] - [Route("[controller]")] - public class CaptchaController : ControllerBase - { - private readonly IPainter _painter; - private readonly ICodeTextGenerator _codeTextGenerator; - private readonly PainterOption _painterOption; - - public CaptchaController( - IOptions painterOpt, - ICodeTextGenerator codeTextGenerator, - IPainter painter) - { - _painterOption = painterOpt.Value; - _codeTextGenerator = codeTextGenerator; - _painter = painter; - } - - [HttpGet] - public async Task Get() - { - string codeText = _codeTextGenerator.Generate(4); - var image = await _painter.GenerateImageAsync(codeText, _painterOption); - return File(image, "image/jpeg; charset=UTF-8"); - } - } -} \ No newline at end of file diff --git a/Samples/CaptchaN.WebApi/Program.cs b/Samples/CaptchaN.WebApi/Program.cs index 8e22404..052b7a4 100644 --- a/Samples/CaptchaN.WebApi/Program.cs +++ b/Samples/CaptchaN.WebApi/Program.cs @@ -1,17 +1,22 @@ -namespace CaptchaN.WebApi +using CaptchaN.Abstractions; +using CaptchaN.Factories; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.Extensions.Options; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.Configure(builder.Configuration.GetSection("CaptchaN")); +builder.Services.AddCaptchaN() + //.UseFontRandomer(new SystemFontRandomerFactory()); + .UseFontRandomer(new DirectoryFontRandomerFactory() { FontDir = new(Path.Combine(builder.Environment.ContentRootPath, "Fonts")) }); + +var app = builder.Build(); + +app.MapGet("/captcha", async Task (IOptions painterOpt, ICodeTextGenerator codeTextGenerator, IPainter painter) => { - public class Program - { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } + var codeText = codeTextGenerator.Generate(4); + var image = await painter.GenerateImageAsync(codeText, painterOpt.Value); + return TypedResults.File(image, "image/jpeg; charset=UTF-8"); +}); - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } -} +app.Run(); \ No newline at end of file diff --git a/Samples/CaptchaN.WebApi/Properties/launchSettings.json b/Samples/CaptchaN.WebApi/Properties/launchSettings.json index b8b48b3..b032cb2 100644 --- a/Samples/CaptchaN.WebApi/Properties/launchSettings.json +++ b/Samples/CaptchaN.WebApi/Properties/launchSettings.json @@ -9,20 +9,12 @@ } }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "captcha", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, "CaptchaN.WebApi": { "commandName": "Project", - "dotnetRunMessages": "true", + "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "captcha", - "applicationUrl": "https://localhost:5001;http://localhost:5000", + "applicationUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/Samples/CaptchaN.WebApi/README.md b/Samples/CaptchaN.WebApi/README.md index 5cb8b80..3ba915f 100644 --- a/Samples/CaptchaN.WebApi/README.md +++ b/Samples/CaptchaN.WebApi/README.md @@ -1,4 +1,4 @@ # CaptchaN.WebApi -Before the first running, please create a directory called `Fonts` at the same level of `Controllers`, then put your font files `*.ttf` into `Fonts`. ->在第一次运行前,请先创建一个与`Controllers`同级的文件夹,命名为`Fonts`,然后将你的`*.ttf`格式字体文件放入其中。 +Before the first running, please create a directory called `Fonts` at the same level of `Program.cs`, then put your font files `*.ttf` into `Fonts`. +>在第一次运行前,请先创建一个与`Program.cs`同级的文件夹,命名为`Fonts`,然后将你的`*.ttf`格式字体文件放入其中。 diff --git a/Samples/CaptchaN.WebApi/Startup.cs b/Samples/CaptchaN.WebApi/Startup.cs deleted file mode 100644 index 5a1417e..0000000 --- a/Samples/CaptchaN.WebApi/Startup.cs +++ /dev/null @@ -1,50 +0,0 @@ -using CaptchaN.Abstractions; -using CaptchaN.Factories; - -namespace CaptchaN.WebApi -{ - public class Startup - { - public Startup(IConfiguration configuration, IWebHostEnvironment env) - { - Configuration = configuration; - HostEnvironment = env; - } - - public IConfiguration Configuration { get; } - - protected IWebHostEnvironment HostEnvironment { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddControllers(); - - services.Configure(Configuration.GetSection("CaptchaN")); - services.AddCaptchaN() - //.UseFontRandomer(new SystemFontRandomerFactory()); - .UseFontRandomer(new DirectoryFontRandomerFactory() { FontDir = new(Path.Combine(HostEnvironment.ContentRootPath, "Fonts")) }); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseStaticFiles(); - app.UseHttpsRedirection(); - - app.UseRouting(); - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - } -} \ No newline at end of file diff --git a/Src/CaptchaN.DI.Microsoft/CaptchaN.DI.Microsoft.csproj b/Src/CaptchaN.DI.Microsoft/CaptchaN.DI.Microsoft.csproj index c1dd674..0282c94 100644 --- a/Src/CaptchaN.DI.Microsoft/CaptchaN.DI.Microsoft.csproj +++ b/Src/CaptchaN.DI.Microsoft/CaptchaN.DI.Microsoft.csproj @@ -1,28 +1,36 @@  - net6.0 + net6.0;net8.0 enable - + latest CaptchaN.DI.Microsoft CaptchaN.DI.Microsoft LeaFrock - 1.1.0 + 3.0.0 CaptchaN.DI.Microsoft CaptchaN DI for .NET default container. - Copyright © LeaFrock 2022 + Copyright © LeaFrock 2023 MIT captcha;imagesharp https://github.com/LeaFrock/CaptchaN https://github.com/LeaFrock/CaptchaN.git git - Upgrade to ImageSharp 2.0 + Add support for .NET 8 false + README.md - - + + + + + + + + + diff --git a/Src/CaptchaN.DI.Microsoft/PainterBuilder.cs b/Src/CaptchaN.DI.Microsoft/PainterBuilder.cs index dede9d3..3a0ac21 100644 --- a/Src/CaptchaN.DI.Microsoft/PainterBuilder.cs +++ b/Src/CaptchaN.DI.Microsoft/PainterBuilder.cs @@ -36,10 +36,9 @@ public PainterBuilder UseFontRandomer() where T : class, IFontRandomer public PainterBuilder UseFontRandomer(IFontRandomerFactory fontRandomerFactory) { var fontRandomer = fontRandomerFactory.CreateFontRandomer(); - if (fontRandomer is null) - { - throw new NullReferenceException("Created FontRandomer is null."); - } + + ArgumentNullException.ThrowIfNull(fontRandomer); + _services.AddSingleton(fontRandomer); return this; } diff --git a/Src/CaptchaN/CaptchaN.csproj b/Src/CaptchaN/CaptchaN.csproj index 57ea874..f27ef61 100644 --- a/Src/CaptchaN/CaptchaN.csproj +++ b/Src/CaptchaN/CaptchaN.csproj @@ -1,27 +1,32 @@  - net6.0 + net6.0;net8.0 enable - + latest CaptchaN CaptchaN LeaFrock - 2.0.1 + 3.0.0 CaptchaN Core module of generating captcha images. - Copyright © LeaFrock 2022 + Copyright © LeaFrock 2023 MIT captcha;imagesharp https://github.com/LeaFrock/CaptchaN https://github.com/LeaFrock/CaptchaN.git git - Upgrade to ImageSharp 2.1 + Add support for .NET 8 false + README.md - + + + + + diff --git a/Src/CaptchaN/CodeTextGenerator.cs b/Src/CaptchaN/CodeTextGenerator.cs index 859a6be..a701eab 100644 --- a/Src/CaptchaN/CodeTextGenerator.cs +++ b/Src/CaptchaN/CodeTextGenerator.cs @@ -1,26 +1,28 @@ using CaptchaN.Abstractions; -using CaptchaN.Helpers; namespace CaptchaN { public class CodeTextGenerator : ICodeTextGenerator { - private readonly static char[] _pool = new char[] - { - //Skip '0/o/O','1/l/I','9/g/q' - '2','3','4','5','6','7','8', - 'a','b','c','d','e','f','h','i','j','k','m','n','p','r','s','t','u','v','w','x','y','z', - 'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z', - }; + //Skip '0/o/O','1/l/I','9/g/q' + private const string _pool = "2345678" + + "abcdefhijkmnprstuvwxyz" + + "ABCDEFGHJKLMNPQRSTUVWXYZ"; public string Generate(int length) { - var random = RandomHelper.CurrentRandom; - Span span = length <= 10 ? stackalloc char[length] : new char[length]; + var random = Random.Shared; + Span span = length <= 10 + ? stackalloc char[length] + : new char[length]; // Will you do so? +#if NET8_0_OR_GREATER + random.GetItems(_pool, span); +#else for (int i = 0; i < length; i++) { - span[i] = _pool[random.Next(0, _pool.Length)]; + span[i] = _pool[random.Next(_pool.Length)]; } +#endif return new string(span); } } diff --git a/Src/CaptchaN/ColorRandomer.cs b/Src/CaptchaN/ColorRandomer.cs index 022aedd..32599fc 100644 --- a/Src/CaptchaN/ColorRandomer.cs +++ b/Src/CaptchaN/ColorRandomer.cs @@ -1,13 +1,12 @@ using CaptchaN.Abstractions; -using CaptchaN.Helpers; using SixLabors.ImageSharp; namespace CaptchaN { public class ColorRandomer : IColorRandomer { - private readonly static Color[] _darkPool = new Color[] - { + private readonly static Color[] _darkPool = + [ Color.Black, Color.MidnightBlue, Color.MediumBlue, @@ -19,10 +18,10 @@ public class ColorRandomer : IColorRandomer Color.OrangeRed, Color.Maroon, Color.DarkViolet - }; + ]; - private readonly static Color[] _lightPool = new Color[] - { + private readonly static Color[] _lightPool = + [ Color.White, Color.Snow, Color.GhostWhite, @@ -47,7 +46,7 @@ public class ColorRandomer : IColorRandomer Color.LightYellow, Color.Pink, Color.PaleGreen - }; + ]; public Color RandomDark() => RandomColor(_darkPool); @@ -55,7 +54,7 @@ public class ColorRandomer : IColorRandomer private static Color RandomColor(Color[] pool) { - int index = RandomHelper.CurrentRandom.Next(0, pool.Length); + int index = Random.Shared.Next(0, pool.Length); return pool[index]; } } diff --git a/Src/CaptchaN/FontRandomer.cs b/Src/CaptchaN/FontRandomer.cs index 3b65328..a17b176 100644 --- a/Src/CaptchaN/FontRandomer.cs +++ b/Src/CaptchaN/FontRandomer.cs @@ -1,5 +1,4 @@ using CaptchaN.Abstractions; -using CaptchaN.Helpers; using SixLabors.Fonts; namespace CaptchaN @@ -15,17 +14,22 @@ internal FontRandomer(FontCollection fontCollection) : this(fontCollection.Famil internal FontRandomer(FontFamily[] fontFamilies) { ArgumentNullException.ThrowIfNull(fontFamilies); - if(fontFamilies.Length < 1) +#if NET8_0_OR_GREATER + ArgumentOutOfRangeException.ThrowIfLessThan(fontFamilies.Length, 1, nameof(fontFamilies)); +#else + if (fontFamilies.Length < 1) { + throw new ArgumentOutOfRangeException(nameof(fontFamilies), "Array length must be over 0."); } +#endif _fontFamilies = fontFamilies; } public Font Random(float size, FontStyle fontStyle) { - int index = RandomHelper.CurrentRandom.Next(0, _fontFamilies.Length); + int index = System.Random.Shared.Next(_fontFamilies.Length); #if DEBUG System.Diagnostics.Debug.WriteLine(_fontFamilies[index].Name); #endif diff --git a/Src/CaptchaN/Helpers/RandomHelper.cs b/Src/CaptchaN/Helpers/RandomHelper.cs deleted file mode 100644 index 81cbfbf..0000000 --- a/Src/CaptchaN/Helpers/RandomHelper.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace CaptchaN.Helpers -{ - internal static class RandomHelper - { - public static Random CurrentRandom => Random.Shared; - } -} \ No newline at end of file diff --git a/Src/CaptchaN/Painter.cs b/Src/CaptchaN/Painter.cs index fe0d2f1..774d511 100644 --- a/Src/CaptchaN/Painter.cs +++ b/Src/CaptchaN/Painter.cs @@ -1,5 +1,4 @@ using CaptchaN.Abstractions; -using CaptchaN.Helpers; using SixLabors.Fonts; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Drawing; @@ -49,7 +48,7 @@ private Image CreateImage(string codeText, PainterOption option) void Operate(IImageProcessingContext ctx) { - var random = RandomHelper.CurrentRandom; + var random = Random.Shared; float fontSize = RandomFontSize(option.Width, option.Height, codeText.Length); ctx.BackgroundColor(option.UseBlackWhiteOnly ? Color.White : _colorRandomer.RandomLight()); //.Glow(_colorRandomer.RandomLight()) @@ -108,7 +107,7 @@ void Operate(IImageProcessingContext ctx) { for (int i = 1; i < option.LineCount; i++) { - ctx.DrawLines(color: option.UseBlackWhiteOnly ? Color.Black : _colorRandomer.RandomDark(), + ctx.DrawLine(color: option.UseBlackWhiteOnly ? Color.Black : _colorRandomer.RandomDark(), thickness: DefaultLineThickness, new PointF(random.Next(0, option.Width / 2), random.Next(1, option.Height)), new PointF(random.Next(option.Width / 2 + 1, option.Width), random.Next(1, option.Height))