欢迎光临
我们一直在努力

HTML静态网页怎么加卡密验证?纯前端方案,粘贴即可用

很多朋友问过我一个问题:我的网站是纯静态HTML页面,没有PHP环境,能加卡密验证吗?

答案是:可以。

而且比PHP方案还简单——不需要服务器环境、不需要配置数据库,只需要把一段JavaScript代码复制到你的HTML文件里,上传到服务器就能用。

用户访问页面时,会自动弹出卡密验证框,输入正确的卡密才能看到内容。

一、适用场景

这套纯前端方案适合以下情况:

  • 网站是纯静态HTML,没有PHP/ASP/JSP等后端环境

  • 只想保护某个特定页面,比如VIP下载页、付费文档页

  • 网站托管在对象存储(OSS/COS)上,不支持PHP

  • 不想折腾后端,想5分钟快速搞定

二、接入步骤

第一步:去卡密通官网(keyt.cn)免费注册一个账号,创建一个应用,获取API地址和应用名称。

第二步:把下面的完整代码复制到你的HTML文件中,放在 </body> 标签之前。

第三步:修改代码顶部的 API_URL 和 APP_NAME 为你的信息。

上传到服务器,完事。

三、完整代码
 

<script src="https://cdn.jsdelivr.net/npm/crypto-js@4.2.0/crypto-js.min.js">
</script>
<script>
// ============================================================
// 配置区(改成你自己的)
// ============================================================
var CONFIG = {
    API_URL: 'https://www.keyt.cn/kami/你的账号/check.php',
    APP_NAME: '你的应用名'
};
// ============================================================

