在做接口開發的時候,有時候需要提高一些接口安全性方面的工作,比如給接口添加簽名等等。本文主要是我自己以前用過的接口簽名的方式,放出來讓大家見笑見笑。
MD5版
為了實現簡單的MD5簽名驗證,我主要分三步走。
1. 創建文件
打開命令行,運行命令創建中間件。
php artisan make:middleware VerifyApiSign
創建成功后,可以在App\Http\Middleware目錄下找到它。
2. 擼代碼
不會擼代碼沒關系,這里可以使用魔法:選中內容,然后Ctrl+C→打開VerifyApiSign.php文件→Ctrl+V。嗯,保存退出。
<?php
namespace App\Http\Middleware;
use Carbon\Carbon;
use Closure;
/**
* 接口簽名
*
* @author Wenhsing <wenhsing@qq.com>
*/
class VerifyApiSign
{
// 忽略列表
protected $except = [
//
];
// 時間誤差
protected $timeError = 5;
// 密鑰
protected $secretKey = '';
// 簽名字段
protected $signField = 'sign';
public function __construct()
{
$this->secretKey = config('auth.api_sign.secret_key', '');
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (
$this->inExceptArray($request)
|| ($this->allowTimestamp($request) && $this->signMatch($request))
) {
return $next($request);
}
throw new \Exception('Signature error');
}
/**
* 判斷當前請求是否在忽略列表中
*
* @author Wenhsing <wenhsing@qq.com>
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function inExceptArray($request)
{
foreach ($this->except as $except) {
if ($except !== '/') {
$except = trim($except, '/');
}
if ($request->fullUrlIs($except) || $request->is($except)) {
return true;
}
}
return false;
}
/**
* 判斷用戶請求是否在對應時間范圍
*
* @author Wenhsing <wenhsing@qq.com>
*
* @param \Illuminate\Http\Request $request
* @return boolean
*/
protected function allowTimestamp($request)
{
$queryTime = Carbon::createFromTimestamp($request->query('timestamp', 0));
$lfTime = Carbon::now()->subSeconds($this->timeError);
$rfTime = Carbon::now()->addSeconds($this->timeError);
if ($queryTime->between($lfTime, $rfTime, true)) {
return true;
}
return false;
}
/**
* 簽名驗證
*
* @author Wenhsing <wenhsing@qq.com>
*
* @param \Illuminate\Http\Request $request
* @return void
*/
protected function signMatch($request)
{
$data = $request->query();
// 移除sign字段
if (isset($data['sign'])) {
unset($data['sign']);
}
ksort($data);
$sign = '';
foreach ($data as $k => $v) {
if ($this->signField !== $k) {
$sign .= $k . $v;
}
}
if (md5($sign . $this->secretKey) === $request->query($this->signField, null)) {
return true;
}
return false;
}
}
3. 修改配置文件
打開config/auth.php修改配置文件,在配置后面添加我們的接口簽名驗證相關參數
<?php
return [
// 這里省略了一些代碼
/*
|--------------------------------------------------------------------------
| Api Signature configuration
|--------------------------------------------------------------------------
*/
'api_sign' => [
// 你的密鑰串
'secret_key' => env('API_SIGN_SECRET_KEY', ''),
],
];
打開App\Http\Kernel.php文件,在路由中間件組中的api字段中添加我們之前創建的中間件
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
// 這里省略了其他代碼
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
// 這里省略了其他代碼
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
// 接口簽名中間件
\App\Http\Middleware\VerifyApiSign::class,
],
];
// 這里省略了其他代碼
}
好了,你的接口就可以進行簡單的接口簽名驗證了。其他類型的驗證,之后再說。。。
