.Net 6 implémente le code de vérification de rotation

Les articles précédents introduisaient la fonction de code de vérification coulissante implémentée par .Net 6. Récemment, le code de vérification coulissante a été ImageSharpremplacé par le code de vérification coulissante SkiaSharpet la partie découpée fait référence au code de pojianbing. Après avoir glissé le code de vérification, je me suis dit. Faites un captcha rotatif. En fait, le code de vérification rotatif est similaire au code de vérification glissant.

Voyons d'abord le rendu :
insérez la description de l'image ici
le principe d'implémentation de la rotation est le même que celui du code de vérification glissante :

  • 1. Obtenez l'image d'arrière-plan
  • 2. Obtenez la carte des rainures et la carte des curseurs du modèle
  • 3. Effectuez la découpe de la rainure
  • 4. Faites pivoter la toile
  • 5. Carte vers la carte du curseur
  • 6. Superposez le modèle de carte de rainure sur l'image d'arrière-plan

Classe d'entité Captcha ImageCaptchaInfo

public class ImageCaptchaInfo
{
    
    
    /// <summary>
    /// 背景图宽
    /// </summary>
    public int BackgroundImageWidth {
    
     get; set; }
    /// <summary>
    /// 背景图高
    /// </summary>
    public int BackgroundImageHeight {
    
     get; set; }
    /// <summary>
    /// 背景图
    /// </summary>
    public string BackgroundImageBase64 {
    
     get; set; }
    /// <summary>
    /// 滑动块图宽
    /// </summary>
    public int SliderImageWidth {
    
     get; set; }
    /// <summary>
    /// 滑动块图高
    /// </summary>
    public int SliderImageHeight {
    
     get; set; }
    /// <summary>
    /// 滑动块图
    /// </summary>
    public string SliderImageBase64 {
    
     get; set; }

    /// <summary>
    /// 随机值
    /// </summary>
    public int RandomX {
    
     get; set; }

    /// <summary>
    /// 容错值,可以为空!
    /// </summary>
    public float Tolerant {
    
     get; set; }
    /// <summary>
    /// 验证码类型
    /// </summary>
    public string CaptchaType {
    
     get; set; }

    public float Percentage
    {
    
    
        get
        {
    
    
            if (BackgroundImageWidth <= 0) return 0;
            return 1.0F * RandomX / BackgroundImageWidth;
        }
    }
}

Parmi eux, la valeur aléatoire RandomX est de participer au Percentagecalcul du taux de glissement. PercentageLe rôle sera discuté plus tard.

Définir l'entité captcha de rotation RotateImageCaptchaInfo

public class RotateImageCaptchaInfo : ImageCaptchaInfo
{
    
    
    /// <summary>
    /// 旋转多少度
    /// </summary>
    public float Degree {
    
     get; set; }


    public void Check()
    {
    
    
        //校验
        if (this.Degree <= 0) throw new TaCaptchaException($"RotateImageCaptchaInfo数据异常: {
      
      nameof(Degree)}小于等于0");
        if (this.RandomX <= 0) throw new TaCaptchaException($"RotateImageCaptchaInfo数据异常: {
      
      nameof(RandomX)}小于等于0");
        if (this.BackgroundImageWidth <= 0) throw new TaCaptchaException($"RotateImageCaptchaInfo数据异常: {
      
      nameof(BackgroundImageWidth)}小于等于0");
        if (this.BackgroundImageHeight <= 0) throw new TaCaptchaException($"RotateImageCaptchaInfo数据异常: {
      
      nameof(BackgroundImageHeight)}小于等于0");
        if (this.SliderImageWidth <= 0) throw new TaCaptchaException($"RotateImageCaptchaInfo数据异常: {
      
      nameof(SliderImageWidth)}小于等于0");
        if (this.SliderImageHeight <= 0) throw new TaCaptchaException($"RotateImageCaptchaInfo数据异常: {
      
      nameof(SliderImageHeight)}小于等于0");
        if (string.IsNullOrWhiteSpace(this.BackgroundImageBase64)) throw new TaCaptchaException($"RotateImageCaptchaInfo数据异常: {
      
      nameof(BackgroundImageBase64)}为空");
        if (string.IsNullOrWhiteSpace(this.SliderImageBase64)) throw new TaCaptchaException($"RotateImageCaptchaInfo数据异常: {
      
      nameof(SliderImageBase64)}为空");
    }
}

CheckDans la méthode de vérification, si le degré de rotation Degree, la valeur aléatoire RandomX, etc. ne remplissent pas les conditions, une erreur sera renvoyée automatiquement.

