授权系统/授权代码
返回首页

授权代码

把授权校验接进你的应用:三步接入,含机器指纹上报的完整代码

接入流程

首次接入用卡密激活一次;之后每次启动只调用校验接口
1
首次激活 用卡密调用 auth_apply.php,一次性绑定域名 + 来源 IP + 机器指纹
2
嵌入校验 启动或定时调用 auth_check.php,机器指纹随请求一起上报
3
按结果放行 authorized 为 true 才允许使用,否则提示并退出

接口一览

全部为 POST,Content-Type 用 application/x-www-form-urlencoded
接口用途调用时机
/api/auth_apply.php用卡密激活授权,绑定域名、来源 IP、机器指纹仅首次,一次
/api/auth_check.php校验授权,顺带上报机器指纹与出口 IP每次启动 / 定时
/api/auth_upgrade.php校验「版本升级」独立授权(只校验域名)用到升级功能时
/api/pirate_report.php上报未授权使用的线索(可选)可选

1 · 首次激活

POST /api/auth_apply.php — 只在第一次接入时调用
参数必填说明
auth_code是管理员发给你的卡密,形如 EYE-XXXX-XXXX-XXXX-XXXX,只能用一次
domain_or_ip是你的域名,例如 www.example.com;一个域名只能授权一次
allowed_ip是你服务器的出口 IP(不是访客 IP)。多个用逗号分隔,支持 1.2.3.* 与 1.2.3.0/24
machine_id否机器指纹。这里带上就立刻绑定;不带则等首次校验时自动绑定
POST https://sqkm.sgkami.cn/api/auth_apply.php
  auth_code=EYE-1234-5678-9ABC-DEF0
  domain_or_ip=www.example.com
  allowed_ip=1.2.3.4
  machine_id=2f8a1c...

// 返回
{ "status": "success", "message": "授权成功..." }
{ "status": "error",   "message": "授权失败:授权码无效或已被使用" }

2 · 授权校验

POST /api/auth_check.php — 每次启动都调用,机器指纹从这里上报
参数必填说明
domain_or_ip是你的域名,例如 $_SERVER['SERVER_NAME']
machine_id建议机器指纹。注意:授权已绑定机器指纹后,这里传空值或换了机器都会判为未授权
POST https://sqkm.sgkami.cn/api/auth_check.php
  domain_or_ip=www.example.com
  machine_id=2f8a1c...

// 返回
{ "status": "success", "message": "授权验证通过", "authorized": true }
{ "status": "error",   "message": "未授权或授权已过期", "authorized": false }
三要素怎么分工 域名和机器指纹由客户端上报;来源 IP 由授权服务器自动获取(取 TCP 层的真实连接 IP,无需也不应该在参数里传)。 每次校验都会刷新后台的「最近上报 IP / 机器指纹」,机器指纹为空时会自动绑定(首次信任)。
还没有授权码? 先把校验代码部署上去、访问一次你的站点,管理员的「待授权设备」里就会出现你的域名、出口 IP 和机器指纹, 然后管理员一键建档即可,无需修改代码。

3 · 机器指纹怎么取

直接复制这个函数,Linux / Windows 都能用
function get_machine_id() {
    // 1) Linux(systemd / dbus)
    foreach (array('/etc/machine-id', '/var/lib/dbus/machine-id') as $p) {
        if (@is_readable($p)) {
            $v = trim(@file_get_contents($p));
            if ($v !== '') { return strtolower(preg_replace('/[^0-9A-Za-z]/', '', $v)); }
        }
    }
    // 2) Windows:主板 UUID
    if (stripos(PHP_OS, 'WIN') === 0) {
        // wmic 在新版 Windows 已移除,取不到时退回 PowerShell
        $cmds = array(
            'wmic csproduct get uuid 2>NUL',
            'powershell -NoProfile -Command "(Get-CimInstance Win32_ComputerSystemProduct).UUID" 2>NUL',
        );
        foreach ($cmds as $cmd) {
            $v = @shell_exec($cmd);
            if (!$v) { continue; }
            $v = strtolower(preg_replace('/[^0-9A-Za-z]/', '', str_ireplace('UUID', '', $v)));
            if (strlen($v) >= 8) { return $v; }
        }
    }
    // 3) 兜底:换主机名 / 重装系统后会变,需要在后台「解绑」后重新绑定
    return strtolower(md5(php_uname('n') . '|' . php_uname('m')));
}
读不到机器指纹时不要传空值 @file_get_contents() 失败会返回空字符串。如果授权已经绑定了机器指纹, 传空值会被判为「机器不匹配」而整站显示未授权。请确保 get_machine_id() 一定有返回值(上面第 3 条的兜底逻辑就是为此)。

4 · 完整 PHP 示例

复制即可用:激活 + 校验 + 超时保护 + 机器指纹
<?php
// ================= 授权系统接入 =================
// 授权服务器地址写死,不要用 $_SERVER['HTTP_HOST'](那是你自己的域名)
define('LICENSE_API', 'https://sqkm.sgkami.cn/api');
// 你的卡密,激活成功后可以删掉这一行
define('LICENSE_CARD', 'EYE-XXXX-XXXX-XXXX-XXXX');

