这一节,我们在Constant目录中,定义两个类CaptchaOptions.cs与CaptchaTypeConstant。目的是设置验证码的类型与其他一些属性。然后在Storage目录中,设置验证码的缓存数据。
上一节内容:.NET 6 实现滑动验证码(四)、扩展类
在Constant 文件夹下新建立CaptchaOptions.cs。定义验证码过期时间、缓存key值、容错值等。
using SlideCaptcha.Model;
using System.Collections.Generic;
namespace SlideCaptcha.Constant
{
public class CaptchaOptions
{
/// <summary>
/// 过期时长
/// </summary>
public int ExpirySeconds { get; set; } = 60;
/// <summary>
/// 存储键前缀
/// </summary>
public string StoreageKeyPrefix { get; set; } = "slide-captcha";
/// <summary>
/// 容错值(校验时用,缺口位置与实际滑动位置匹配容错范围)
/// </summary>
public float Tolerant { get; set; } = 0.02f;
/// <summary>
/// 背景图
/// </summary>
public List<Resource> Backgrounds { get; set; } = new List<Resource>();
/// <summary>
/// 模板图(必须是slider,notch的顺序依次出现)
/// </summary>
public List<TemplatePair> Templates { get; set; } = new List<TemplatePair>();
}
}
在Constant 文件夹下新建立CaptchaTypeConstant.cs。定义各种常见验证码类型:
namespace SlideCaptcha.Constant
{
public class CaptchaTypeConstant
{
/** 滑块. */
public static string SLIDER = "SLIDER";
/** 旋转. */
public static string ROTATE = "ROTATE";
/** 拼接.*/
public static string CONCAT = "CONCAT";
/** 图片点选.*/
public static string IMAGE_CLICK = "IMAGE_CLICK";
/** 文字图片点选.*/
public static string WORD_IMAGE_CLICK = "WORD_IMAGE_CLICK";
}
}
本次我们只实现滑块验证码。旋转、拼接、图片点选,文字图片点选暂不考虑。不过在源码中,已添加了旋转验证码的实现,目前还在测试中。
在Storage文件夹建立DefaultStorage.cs,定义缓存的各种方法。
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SlideCaptcha.Constant;
using SlideCaptcha.Interface;
using System;
using System.Text;
namespace SlideCaptcha.Storage
{
public class DefaultStorage : IStorage
{
private readonly IDistributedCache _cache;
private readonly IOptionsMonitor<CaptchaOptions> _options;
public DefaultStorage(IOptionsMonitor<CaptchaOptions> options, IDistributedCache cache)
{
_options = options;
_cache = cache;
}
private string WrapKey(string key)
{
return $"{this._options.CurrentValue.StoreageKeyPrefix}{key}";
}
public T Get<T>(string key)
{
var bytes = _cache.Get(WrapKey(key));
if (bytes == null) return default(T);
var json = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
return JsonConvert.DeserializeObject<T>(json);
}
public void Remove(string key)
{
_cache.Remove(WrapKey(key));
}
public void Set<T>(string key, T value, DateTimeOffset absoluteExpiration)
{
string json = JsonConvert.SerializeObject(value);
byte[] bytes = Encoding.UTF8.GetBytes(json);
_cache.Set(WrapKey(key), bytes, new DistributedCacheEntryOptions
{
AbsoluteExpiration = absoluteExpiration
});
}
}
}
缓存使用的是IDistributedCache 接口,方便集成在项目的时候,选择需要的缓存,如MemoryCache或Redis。
下一篇,开始写验证码图片与验证码凹槽的获取。
下载方式:
扫描公众号二维码关注我,回复captcha下载,压缩包包含了验证码类库、服务端API、HTML+JQuery完整代码、vue3组件代码及演示代码!
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问