PHP如何改造Vue项目中的API解码文件?

前后端开发时,往往由后端提供API,且该API需要经过一些Header或者Token设置,方能正确请求并解码参数,此方法既能保护API不被暴露,也能一定程度保护项目不被恶意逆向破解,影响运行。

前端即可采用Vue也可以采用PHP的方式,两种解码所需参数都一样,但都有各自的处理方式,

Vue的处理的方式如,(核心处理):

// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use((config) => {
    console.log(navigator.userAgent);
    if (config.url.indexOf("notMask") === -1) {
      // store.commit('requestBegin');
    }

    const deviceId = encryptPassword(getUniqueDeviceIdentifier());
    const authToken = localStorage.getItem('authToken') || '';
    const ts = new Date().getTime();
    const token = handleLocalStorage('get', 'HLJXCXTOKEN')

    // 设置请求头
    // 优先使用用户传入的 Content-Type,否则使用默认值
    if (!config.headers['Content-Type']) {
      config.headers['Content-Type'] = 'application/json;charset=utf-8';
    }
    config.headers["accesskey"] = "q878s0"; //请求头签名
    config.headers["pId"] = handleLocalPID()
    //从缓存中获取语言
    config.headers['lang'] = handleLangType()==='zh' ? 'zh' : handleLangType()
    config.headers['countryCode'] = 'ZH-CN'
    config.headers['channel'] = 'WEBH5'
    config.headers['version'] = '1.0.01'
    config.headers['system'] = 'WEBH5'
    // config.headers['timezone'] = 'UTC/GMT+08:00'
    config.headers['timezone'] = '8'
    config.headers['platform'] = PLATFORM()
    config.headers['versionCode'] = '1.0.01'
    config.headers['deviceToken'] = 'WEBH5'
    config.headers['phonesystem'] = 'WEBH5'
    config.headers['deviceId'] = deviceId
    config.headers['idfa'] = ''
    config.headers['oaid'] = ''
    config.headers['appmarketid'] = ''
    config.headers['authToken'] = authToken
    config.headers['ts'] = ts
    // 设置签名
    if (config.url) {
      config.headers['sign'] = sign(config.url, deviceId, ts)
    }
    // 设置token
    if (token) {
      config.headers['authToken'] = token
    }
    return config
  }, (error) => {
    // store.commit('requestComplete');
    console.error(" 请求失败,服务器错误");
    return Promise.reject(error);
  });
// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(async (response) => {
    // store.commit('requestComplete');
    let res = response.data;
    // 兼容服务端返回的字符串数据
    if (typeof res === "string") {
      res = res ? JSON.parse(res) : res;
    } else {
      if (res.data == null || res.data === "") {
        res.data = null;
      } else {
        // console.log(res.data);
        let bb = requestDecrypt(res.data);
        const gzipData = atob(bb)
          .split("")
          .map((char) => char.charCodeAt(0));
        const gzipArray = new Uint8Array(gzipData);
        const uncompressedData = pako.inflate(gzipArray);
        res.data = new TextDecoder().decode(uncompressedData);
        res.data = JSON.parse(res.data);
      }
      switch (res.code) {
        case 1013:
          //移除Token
              localStorage.removeItem('authToken');
          //移除用户信息
          localStorage.removeItem('USER_PROFILE');
          return;
      }
    }
    return res;
  },
  (error) => {
    // store.commit('requestComplete');
    console.error(" 请求失败,服务器错误");
    return Promise.reject(error);
  }
);

PHP的处理的方式如,(核心处理):

<?php
/**
 * Request proxy wrapper for theme templates.
 *
 * 说明:集中封装访问远端 VDAPI 服务时的公共逻辑:
 * - 组装设备信息 / 签名
 * - 构建统一请求头
 * - 调用 wp_remote_request 并处理错误
 * - 对响应数据执行解密与解析
 */

require_once get_template_directory() . '/api/Function.php';


class RequestProxy
{
    /** 默认目标服务 base url */
    private const DEFAULT_TARGET_BASE = 'http://apitest.xxxx.cc';

    /** @var string */
    private $targetBase;

    public function __construct(?string $targetBase = null)
    {
        $base = $targetBase ?: self::DEFAULT_TARGET_BASE;
        $this->targetBase = rtrim($base, '/');
    }