function get_machine_id() {
    foreach (array('/etc/machine-id', '/var/lib/dbus/machine-id') as $p) {
        if (@is_readable($p)) {
            $v = trim(@file_get_contents($p));
            if ($v !== '') { return strtolower(preg_replace('/[^0-9A-Za-z]/', '', $v)); }
        }
    }
    if (stripos(PHP_OS, 'WIN') === 0) {
        // wmic 在新版 Windows 已移除,取不到时退回 PowerShell
        $cmds = array(
            'wmic csproduct get uuid 2>NUL',
            'powershell -NoProfile -Command "(Get-CimInstance Win32_ComputerSystemProduct).UUID" 2>NUL',
        );
        foreach ($cmds as $cmd) {
            $v = @shell_exec($cmd);
            if (!$v) { continue; }
            $v = strtolower(preg_replace('/[^0-9A-Za-z]/', '', str_ireplace('UUID', '', $v)));
            if (strlen($v) >= 8) { return $v; }
        }
    }
    return strtolower(md5(php_uname('n') . '|' . php_uname('m')));
}

function license_post($path, $data) {
    $ch = curl_init(LICENSE_API . $path);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);        // 必须设超时,否则授权服务器故障会拖死你的站
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
    $raw = curl_exec($ch);
    curl_close($ch);
    $json = json_decode((string) $raw, true);
    return is_array($json) ? $json : array('authorized' => false, 'message' => '授权服务器无响应');
}

// 首次激活(只调用一次,成功后可以删掉这段)
function license_activate($code, $domain, $allowed_ip, $machine_id) {
    return license_post('/auth_apply.php', array(
        'auth_code'    => $code,
        'domain_or_ip' => $domain,
        'allowed_ip'   => $allowed_ip,
        'machine_id'   => $machine_id,
    ));
}

// 授权校验
function license_check($domain, $machine_id) {
    return license_post('/auth_check.php', array(
        'domain_or_ip' => $domain,
        'machine_id'   => $machine_id,
    ));
}

// ================= 使用 =================
$domain     = $_SERVER['SERVER_NAME'];
$machine_id = get_machine_id();

// 第一次部署时解除下面两行注释,激活一次即可(把出口 IP 换成你服务器的)
// $r = license_activate(LICENSE_CARD, $domain, '1.2.3.4', $machine_id);
// if ($r['status'] !== 'success') { echo '激活失败:' . $r['message']; exit; }

$r = license_check($domain, $machine_id);
if (empty($r['authorized'])) {
    echo '未授权使用!请联系管理员获取授权。';
    exit;
}

5 · Python 示例

import hashlib, platform, re, socket, subprocess, sys
import requests

LICENSE_API  = 'https://sqkm.sgkami.cn/api'
DOMAIN       = 'www.example.com'
LICENSE_CARD = 'EYE-XXXX-XXXX-XXXX-XXXX'

def get_machine_id() -> str:
    for p in ('/etc/machine-id', '/var/lib/dbus/machine-id'):
        try:
            with open(p) as f:
                v = f.read().strip()
            if v:
                return re.sub(r'[^0-9A-Za-z]', '', v).lower()
        except OSError:
            pass
    if sys.platform.startswith('win'):
        cmds = [['wmic', 'csproduct', 'get', 'uuid'],
                ['powershell', '-NoProfile', '-Command',
                 '(Get-CimInstance Win32_ComputerSystemProduct).UUID']]
        for cmd in cmds:                      # wmic 在新版 Windows 已移除
            try:
                out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL, text=True)
                v = re.sub(r'[^0-9A-Za-z]', '', out.replace('UUID', '')).lower()
                if len(v) >= 8:
                    return v
            except Exception:
                continue
    return hashlib.md5((socket.gethostname() + '|' + platform.machine()).encode()).hexdigest()

def license_post(path: str, data: dict) -> dict:
    r = requests.post(f'{LICENSE_API}{path}', data=data, timeout=5)
    return r.json()

def license_check(machine_id: str) -> dict:
    return license_post('/auth_check.php',
                        {'domain_or_ip': DOMAIN, 'machine_id': machine_id})

# 首次激活(只跑一次)
# print(license_post('/auth_apply.php', {'auth_code': LICENSE_CARD, 'domain_or_ip': DOMAIN,
#                                        'allowed_ip': '1.2.3.4', 'machine_id': get_machine_id()}))

if not license_check(get_machine_id()).get('authorized'):
    print('未授权使用!请联系管理员获取授权。')
    raise SystemExit(1)

6 · 常见坑

坑后果正确做法
接口地址用 $_SERVER['HTTP_HOST'] 拼请求打到你自己站上,永远返回未授权写死授权服务器地址
curl 不设超时授权服务器抖动时你的站跟着挂设 CURLOPT_TIMEOUT = 5
机器指纹读不到时传空已绑定的授权整站显示未授权用上面的兜底逻辑保证有值
allowed_ip 填了访客 IP校验时来源 IP 不匹配,判定未授权填服务器出口 IP,多台用逗号分隔
中途改了机器指纹的取值方式指纹变了,校验直接失败先在后台「解绑」,再让客户站重新上报
同一域名授权两条记录第二条会被拒绝创建一个域名一条授权,先删旧的再加新的
升级功能单独授权auth_upgrade.php 只校验域名,不看机器指纹升级授权是否开通、到期在后台单独控制