if (localStorage.getItem('card_verified') === 'true') {
    // ===== 已登录,显示剩余时间悬浮窗 =====
    (function() {
        var remainDiv = document.createElement('div');
        remainDiv.id = 'remainTimeDisplay';
        remainDiv.style.cssText = 'position:fixed;top:16px;right:20px;background:rgba(0,0,0,0.75);backdrop-filter:blur(8px);color:#36d399;padding:8px 18px;border-radius:10px;font-size:14px;z-index:9999;font-family:sans-serif;border:1px solid rgba(255,255,255,0.08);box-shadow:0 4px 16px rgba(0,0,0,0.3);cursor:move;user-select:none;';
        remainDiv.textContent = '⏱ 加载中…';
        document.body.appendChild(remainDiv);
        
        // 拖拽功能
        var isDragging = false;
        var offsetX, offsetY;

        remainDiv.addEventListener('mousedown', function(e) {
            isDragging = true;
            var rect = remainDiv.getBoundingClientRect();
            offsetX = e.clientX – rect.left;
            offsetY = e.clientY – rect.top;
            remainDiv.style.cursor = 'grabbing';
            remainDiv.style.transition = 'none';
            e.preventDefault();
        });

        document.addEventListener('mousemove', function(e) {
            if (!isDragging) return;
            var x = e.clientX – offsetX;
            var y = e.clientY – offsetY;
            x = Math.max(0, Math.min(window.innerWidth – remainDiv.offsetWidth, x));
            y = Math.max(0, Math.min(window.innerHeight – remainDiv.offsetHeight, y));
            remainDiv.style.left = x + 'px';
            remainDiv.style.top = y + 'px';
            remainDiv.style.right = 'auto';
        });

        document.addEventListener('mouseup', function() {
            if (isDragging) {
                isDragging = false;
                remainDiv.style.cursor = 'move';
            }
        });

        function getCookie(name) {
            var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
            if (match) return match[2];
            return null;
        }

        function deleteCookie(name) {
            document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
        }

        function request(url, callback) {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    callback(xhr.status === 200 ? xhr.responseText : 'error');
                }
            };
            xhr.send();
        }

        function getDeviceId() {
            var saved = localStorage.getItem('device_id');
            if (saved) return saved;
            var parts = [screen.width + 'x' + screen.height, screen.colorDepth, navigator.platform, navigator.userAgent];
            try {
                var c = document.createElement('canvas');
                c.width = 256;
                c.height = 64;
                var ctx = c.getContext('2d');
                ctx.fillStyle = '#f60';
                ctx.fillRect(100, 1, 62, 20);
                ctx.fillStyle = '#069';
                ctx.font = '14px Arial';
                ctx.fillText('Keyt.cn', 2, 15);
                parts.push(c.toDataURL());
            } catch(e) {}
            var id = 'web_' + CryptoJS.MD5(parts.join('|')).toString();
            localStorage.setItem('device_id', id);
            return id;
        }

        function doHeartbeat() {
            var card = getCookie('card');
            if (!card) return;
            var deviceId = getDeviceId();
            var url = CONFIG.API_URL + '?card=' + encodeURIComponent(card) + '&mac=' + encodeURIComponent(deviceId) + '&app=' + CONFIG.APP_NAME;
            request(url, function(response) {
                var pos = response.indexOf('|sign=');
                if (pos !== -1) response = response.substring(0, pos);
                var parts = response.split('|');
                if (parts[0] === 'ok') {
                    var days = parts[2] || '未知';
                    var minutes = parseInt(parts[3]) || 0;
                    localStorage.setItem('remain_days', days);
                    localStorage.setItem('remain_minutes', minutes);
                    var el = document.getElementById('remainTimeDisplay');
                    if (!el) return;
                    if (days === '永久') {
                        el.textContent = '⏱ 永久有效';
                        el.style.color = '#36d399';
                        return;
                    }
                    if (minutes <= 0) {
                        el.textContent = '⏱ 卡密已过期';
                        el.style.color = '#ff6b6b';
                        return;
                    }
                    var daysNum = Math.floor(minutes / 1440);
                    var hours = Math.floor((minutes % 1440) / 60);
                    var mins = minutes % 60;
                    var text = '';
                    if (daysNum > 0) text += daysNum + '天';
                    if (hours > 0) text += hours + '小时';
                    if (mins > 0) text += mins + '分钟';
                    el.textContent = '⏱ 剩余时间:' + text;
                    el.style.color = '#36d399';
                } else {
                    clearInterval(heartTimer);
                    alert('卡密已失效,请重新验证');
                    deleteCookie('card');
                    localStorage.removeItem('card_verified');
                    localStorage.removeItem('remain_days');
                    localStorage.removeItem('remain_minutes');
                    var remainEl = document.getElementById('remainTimeDisplay');
                    if (remainEl) remainEl.remove();
                    document.getElementById('authBox').style.display = 'flex';
                }
            });
        }

        // 启动心跳(60秒一次)
        var heartTimer = setInterval(doHeartbeat, 60000);
        setTimeout(doHeartbeat, 2000);
    })();
} else {
    // ===== 弹出验证框 =====
    document.write('<div id="authBox" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.92);z-index:999999;display:flex;align-items:center;justify-content:center;font-family:sans-serif;">');
    document.write('<div style="background:#1a202c;padding:40px;border-radius:20px;width:400px;max-width:90%;text-align:center;color:#fff;box-shadow:0 20px 60px rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.06);">');
    document.write('<div style="font-size:56px;margin-bottom:12px;">🔐</div>');
    document.write('<h2 style="font-size:24px;margin-bottom:4px;font-weight:700;">请输入卡密</h2>');
    document.write('<p style="color:#94a3b8;font-size:14px;margin-bottom:24px;">验证通过后才能查看内容</p>');
    document.write('<div id="remainTime" style="color:#36d399;font-size:14px;margin-bottom:12px;"></div>');
    document.write('<input id="cardInput" type="text" placeholder="请输入卡密" style="width:100%;padding:14px 18px;border:2px solid #2d3748;border-radius:12px;background:#111827;color:#fff;font-size:16px;text-align:center;letter-spacing:2px;outline:none;font-family:monospace;box-sizing:border-box;">');
    document.write('<div id="authError" style="color:#ff6b6b;font-size:13px;margin-top:8px;min-height:20px;"></div>');
    document.write('<button id="verifyBtn" style="width:100%;padding:14px 0;border:none;border-radius:12px;font-size:16px;font-weight:600;color:#000;background:linear-gradient(90deg,#4096ff,#36d399);cursor:pointer;margin-top:16px;">验证卡密</button>');
    document.write('</div></div>');

    function getDeviceId() {
        var saved = localStorage.getItem('device_id');
        if (saved) return saved;
        var parts = [screen.width + 'x' + screen.height, screen.colorDepth, navigator.platform, navigator.userAgent];
        try {
            var c = document.createElement('canvas');
            c.width = 256;
            c.height = 64;
            var ctx = c.getContext('2d');
            ctx.fillStyle = '#f60';
            ctx.fillRect(100, 1, 62, 20);
            ctx.fillStyle = '#069';
            ctx.font = '14px Arial';
            ctx.fillText('Keyt.cn', 2, 15);
            parts.push(c.toDataURL());
        } catch(e) {}
        var id = 'web_' + CryptoJS.MD5(parts.join('|')).toString();
        localStorage.setItem('device_id', id);
        return id;
    }

    document.getElementById('verifyBtn').onclick = function() {
        var card = document.getElementById('cardInput').value.trim();
        if (!card) { document.getElementById('authError').textContent = '请输入卡密'; return; }
        document.getElementById('authError').textContent = '';
        this.disabled = true;
        this.textContent = '验证中…';

        var deviceId = getDeviceId();
        var xhr = new XMLHttpRequest();
        xhr.open('GET', CONFIG.API_URL + '?card=' + encodeURIComponent(card) + '&mac=' + encodeURIComponent(deviceId) + '&app=' + CONFIG.APP_NAME);
        xhr.onload = function() {
            var r = xhr.responseText;
            var p = r.indexOf('|sign=');
            if (p !== -1) r = r.substring(0, p);
            var parts = r.split('|');
            if (parts[0] === 'ok') {
                var days = parts[2] || '未知';
                var minutes = parseInt(parts[3]) || 0;
                document.cookie = 'card=' + encodeURIComponent(card) + '; path=/; max-age=' + (30 * 24 * 60 * 60);
                localStorage.setItem('card_verified', 'true');
                localStorage.setItem('remain_days', days);
                localStorage.setItem('remain_minutes', minutes);
                document.getElementById('authBox').style.display = 'none';
                location.reload();
            } else {
                var msgs = {
                    'invalid_card': '卡密无效,请检查是否输入正确',
                    'expired': '卡密已过期',
                    'banned': '卡密已被禁用',
                    'device_mismatch': '设备不匹配',
                    'online_limit_reached': '在线设备数已满',
                    'too_frequent': '验证过于频繁,请稍后再试'
                };
                document.getElementById('authError').textContent = msgs[parts[1]] || '验证失败';
                document.getElementById('verifyBtn').disabled = false;
                document.getElementById('verifyBtn').textContent = '验证卡密';
            }
        };
        xhr.send();
    };

    // Enter键提交
    document.getElementById('cardInput').addEventListener('keydown', function(e) {
        if (e.key === 'Enter') document.getElementById('verifyBtn').click();
    });

    // 自动验证已保存的卡密
    var savedCard = document.cookie.match(new RegExp('(^| )card=([^;]+)'));
    if (savedCard) {
        document.getElementById('verifyBtn').textContent = '自动验证中…';
        document.getElementById('verifyBtn').disabled = true;
        var deviceId = getDeviceId();
        var xhr2 = new XMLHttpRequest();
        xhr2.open('GET', CONFIG.API_URL + '?card=' + encodeURIComponent(savedCard[2]) + '&mac=' + encodeURIComponent(deviceId) + '&app=' + CONFIG.APP_NAME);
        xhr2.onload = function() {
            var r = xhr2.responseText;
            var p = r.indexOf('|sign=');
            if (p !== -1) r = r.substring(0, p);
            if (r.split('|')[0] === 'ok') {
                var parts = r.split('|');
                var days = parts[2] || '未知';
                var minutes = parseInt(parts[3]) || 0;
                localStorage.setItem('card_verified', 'true');
                localStorage.setItem('remain_days', days);
                localStorage.setItem('remain_minutes', minutes);
                document.getElementById('authBox').style.display = 'none';
                location.reload();
            } else {
                document.getElementById('verifyBtn').textContent = '验证卡密';
                document.getElementById('verifyBtn').disabled = false;
                document.getElementById('authError').textContent = '已保存的卡密已失效,请重新输入';
            }
        };
        xhr2.send();
    }
}
</script>

四、功能说明

功能说明
卡密验证 用户输入卡密,调用API验证
设备指纹 基于Canvas生成设备唯一标识
Cookie记忆 验证后记录状态,下次访问自动登录
剩余时间悬浮窗 右上角显示剩余时间,可拖拽移动
心跳保活 每60秒自动验证,卡密过期自动踢出

五、后台管理

注册卡密验证平台后,你会获得一个管理后台,可以:

  • 批量生成卡密:天卡/周卡/月卡/季卡/年卡/终身卡

  • 查看卡密状态:未使用/已激活/已过期/已禁用

  • 禁用/启用卡密:随时控制某张卡密是否有效

  • 使用记录:查看谁在什么时间用了哪张卡密

六、总结

HTML静态网页加卡密验证,纯前端方案最省事:

  • 注册平台账号,获取API信息

  • 复制代码到HTML文件,修改配置

  • 上传服务器,完事

  • 整个接入过程不超过10分钟,不需要后端环境,不需要数据库,适合纯静态网站。

    想要更详细接入教程的话,可以搜索一下卡密通看看官网文档。

    赞(0)
    未经允许不得转载:171主机测评 » HTML静态网页怎么加卡密验证?纯前端方案,粘贴即可用
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址