Browse Source

CMS Kit: Cache generated reCaptcha result

pull/17565/head
Engincan VESKE 3 years ago
parent
commit
dc2e58442d
  1. 4
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs
  2. 14
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs
  3. 3
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml
  4. 5
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs
  5. 47
      modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs

4
modules/cms-kit/src/Volo.CmsKit.Public.Web/Controllers/CmsKitPublicCommentsController.cs

@ -37,7 +37,7 @@ public class CmsKitPublicCommentsController : CmsKitPublicControllerBase
{
CheckCaptchaTokenNullity(input.CaptchaToken);
SimpleMathsCaptchaGenerator.Validate(input.CaptchaToken.Value, input.CaptchaAnswer);
await SimpleMathsCaptchaGenerator.ValidateAsync(input.CaptchaToken.Value, input.CaptchaAnswer);
}
var dto = ObjectMapper.Map<CreateCommentWithParametersInput, CreateCommentInput> (input);
@ -51,7 +51,7 @@ public class CmsKitPublicCommentsController : CmsKitPublicControllerBase
{
CheckCaptchaTokenNullity(input.CaptchaToken);
SimpleMathsCaptchaGenerator.Validate(input.CaptchaToken.Value, input.CaptchaAnswer);
await SimpleMathsCaptchaGenerator.ValidateAsync(input.CaptchaToken.Value, input.CaptchaAnswer);
}
await CommentPublicAppService.UpdateAsync(id, input);

14
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/CommentingViewComponent.cs

@ -76,26 +76,30 @@ public class CommentingViewComponent : AbpViewComponent
LoginUrl = loginUrl,
Comments = comments.OrderByDescending(i => i.CreationTime).ToList()
};
await ConvertMarkdownTextsToHtml(viewModel);
if (CmsKitCommentOptions.IsRecaptchaEnabled)
{
CaptchaOutput = GetCaptcha();
CaptchaOutput = await GenerateCaptchaAsync();
viewModel.CaptchaImageBase64 = GetCaptchaImageBase64(CaptchaOutput.ImageBytes);
}
this.Input = viewModel;
return View("~/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml", this);
}
public CaptchaOutput GetCaptcha()
public async Task<CaptchaOutput> GenerateCaptchaAsync()
{
return SimpleMathsCaptchaGenerator.Generate(new CaptchaOptions(
return await SimpleMathsCaptchaGenerator.GenerateAsync(
new CaptchaOptions(
number1MinValue: 1,
number1MaxValue: 10,
number2MinValue: 5,
number2MaxValue: 15)
);
number2MaxValue: 15
)
);
}
public string GetCaptchaImageBase64(byte[] bytes)

3
modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml

@ -133,7 +133,8 @@
@if (CmsKitCommentOptions.Value.IsRecaptchaEnabled)
{
var output = Model.GetCaptcha();
var output = await Model.GenerateCaptchaAsync();
<div class="volo-captcha">
<label class="form-label" for="Input_Captcha_@output.Id">@L["CaptchaCode"]</label>
<div class="d-flex">

5
modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/CaptchaOptions.cs

@ -1,4 +1,5 @@
using SixLabors.Fonts;
using System;
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
@ -47,6 +48,8 @@ public class CaptchaOptions
public int Number2MaxValue { get; set; } = 99;
public TimeSpan DurationOfValidity { get; set; } = TimeSpan.FromMinutes(10);
public CaptchaOptions()
{

47
modules/cms-kit/src/Volo.CmsKit.Public.Web/Security/Captcha/SimpleMathsCaptchaGenerator.cs

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
@ -15,27 +14,30 @@ using Microsoft.Extensions.Localization;
using Volo.Abp.DependencyInjection;
using Color = SixLabors.ImageSharp.Color;
using PointF = SixLabors.ImageSharp.PointF;
using Volo.Abp.Caching;
using Microsoft.Extensions.Caching.Distributed;
namespace Volo.CmsKit.Public.Web.Security.Captcha;
public class SimpleMathsCaptchaGenerator : ISingletonDependency
public class SimpleMathsCaptchaGenerator : ITransientDependency
{
private readonly IStringLocalizer<CmsKitResource> _localizer;
protected IStringLocalizer<CmsKitResource> Localizer { get; }
protected IDistributedCache<CaptchaOutput> Cache { get; }
public SimpleMathsCaptchaGenerator(IStringLocalizer<CmsKitResource> localizer)
public SimpleMathsCaptchaGenerator(IStringLocalizer<CmsKitResource> localizer, IDistributedCache<CaptchaOutput> cache)
{
_localizer = localizer;
Localizer = localizer;
Cache = cache;
}
private static Dictionary<Guid, CaptchaRequest> Session { get; set; } = new Dictionary<Guid, CaptchaRequest>();
public CaptchaOutput Generate()
public virtual Task<CaptchaOutput> GenerateAsync()
{
return Generate(options: null, number1: null, number2: null);
return GenerateAsync(options: null, number1: null, number2: null);
}
public CaptchaOutput Generate(CaptchaOptions options)
public virtual Task<CaptchaOutput> GenerateAsync(CaptchaOptions options)
{
return Generate(options, number1: null, number2: null);
return GenerateAsync(options, number1: null, number2: null);
}
/// <summary>
@ -45,7 +47,7 @@ public class SimpleMathsCaptchaGenerator : ISingletonDependency
/// <param name="number1">First number for maths operation</param>
/// <param name="number2">Second number for maths operation</param>
/// <returns></returns>
public CaptchaOutput Generate(CaptchaOptions options, int? number1, int? number2)
public virtual async Task<CaptchaOutput> GenerateAsync(CaptchaOptions options, int? number1, int? number2)
{
var random = new Random();
options ??= new CaptchaOptions();
@ -65,11 +67,15 @@ public class SimpleMathsCaptchaGenerator : ISingletonDependency
{
Text = text,
Result = Calculate(number1.Value, number2.Value),
ImageBytes = GenerateInternal(text, options)
ImageBytes = GenerateInternal(text, options)
}
};
Session[request.Output.Id] = request;
await Cache.SetAsync(request.Output.Id.ToString("N"), request.Output, new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.Add(options.DurationOfValidity)
});
return request.Output;
}
@ -78,24 +84,25 @@ public class SimpleMathsCaptchaGenerator : ISingletonDependency
return number1 + number2;
}
public void Validate(Guid requestId, int value)
public virtual async Task ValidateAsync(Guid requestId, int value)
{
var request = Session[requestId];
if (request.Output.Result != value)
var request = await Cache.GetAsync(requestId.ToString("N"));
if(request == null || request.Result != value)
{
throw new UserFriendlyException(_localizer["CaptchaCodeErrorMessage"]);
throw new UserFriendlyException(Localizer["CaptchaCodeErrorMessage"]);
}
}
public void Validate(Guid requestId, string value)
public virtual async Task ValidateAsync(Guid requestId, string value)
{
if (int.TryParse(value, out var captchaInput))
{
Validate(requestId, captchaInput);
await ValidateAsync(requestId, captchaInput);
}
else
{
throw new UserFriendlyException(_localizer["CaptchaCodeMissingMessage"]);
throw new UserFriendlyException(Localizer["CaptchaCodeMissingMessage"]);
}
}

Loading…
Cancel
Save