    /**
     * 对指定 path 发起 GET 请求,并返回统一结构。
     *
     * @param string $path 目标接口路径(可含 query)
     * @param string $deviceIdRaw 客户端 base64 原文(可为空)
     * @param array $extraHeaders 额外 header
     * @return array
     */
    public function get(string $path, string $deviceIdRaw = '', array $extraHeaders = []): array
    {
        $path = $this->normalizePath($path);
        $forwardUrl = $this->targetBase . $path;

        $deviceId = $this->resolveDeviceId($deviceIdRaw);
        $ts = (string) round(microtime(true) * 1000);
        $sign = RequestHelper::sign($path, $deviceId, $ts, 'm94icx7kiq67');

        $headers = $this->buildHeaders($deviceId, $ts, $sign, $extraHeaders);

        $response = wp_remote_request($forwardUrl, [
            'method' => 'GET',
            'headers' => $headers,
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return [
                'code' => 1,
                'msg' => 'request_error',
                'data' => [
                    'error' => $response->get_error_message(),
                    'debug' => ['deviceId' => $deviceId, 'ts' => $ts, 'sign' => $sign],
                ],
                'currentTime' => (int) $ts,
            ];
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);

        return RequestHelper::parseAndDecryptResponse($body, $deviceId, $ts, $sign);
    }

    /**
     * 对指定 path 发起 POST 请求,并返回统一结构。
     *
     * @param string $path 目标接口路径(可含 query)
     * @param string $deviceIdRaw 客户端 base64 原文(可为空)
     * @param array $extraHeaders 额外 header
     * @param array $postData POST 数据(将作为 JSON 发送)
     * @return array
     */
    public function post(string $path, string $deviceIdRaw = '', array $extraHeaders = [], array $postData = []): array
    {
        $path = $this->normalizePath($path);
        $forwardUrl = $this->targetBase . $path;

        $deviceId = $this->resolveDeviceId($deviceIdRaw);
        $ts = (string) round(microtime(true) * 1000);
        $sign = RequestHelper::sign($path, $deviceId, $ts, 'm94icx7kiq67');

        $headers = $this->buildHeaders($deviceId, $ts, $sign, $extraHeaders);

        $response = wp_remote_request($forwardUrl, [
            'method' => 'POST',
            'headers' => $headers,
            'body' => json_encode($postData, JSON_UNESCAPED_UNICODE),
            'timeout' => 30,
        ]);

        if (is_wp_error($response)) {
            return [
                'code' => 1,
                'msg' => 'request_error',
                'data' => [
                    'error' => $response->get_error_message(),
                    'debug' => ['deviceId' => $deviceId, 'ts' => $ts, 'sign' => $sign],
                ],
                'currentTime' => (int) $ts,
            ];
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);

        return RequestHelper::parseAndDecryptResponse($body, $deviceId, $ts, $sign);
    }

    /**
     * 便捷方法:发起 GET 请求(自动处理 deviceId),类似于 JS 的 requestGetList。
     *
     * @param string $path 目标接口路径(可含 query)
     * @param array $extraHeaders 额外 header
     * @return array
     */
    public function requestGetList(string $path, array $extraHeaders = []): array
    {
        return $this->get($path, '', $extraHeaders);
    }

    /**
     * 便捷方法:发起 POST 请求(自动处理 deviceId),类似于 JS 的 requestPostList。
     *
     * @param string $path 目标接口路径(可含 query)
     * @param array $extraHeaders 额外 header
     * @param array $postData POST 数据(将作为 JSON 发送)
     * @return array
     */
    public function requestPostList(string $path, array $extraHeaders = [], array $postData = []): array
    {
        return $this->post($path, '', $extraHeaders, $postData);
    }

    private function buildHeaders(string $deviceId, string $ts, string $sign, array $extra = []): array
    {
        $baseHeaders = [
            'Accept' => 'application/json, text/plain, */*',
            'Content-Type' => 'application/json;charset=utf-8',
            'accesskey' => 'q878s0',
            'pId' => 'lVFFFvztVU',
            'lang' => 'zh',
            'countryCode' => 'ZH-CN',
            'channel' => 'WEBH5',
            'version' => '1.0.01',
            'system' => 'WEBH5',
            'timezone' => '8',
            'platform' => 'WEBH5',
            'versionCode' => '1.0.01',
            'deviceToken' => 'WEBH5',
            'phonesystem' => 'WEBH5',
            'deviceId' => $deviceId,
            'idfa' => '',
            'oaid' => '',
            'appmarketid' => '',
            'authToken' => '',
            'ts' => $ts,
            'sign' => $sign,
            'X-Ts' => $ts,
            'X-Device' => $deviceId,
            'X-Sign' => $sign,
        ];

        return array_merge($baseHeaders, $extra);
    }

    private function normalizePath(string $path): string
    {
        $path = trim($path);
        if ($path === '') {
            $path = '/';
        }
        if ($path[0] !== '/') {
            $path = '/' . $path;
        }
        return $path;
    }

    private function resolveDeviceId(string $deviceIdRaw): string
    {
        $deviceIdRaw = trim($deviceIdRaw);
        if ($deviceIdRaw !== '') {
            return md5($deviceIdRaw);
        }

        $host = gethostname();
        $serverAddr = $_SERVER['SERVER_ADDR'] ?? '127.0.0.1';
        return md5($host . '-' . $serverAddr);
    }
}

 

posted @ 2025-11-27 13:55  coderjim  阅读(5)  评论(0)    收藏  举报

更多知识请点击——

www.7017online.xyz