Définir l'interface IRotateCaptchaImageGenerator

Définissez l'interface de code de vérification de rotation, qui est relativement simple, juste une méthode pour générer des codes de vérification.

public interface IRotateCaptchaImageGenerator
{
    
    
	Task<RotateImageCaptchaInfo> Generate(string captchaId);
}

générer un code de vérification

public class RotateCaptchaImageGenerator : IRotateCaptchaImageGenerator
{
    
    
    private readonly IResourceManager _resourceManager;
    private readonly Random _random = new Random();
      
    public RotateCaptchaImageGenerator(IResourceManager resourceManager)
    {
    
    
        _resourceManager = resourceManager;
            
    }

    public async Task<RotateImageCaptchaInfo> Generate(string captchaId)
    {
    
    

        //获取背景图
        var background = await _resourceManager.RandomBackground();
        //获取滑块图、凹槽图
        (var slider, var notch) = await _resourceManager.RandomTemplate(CaptchaTypeConstant.ROTATE);

        using var backgroundImage = SKBitmap.Decode(background);
        //滑块
        using var sliderTemplateImage = SKBitmap.Decode(slider);
        //凹槽
        using var notchTemplateImage = SKBitmap.Decode(notch);

        //定义空的凹槽图与滑块图
        using var notchMattingImage = new SKBitmap(notchTemplateImage.Width, notchTemplateImage.Height);
        using var sliderBarImage = new SKBitmap(360,360);


        //根据透明度计算凹槽图轮廓形状(形状由不透明区域形成)
        var notchShape = CaptchaImageUtils.GetImageShape(notchTemplateImage);

        //滑块图画布
        using var sliderCanvas = new SKCanvas(notchMattingImage);
        //叠加轮廓图
        sliderCanvas.ClipPath(notchShape, SKClipOperation.Intersect, true);
        //计算居中的位置
        int x = backgroundImage.Width / 2 - notchTemplateImage.Width / 2;
        int y = backgroundImage.Height / 2 - notchTemplateImage.Height / 2;
        //随机旋转抠图部分

        int randomX = _random.Next(notchTemplateImage.Width + 10, backgroundImage.Width - 10);
        float degree = 360f - randomX / (backgroundImage.Width / 360f);
        sliderCanvas.RotateDegrees(degree, notchMattingImage.Width/2, notchMattingImage.Height/2);

        //绘制抠图
        sliderCanvas.DrawBitmap(backgroundImage,-x,-y);
        //叠加滑块模板
        sliderCanvas.DrawBitmap(sliderTemplateImage, 0, 0);
            

        int bw = 360;
        int bh = 360;
        int cw = notchMattingImage.Width;
        int ch = notchMattingImage.Height;
        int iw = (int)(bw / 2 - cw / 2);
        int ih = (int)(bh / 2 - ch / 2);

        using var sliderBarCanvas = new SKCanvas(sliderBarImage);
        sliderBarCanvas.DrawBitmap(notchMattingImage, iw, ih);
           


           

        using var backgroundCanvas = new SKCanvas(backgroundImage);
        //叠加凹槽
        backgroundCanvas.DrawBitmap(notchTemplateImage, x, y);

        return new RotateImageCaptchaInfo
        {
    
    
            BackgroundImageWidth = backgroundImage.Width,
            BackgroundImageHeight = backgroundImage.Height,
            BackgroundImageBase64 = backgroundImage.ToBase64String(SKEncodedImageFormat.Png),
            RandomX = randomX,
            Degree = degree,
            Tolerant = 0.03f,
            SliderImageWidth = notchMattingImage.Width,
            SliderImageHeight = notchMattingImage.Height,
            SliderImageBase64 = sliderBarImage.ToBase64String(SKEncodedImageFormat.Png),
            CaptchaType = CaptchaTypeConstant.ROTATE
        };

    }
}

Dans le code, obtenez d'abord l'image d'arrière-plan, l'image de la rainure et l'image du curseur, et convertissez-les en SKBitmap.

Définissez un tracé de rainure et de curseur vide. Selon la carte de rainure, obtenez le chemin de la carte de rainure.

Obtenir la découpe de rainure

