AuthDeviceController.php 5.76 KB
<?php

namespace app\api\controllers;

use Yii;
use common\exts\RSACrypt;
use common\exts\Aes;
use common\helpers\Utils;
use common\helpers\Log as AppLog;
use domain\device\Device;

use stdClass;

use function date;
use function count;
use function time;

/**
 * 设备授权-控制器
 * Class AuthDeviceController
 * @package app\api\controllers
 *  manufacture	厂商ID	string	是个数字字符串,例如“001”代表 XX厂商
    device_id	设备id	string	设备的ID
    project	项目ID	string	项目ID
    model	型号ID	string	例如 001
    timestamp	时间戳	int	例如 2019-10-10 01:01:01
    sign	签名	string	用来认证请求是否合法 签名组合为 md5(manufacture + project+  model + production + timestamp + salt) salt 为客户端和服务器约定的key
    production	生产日期ID	string	日期 例如001
 *
 */
class AuthDeviceController extends BaseController
{
    private static $SIGN_SALT = '13456';
    private static $RANDOM_KEY_SALT = '12356';

    private static function myLog($str)
    {
        AppLog::DEBUG($str);
    }

    /**
     * 设备授权接口,未加密的
     * @return stdClass
     */
    private function indexNoEncode()
    {
        $getPostData = file_get_contents('php://input', 'r');
        self::myLog('actionIndex postData:'.$getPostData);

        return $this->authDevice($getPostData);
    }

    /**
     * 设备授权接口加密过的
     * @return stdClass
     */
    public function actionIndex()
    {
        $e = new stdClass();
        $e->content = '';

        $getPostData = file_get_contents('php://input', 'r');
        self::myLog('actionIndext postData:'.$getPostData);
        $getPostData = json_decode($getPostData, true);
        $randomKey = $getPostData['randomKey'];
        $content = $getPostData['content'];
        $rsaKeys = Yii::$app->params['AUTH_DEVICE_RSA_PKCS_1'];
        $rsa = new RSACrypt($rsaKeys['PRIVATE'], $rsaKeys['PUBLIC']);
        $randKey = $rsa->decrypt($randomKey);
        if (16 != strlen($randKey)) {
            // 检查randKey,当前只是做长度判断
            $randKey = null;
        } else {
            $randKey = substr(md5($randKey. self::$RANDOM_KEY_SALT), 8, 16);
        }

        $aes = new Aes($randKey);
        $contentStr = $aes->decrypt($content);
        $authResult = $this->authDevice($contentStr);

        $returnStr = json_encode($authResult, JSON_UNESCAPED_UNICODE);
        $e->content = $aes->encrypt($returnStr);

        return $e;
    }

    /**
     * @param $getPostData
     * @return stdClass
     */
    private function authDevice($getPostData)
    {
        $e = new stdClass();
        $e->status = 1;
        $e->message = 'message';
        $e->serial_no = '';;
        $e->mac = '';

        $getPostData     = json_decode($getPostData, true);
        if (empty($getPostData)) {
            $e->status = 1;
            $e->message = '传入的数据为空';
            return $e;
        }
        $manufactureNo	= isset($getPostData['manufacture'])?$getPostData['manufacture']:'';
        $deviceId	    = isset($getPostData['device_id'])?$getPostData['device_id']:'';
        $projectNo	    = isset($getPostData['project'])?$getPostData['project']:'';
        $modelNo	    = isset($getPostData['model'])?$getPostData['model']:'';
        $productionNo	= isset($getPostData['production'])?$getPostData['production']:'';
        $timestamp       = isset($getPostData['timestamp'])?$getPostData['timestamp']:'';
        $sign	        = isset($getPostData['sign'])?$getPostData['sign']:'';
        if (empty($deviceId) || empty($manufactureNo) || empty($projectNo) || empty($modelNo) || empty($productionNo)) {
            $e->message = '传入的数据部分为空';
            return $e;
        }
        $pattern = "/^[a-zA-Z0-9]+$/";
        $dexPattern = "/^[0-9a-fA-F]+$/";
        if (!preg_match($pattern, $deviceId) || !preg_match($dexPattern, $manufactureNo) || !preg_match($dexPattern, $modelNo) || !preg_match($dexPattern, $productionNo)) {
            $e->status = 9;
            $e->message = '传入的数据字段格式不对';
            return $e;
        }
        if (isset(Yii::$app->params['secretKey']) && !empty(Yii::$app->params['secretKey'])) {
            $salt = Yii::$app->params['secretKey'];
        } else {
            $salt = isset(Yii::$app->params['secretKey'])? Yii::$app->params['secretKey']: self::$SIGN_SALT;
        }

        $makeSign = md5($manufactureNo . $projectNo. $modelNo . $productionNo . $timestamp . $deviceId. $salt);
        if ($sign != $makeSign || empty($sign)) {
            $e->status = 2;
            $e->message = '签名出错';
            return $e;
        }

        $authResult = Device::authDevice($deviceId, $manufactureNo, $projectNo, $modelNo, $productionNo);

        $e->status = $authResult->status;
        $e->message = $authResult->message;
        if ($authResult->success) {
            $e->mac = $authResult->mac;
            $e->serial_no = $authResult->serial_no;
        }

        return $e;
    }

    /**
     *
     */
    public function actionCryptTxt()
    {
        $e = new stdClass();

        $getPostDataTxt    = file_get_contents('php://input', 'r');
        $getPostData    = json_decode($getPostDataTxt, true);
        $randomKey = $getPostData['randomKey'];
        $content = $getPostData['content'];
        $rsaKeys = Yii::$app->params['AUTH_DEVICE_RSA_PKCS_1'];
        $rsa = new RSACrypt($rsaKeys['PRIVATE'], $rsaKeys['PUBLIC']);

        $randKey = $rsa->decrypt($randomKey);
        $aes = new Aes($randKey);
        $contentStr = $aes->decrypt($content);

        $returnContent = [
            "mac" => Utils::macGenerate(),
            "serial_no" => Utils::rand(16),
            'random_key'  =>$randKey,
        ];

        $e->content = $aes->encrypt(json_encode($returnContent));

        return $e;
    }

}