LazySlideCaptcha
介紹
LazySlideCaptcha是基於.Net Standard 2.1的滑動驗證碼模組。
專案同時提供一個基於vue2的演示前端元件和背景圖裁剪工具。
圖形驗證碼請移步lazy-captcha。
快速開始
- 安裝
Install-Package Lazy.SlideCaptcha.Core
dotnet add package Lazy.SlideCaptcha.Core
- 註冊並配置服務
builder.Services.AddSlideCaptcha(builder.Configuration);
// 如果使用redis分散式快取
//builder.Services.AddStackExchangeRedisCache(options =>
//{
// options.Configuration = builder.Configuration.GetConnectionString("RedisCache");
// options.InstanceName = "captcha:";
//});
"CaptchaSlideOptions": {
"Backgrounds": [
{
"Type": "file",
"Data": "wwwroot/images/background/1.jpg"
},
{
"Type": "file",
"Data": "wwwroot/images/background/2.jpg"
}
]
}
背景圖片要求尺寸要求為 552 X 344 , 快速開始可在 Demo 專案 wwwroot/images/background 下挑選。(僅用作演示,生產請自行製作。)也可以通過裁剪工具製作,非常簡單,上傳圖片,拖動範圍後儲存自動生成 552 X 344 圖片。
- 介面定義
[Route("api/[controller]")]
[ApiController]
public class CaptchaController : ControllerBase
{
private readonly ICaptcha _captcha;
public CaptchaController(ICaptcha captcha)
{
_captcha = captcha;
}
/// <summary>
/// id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[Route("gen")]
[HttpGet]
public CaptchaData Generate()
{
return _captcha.Generate();
}
/// <summary>
/// id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[Route("check")]
[HttpPost]
public bool Validate([FromQuery]string id, SlideTrack track)
{
return _captcha.Validate(id, track);
}
}
至此後端Api服務已搭建完成。
- 前端
前端提供演示元件lazy-slide-captcha,可通過npm安裝。Demo專案為了演示方便直接採用script直接引入方式。
@{
ViewData["Title"] = "滑動驗證碼";
}
<link rel="stylesheet" href="~/lib/lazy-slide-captcha/dist/lazy-slide-captcha.css" asp-append-version="true" />
<style>
#app {
display: flex;
align-items: center;
justify-content: center;
}
.panel {
padding: 20px;
box-shadow: inherit;
border-radius: 6px;
box-shadow: 0 0 4px 0 #999999;
margin-top: 100px;
}
</style>
<div id="app">
<div class="panel">
<lazy-slide-captcha ref="captcha" :width="width" :height="height" :show-refresh="true" :fail-tip="failTip" :success-tip="successTip" @@finish="handleFinish" @@refresh="generate"></lazy-slide-captcha>
</div>
</div>
@section Scripts{
<script src="~/lib/vue/vue.min.js"></script>
<script src="~/lib/vue/axios.min.js"></script>
<script src="~/lib/lazy-slide-captcha/dist/lazy-slide-captcha.umd.js"></script>
<script>
var app = new Vue({
el: '#app',
data(){
return {
requestId: undefined,
failTip: '',
successTip: '',
// width,height保持與552 * 344同比例即可
width: 340,
height: 212
}
},
mounted(){
this.generate()
},
methods:{
generate(){
// 改變內部狀態,標識生成請求開始
this.$refs.captcha.startRequestGenerate()
axios.get('/api/captcha/gen')
.then((response) => {
this.requestId = response.data.id
// 改變內部狀態,標識生成請求結束,同時設定background,slider影像
this.$refs.captcha.endRequestGenerate(response.data.backgroundImage, response.data.sliderImage)
})
.catch((error) => {
console.log(error);
// 標識生成請求結束
this.$refs.captcha.endRequestGenerate(null, null)
});
},
handleFinish(data){
// 改變內部狀態,標識驗證請求開始
this.$refs.captcha.startRequestVerify()
axios.post(`/api/captcha/check?id=${this.requestId}`, data)
.then((response) => {
let success = response.data.result === 0
// 驗證失敗時顯示資訊
this.failTip = response.data.result == 1 ? '驗證未通過,拖動滑塊將懸浮影像正確合併' : '驗證超時, 請重新操作'
// 驗證通過時顯示資訊
this.successTip = '驗證通過,超過80%使用者'
// 改變內部狀態,標識驗證請求結束,同時設定是否成功狀態
this.$refs.captcha.endRequestVerify(success)
if(!success){
setTimeout(() => {
this.generate()
}, 1000)
}
})
.catch((error) => {
console.log(error);
this.failTip = '服務異常,請稍後重試'
// 標識驗證請求結束
this.$refs.captcha.endRequestVerify(false)
});
}
}
});
</script>
}
配置說明
支援配置檔案和程式碼配置,同時配置則程式碼配置覆蓋配置檔案。
- 配置檔案
"CaptchaSlideOptions": {
"ExpirySeconds": 60, // 快取過期時長
"StoreageKeyPrefix": "", // 快取字首
"Tolerant": 0.02, // 容錯值(校驗時用,缺口位置與實際滑動位置匹配容錯範圍)
"Backgrounds": [ // 背景圖配置
{
"Type": "file",
"Data": "wwwroot/images/background/1.jpg"
}
],
// Templates不配置,則使用預設模板
"Templates": [
{
"Slider": {
"Type": "file",
"Data": "wwwroot/images/template/1/slider.png"
},
"Hole": {
"Type": "file",
"Data": "wwwroot/images/template/1/hole.png"
}
}
]
}
- 程式碼配置
builder.Services.AddSlideCaptcha(builder.Configuration, options =>
{
options.Tolerant = 0.02f;
options.StoreageKeyPrefix = "slider-captcha";
options.Backgrounds.Add(new Resource(FileResourceHandler.TYPE, @"wwwroot/images/background/1.jpg"));
options.Templates.Add
(
TemplatePair.Create
(
new Resource(FileResourceHandler.TYPE, @"wwwroot/images/template/1/slider.png"),
new Resource(FileResourceHandler.TYPE, @"wwwroot/images/template/1/hole.png")
)
);
});
擴充套件
- Template自定義
Template 是指用於生成凹槽和拖塊的圖片,可通過Templates配置節點設定設定自定義Template。 預設五個 Template (不要配置,已經包含在類庫內部)如下:
slider | hole | slider | hole |
---|---|---|---|
禁用預設 _Template_呼叫DisableDefaultTemplates即可:
builder.Services.AddSlideCaptcha(builder.Configuration)
.DisableDefaultTemplates();
- Validator自定義
類庫提供 SimpleValidator , BasicValidator 兩個實現。
SimpleValidator 僅位置驗證,BasicValidator除位置驗證外,同時對軌跡做驗證。BasicValidator由於演算法的原因,容易誤判,因此類庫預設用SimpleValidator_ 做為預設 Validator 。
自定義 Validator 繼承 BaseValidator , BaseValidator 提供了基本的位置驗證。
舉一個栗子:
public class CustomValidator: BaseValidator
{
public override bool ValidateCore(SlideTrack slideTrack, CaptchaValidateData captchaValidateData)
{
// BaseValidator已做了基本滑塊與凹槽的對齊驗證,這裡做其他驗證
return true;
}
}
替換預設的Validator
builder.Services.AddSlideCaptcha(builder.Configuration);
.ReplaceValidator<CustomValidator>();
- ResourceProvider自定義
除了通過Options配置Background和Template外,你也可以通過自定義ResourceProvider的形式提供Background和Template。
public class CustomResourceProvider : IResourceProvider
{
public List<Resource> Backgrounds()
{
return Enumerable.Range(1, 10)
.ToList()
.Select(e => new Resource(Core.Resources.Handler.FileResourceHandler.TYPE, $"wwwroot/images/background/{e}.jpg"))
.ToList();
}
// 這裡返回自定義的Template
public List<TemplatePair> Templates()
{
return new List<TemplatePair>();
}
}
註冊ResourceProvider
builder.Services.AddSlideCaptcha(builder.Configuration)
.AddResourceProvider<CustomResourceProvider>();
- 自定義ResourceHandler
public class UrlResourceHandler : IResourceHandler
{
public const string Type = "url";
public bool CanHandle(string handlerType)
{
return handlerType == Type;
}
/// <summary>
/// 這裡僅演示,仍然從本地讀取。實際需要通過Http讀取
/// </summary>
/// <param name="resource"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public byte[] Handle(Resource resource)
{
if (resource == null) throw new ArgumentNullException(nameof(resource));
return File.ReadAllBytes(resource.Data);
}
}
註冊ResourceHandler
builder.Services.AddSlideCaptcha(builder.Configuration)
.AddResourceHandler<UrlResourceHandler>();
專案參考
專案參考了tianai-captcha,vue-drag-verify非常優秀的專案,非常感謝。