验证码优化

This commit is contained in:
biss committed 2026-09-12 07:57:27 +08:00
1 parent f489a3553c
commit 4a3bb84aa4
17 files changed
+156 -430

No files matched your search

@@ -0,0 +1,53 @@
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using Jiaowu.Api.Controllers;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace Jiaowu.Api.Tests;
public sealed class ArchiveBatchRequestValidationTests
{
[Fact]
public void Mvc_validator_accepts_archive_record_metadata()
{
var services = new ServiceCollection();
services.AddLogging();
services.AddControllers().AddApplicationPart(typeof(ArchivesController).Assembly);
using var provider = services.BuildServiceProvider();
var actionContext = new ActionContext(
new DefaultHttpContext { RequestServices = provider },
new RouteData(),
new ActionDescriptor(),
new ModelStateDictionary());
var exception = Record.Exception(() => provider.GetRequiredService<IObjectModelValidator>()
.Validate(actionContext, null, string.Empty,
new ArchiveBatchRequest([Guid.NewGuid()], true, "学期已结束")));
Assert.Null(exception);
Assert.True(actionContext.ModelState.IsValid);
}
[Fact]
public void Validation_metadata_is_attached_to_record_constructor_parameters()
{
var constructor = Assert.Single(typeof(ArchiveBatchRequest).GetConstructors());
var parameters = constructor.GetParameters();
Assert.Contains(parameters[0].GetCustomAttributes(), x => x is RequiredAttribute);
Assert.Contains(parameters[0].GetCustomAttributes(), x => x is MinLengthAttribute { Length: 1 });
Assert.Contains(parameters[0].GetCustomAttributes(), x => x is MaxLengthAttribute { Length: 100 });
Assert.Contains(parameters[2].GetCustomAttributes(), x => x is MaxLengthAttribute { Length: 500 });
Assert.Empty(typeof(ArchiveBatchRequest).GetProperty(nameof(ArchiveBatchRequest.Ids))!
.GetCustomAttributes<ValidationAttribute>());
Assert.Empty(typeof(ArchiveBatchRequest).GetProperty(nameof(ArchiveBatchRequest.Reason))!
.GetCustomAttributes<ValidationAttribute>());
}
}
@@ -10,6 +10,8 @@ using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Lazy.Captcha.Core;
namespace Jiaowu.Api.Tests;
@@ -47,6 +49,8 @@ public sealed class AuthControllerTests
await connection.OpenAsync();
var services = new ServiceCollection();
services.AddLogging();
services.AddDistributedMemoryCache();
services.AddCaptcha(new ConfigurationBuilder().Build());
services.AddDbContext<AppDbContext>(options => options
.UseSqlite(connection)
.ReplaceService<IExecutionStrategyFactory, RetryingExecutionStrategyFactory>());
@@ -109,8 +113,7 @@ public sealed class AuthControllerTests
userManager,
new StubAuthSessionService(),
new TwoFactorLoginTicketService(new Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider()),
new LoginCaptchaService(new Microsoft.Extensions.Caching.Distributed.MemoryDistributedCache(
Microsoft.Extensions.Options.Options.Create(new Microsoft.Extensions.Caching.Memory.MemoryDistributedCacheOptions()))),
scope.ServiceProvider.GetRequiredService<ICaptcha>(),
NoOpAppCache.Instance);
var request = new StudentActivationRequest(
student.Name,
@@ -0,0 +1,26 @@
using Lazy.Captcha.Core;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Jiaowu.Api.Tests;
public sealed class LazyCaptchaIntegrationTests
{
[Fact]
public void Generated_code_is_valid_once_and_returns_image_bytes()
{
var services = new ServiceCollection();
services.AddDistributedMemoryCache();
services.AddCaptcha(new ConfigurationBuilder().Build());
using var provider = services.BuildServiceProvider();
var captcha = provider.GetRequiredService<ICaptcha>();
var id = Guid.NewGuid().ToString("N");
var generated = captcha.Generate(id, expirySeconds: 120);
Assert.NotEmpty(generated.Bytes);
Assert.True(captcha.Validate(id, generated.Code));
Assert.False(captcha.Validate(id, generated.Code));
}
}
Loaded 3 of 17 files, more files were not shown because too many files have changed in this diff. Show more