config/Sign.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?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

1
2
3
4
5
6
<?php

// 路由使用签名做校验
Route::group(['prefix' => 'mini', 'middleware' => ['auth.test', 'request.log'], 'namespace' => 'test'], function () {
    Route::put('xxx', 'SignController@setXXX');
});