/// <summary>
/// 获取图形轮廓,形状由不透明的区域形成
/// </summary>
/// <param name="image">要获取轮廓的图片</param>
/// <returns></returns>
public static SKPath GetImageShape(SKBitmap image)
{
    
    
    int temp = 0;
    var path = new SKPath();
    for(int y=0;y< image.Height;y++)
    {
    
    
        for(int x=0;x< image.Width;x++)
        {
    
    
            var pixel = image.GetPixel(x, y);
            if(pixel.Alpha!=0)
            {
    
    
                if(temp==0)
                {
    
    
                    temp = x;
                }
            }
            else
            {
    
    
                if(temp!=0)
                {
    
    
                    path.AddRect(new SKRect(temp, y, x, y + 1));
                    temp= 0;
                }
            }
        }
    }
    return path;
}

Dans la méthode, définissez un chemin , puis pathobtenez les informations de pixel de chaque bloc colonne par colonne, et utilisez la méthode pour en obtenir une . Il y a 5 attributsSKBitmap GetPixelSKColorSKColor

  • Alpha
  • Bleu
  • Vert
  • Teinte
  • Parmi
    eux, il suffit de juger que le jugement Alphan'est pas 0, c'est-à-dire qu'il n'est pas transparent.

Après avoir obtenu la découpe de la rainure, vous devez en définir une SKCanvas, que j'appelle une toile. Le nom est sliderCanvas, sliderCanvasla découpe d'arrière-plan doit être dessinée sur le dessus.
La méthode d'utilisation superpose ClipPathd' sliderCanvasabord la carte de contour notchShape, c'est-à-dire le tapis de rainures que nous venons de générer. ClipPathLa méthode a plusieurs surcharges et les paramètres utilisés ici sont : SKPath, SKClipOperationet antialias.
Le premier paramètre est l'image de contour qui vient d'être obtenue notchShape, le deuxième paramètre est sélectionné SKClipOperation.Intersectpour prendre l'intersection de deux zones, et le troisième paramètre est défini sur true, ce qui signifie anti-aliasing.
Après avoir superposé la carte de contour, calculez d'abord la position à déduire sur le fond de carte. Obtenez d'abord la position centrale de l'image d'arrière-plan et soustrayez la position centrale de l'image du sillon. Les valeurs x et y obtenues sont les coordonnées du point de départ à dessiner.
Ensuite, selon la valeur aléatoire, faites pivoter la toile de manière aléatoire, en utilisant RotateDegreesla méthode. RotateDegreesLe premier paramètre de la méthode est le degré de rotation, et les deuxième et troisième paramètres déterminent le point central de la rotation.
Il est écrit pour dessiner la partie découpée d'arrière-plan sur le canevas et dessiner le modèle de carte de curseur sur le canevas.
Définissez ensuite un canevas pour le slider sliderBarCanvas. Dessinez la découpe faite sur le curseur.
Enfin, dessinez la carte de rainure sur la carte d'arrière-plan.
Une fois que tout est dessiné, renvoyez les informations au front-end, et c'est tout. SKBitmapLa chaîne base64 renvoyée dans le code est une extension que j'ai moi-même écrite , ce qui est très simple

public static string ToBase64String(this SKBitmap source, SKEncodedImageFormat format)
{
    
    
    using var img = SKImage.FromBitmap(source);
    using SKData data = img.Encode(format, 100);
    var array = data.ToArray();
    return "data:" + format.ToString().ToLower() + ";base64," + Convert.ToBase64String(array, 0, array.Length);
}

jusqu'à présent. Le code pour la rotation du captcha est terminé.

code frontal

Comme le code de vérification de glissement précédent, il y a très peu d'endroits qui doivent être modifiés. resetDans la méthode, réglez la position du curseur sur la position du point central et réglez la rotation sur 0

$(".captcha_slider").css('left', (captchaMainWidth - captchaMainHeight)/2);
$(".captcha_slider").css("transform", "rotate(0deg)")

handleDragMovingméthode, définissez le curseur sur sélectionné au lieu de se déplacer de gauche à droite

$('#sliderSrc').css('transform',"rotate("+(_x/(206/360))+"deg)");

D'autres sont inchangés. Le code frontal est présenté en détail dans cet article
.NET 6 réalise le code de vérification glissant (10), le final : combat de code frontal, vue3 et HTML+JQuery

Résumer

Il existe d'autres types de codes de vérification, tels que les codes de vérification de clic, les codes de vérification graphique, etc. Il sera progressivement perfectionné et réalisé.

Cliquez sur la carte de compte officielle ci-dessous pour me suivre ! Apprendre ensemble et progresser ensemble !

Je suppose que tu aimes

Origine blog.csdn.net/sd2208464/article/details/128507887
conseillé
Classement