在 Laravel 12 中实现拖动验证码(滑块验证码)功能

Laravel 12 实现拖动验证码功能

在 Laravel 12 中实现拖动验证码(滑块验证码)功能,可以使用第三方服务或自行开发。以下是几种实现方式:

方法一:使用第三方服务(推荐)

1. 使用极验(GeeTest)

composer require gee-team/gt3-php-sdk

.env 中添加:

GEETEST_ID=your_id
GEETEST_KEY=your_key

控制器代码:

use GeeTeam\GeeValidate;

public function getGeeTest()
{
    $geeValidate = new GeeValidate(env('GEETEST_ID'), env('GEETEST_KEY'));
    return $geeValidate->preProcess();
}

public function validateGeeTest(Request $request)
{
    $geeValidate = new GeeValidate(env('GEETEST_ID'), env('GEETEST_KEY'));
    if (!$geeValidate->validate($request->input('geetest_challenge'), $request->input('geetest_validate'), $request->input('geetest_seccode'))) {
        return back()->withErrors(['captcha' => '验证失败']);
    }
    // 验证通过
}

前端代码:

<script src="//static.geetest.com/static/tools/gt.js"></script>
<div id="geetest-captcha"></div>
<script>
    initGeetest({
        gt: "{{ $gt }}",
        challenge: "{{ $challenge }}",
        product: "float",
        offline: false
    }, function(captchaObj) {
        captchaObj.appendTo("#geetest-captcha");
        captchaObj.onSuccess(function() {
            // 验证通过后的处理
        });
    });
</script>

2. 使用腾讯云验证码

composer require tencentcloud/tencentcloud-sdk-php

控制器代码:

use TencentCloud\Captcha\V20190722\CaptchaClient;
use TencentCloud\Captcha\V20190722\Models\DescribeCaptchaResultRequest;
use TencentCloud\Common\Credential;

public function validateTencentCaptcha(Request $request)
{
    $cred = new Credential(env('TENCENT_SECRET_ID'), env('TENCENT_SECRET_KEY'));
    $client = new CaptchaClient($cred, "ap-guangzhou");
    
    $req = new DescribeCaptchaResultRequest();
    $req->CaptchaType = 9; // 滑块验证码类型
    $req->Ticket = $request->input('ticket');
    $req->UserIp = $request->ip();
    $req->Randstr = $request->input('randstr');
    $req->CaptchaAppId = env('TENCENT_CAPTCHA_APP_ID');
    $req->AppSecretKey = env('TENCENT_CAPTCHA_APP_KEY');
    
    $resp = $client->DescribeCaptchaResult($req);
    
    if ($resp->CaptchaCode != 1) {
        return back()->withErrors(['captcha' => '验证失败']);
    }
    // 验证通过
}

方法二:自行开发简单滑块验证码

1. 后端实现

创建验证路由:

Route::post('/verify-slider', function(Request $request) {
    $position = $request->input('position');
    $savedPosition = session('slider_position');
    
    // 允许±5像素的误差
    if (abs($position - $savedPosition) > 5) {
        return response()->json(['success' => false]);
    }
    
    session(['slider_verified' => true]);
    return response()->json(['success' => true]);
});

Route::get('/slider-data', function() {
    $position = rand(20, 80); // 生成随机位置(百分比)
    session(['slider_position' => $position]);
    
    return response()->json([
        'position' => $position,
        'image' => 'path/to/background-image.jpg' // 背景图路径
    ]);
});

2. 前端实现

<div class="slider-container">
    <div class="slider-bg">
        <img src="" id="slider-bg" alt="验证背景">
    </div>
    <div class="slider">
        <div class="slider-btn"></div>
        <div class="slider-track"></div>
    </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
    fetch('/slider-data')
        .then(response => response.json())
        .then(data => {
            document.getElementById('slider-bg').src = data.image;
            
            const sliderBtn = document.querySelector('.slider-btn');
            const sliderTrack = document.querySelector('.slider-track');
            let isDragging = false;
            let startX = 0;
            let currentX = 0;
            
            sliderBtn.addEventListener('mousedown', (e) => {
                isDragging = true;
                startX = e.clientX;
                document.addEventListener('mousemove', onDrag);
                document.addEventListener('mouseup', onDragEnd);
            });
            
            function onDrag(e) {
                if (!isDragging) return;
                currentX = e.clientX - startX;
                if (currentX < 0) currentX = 0;
                if (currentX > sliderTrack.offsetWidth - sliderBtn.offsetWidth) {
                    currentX = sliderTrack.offsetWidth - sliderBtn.offsetWidth;
                }
                sliderBtn.style.transform = `translateX(${currentX}px)`;
            }
            
            function onDragEnd() {
                isDragging = false;
                document.removeEventListener('mousemove', onDrag);
                document.removeEventListener('mouseup', onDragEnd);
                
                // 验证
                const position = (currentX / (sliderTrack.offsetWidth - sliderBtn.offsetWidth)) * 100;
                fetch('/verify-slider', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
                    },
                    body: JSON.stringify({ position: position })
                })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        alert('验证成功');
                    } else {
                        alert('验证失败');
                        sliderBtn.style.transform = 'translateX(0)';
                    }
                });
            }
        });
});
</script>

方法三:使用开源库(如SlideCaptcha)

  1. 安装前端库:
npm install slide-captcha --save
  1. 前端组件:
import SlideCaptcha from 'slide-captcha';

const captcha = new SlideCaptcha({
    container: '#captcha-container',
    width: 320,
    height: 160,
    sliderL: 42,
    sliderR: 9,
    sliderY: 50,
    onSuccess: function() {
        // 验证成功回调
    },
    onFail: functionfunction() {
        // 验证失败回调
    },
    onRefresh: function() {
        // 刷新验证码回调
    }
});

Laravel 后端验证:

public function validateSlide(Request $request)
{
    $data = $request->validate([
        'captcha_token' => 'required',
        'slide_x' => 'required|numeric'
    ]);
    
    // 这里应该添加更复杂的验证逻辑
    $expected = Cache::get('captcha_'.$data['captcha_token']);
    
    if (abs($data['slide_x'] - $expected) > 5) {
        return response()->json(['success' => false]);
    }
    
    return response()->json(['success' => true]);
}

安全建议

  1. 对于生产环境,建议使用成熟的第三方服务
  2. 自行实现时,应该:
  • 添加时间限制(如5分钟内完成验证)
  • 限制尝试次数
  • 记录失败尝试
  • 使用加密令牌防止伪造
  1. 考虑添加行为分析,如拖动速度、路径等

以上方法可以根据项目需求选择,第三方服务通常更安全可靠但可能有费用,自行开发则更灵活但安全性需要更多考虑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值