多系统对接-签名校验案例

多系统对接-签名校验案例

config/Sign.php

<?php

// 第三方平台调用『当前系统』接口的签名密钥
return [
    // 签名生命周期设置,单位秒
    'sign_ttl' => env('SIGN_TTL', 600),

    // 签名类型
    'sign_type_xxx' => 'xxx', //  xxx系统
    'sign_type_test' => 'test', //  test系统

    // 密钥
    'sign_type_secret' => [
        'xxx' => env('SIGN_SECRET_XXX', 'test_123456'),
        'test' => env('SIGN_SECRET_TEST', 'test_123456'),
    ],
];

app/Services/AuthSign.php

<?php

namespace App\Services;

// 第三方平台请求的签名校验
class AuthSign
{
    /**
     * 签名校验
     * @param string $signType 签名类型,对接哪个第三方系统的标识
     * @param string $sign 签名
     * @param int $requestTime 请求时间戳
     * @return array
     */
    public static function checkSign(string $signType, string $sign, int $requestTime): array
    {
        // 签名类型:新增对外接口签名类型时,需要去配置新的签名类型和密钥
        $signSecret = config('sign.sign_type_secret')[$signType] ?? '';

        if ($signSecret == '') {
            return ['result' => false, 'msg' => '该签名类型还没配置'];
        }

        if ($sign != md5("{$requestTime}-{$signType}-{$signSecret}")) {
            return ['result' => false, 'msg' => '签名有误'];
        }

        $currentTime = time();
        if ($currentTime < $requestTime || ($currentTime-$requestTime) > config('sign.sign_ttl')) {
            return ['result' => false, 'msg' => '签名已过期'];
        }

        return ['result' => true, 'msg' => '签名校验成功'];
    }

    /**
     * 生成签名
     * @param string $signType 签名类型,对接哪个第三方系统的标识
     * @return array
     */
    public static function getSign(string $signType): array
    {
        $signSecret = config('sign.sign_type_secret')[$signType] ?? '';
        if ($signSecret == '') {
            return ['result' => false, 'msg' => '该签名类型还没配置'];
        }
        $requestTime = time();
        return ['result' => true, 'time' => $requestTime, 'sign' => md5("{$requestTime}-{$signType}-{$signSecret}")];
    }
}

app/Http/Middleware/AuthSignTest.php

<?php

namespace App\Http\Middleware;

use App\Facades\Response;
use Symfony\Component\HttpFoundation\Response as FoundationResponse;
use Closure;

// 『test系统』请求『当前系统』接口的签名校验
class AuthSignTest
{
    public function handle($request, Closure $next)
    {
        $sign = $request->header('sign') ?: '';
        $time = $request->header('time') ? : '';

        if (empty($sign) || empty($time)) {
            return Response::fail('传参有误', [], FoundationResponse::HTTP_UNAUTHORIZED);
        }

        $signData = \App\Services\AuthSign::checkSign(config('sign.sign_type_test'), $sign, (int)$time);
        if (!$signData['result']) {
            return Response::fail("sign校验失败:{$signData['msg']}", [], FoundationResponse::HTTP_UNAUTHORIZED);
        }

        return $next($request);
    }
}

app/Http/Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    // 注册中间件
    protected $routeMiddleware = [
        'auth.test' => \App\Http\Middleware\AuthSignTest::class,
    ];
}

routes/api_sign.php

<?php

// 路由使用签名做校验
Route::group(['prefix' => 'mini', 'middleware' => ['auth.test', 'request.log'], 'namespace' => 'test'], function () {
    Route::put('xxx', 'SignController@setXXX');
});
本作品采用《CC 协议》,转载必须注明作者和本文链接
编程就像呼吸,学会那天起一日不敢荒废。
ZsmHub
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!