實作
過濾函式
新增 app/Helpers/Helper.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
| <?php
namespace App\Helpers;
class Helper { static function sanitize($data) { $fields = ['password', 'secret', 'token'];
if (is_array($data)) { foreach ($data as $key => $value) { if (is_array($value)) { $data[$key] = self::sanitize($value, $fields); } foreach ($fields as $field) { if (stripos($key, $field) !== false) { $data[$key] = '******'; } } } }
return $data; } }
|
建立中介層
建立 app/Http/Middleware/AssignRequestId.php
檔,為所有日誌添加共用的 REQUEST_ID
資訊。
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
| <?php
namespace App\Http\Middleware;
use Closure; use Illuminate\Http\Request; use Illuminate\Support\Str; use Illuminate\Support\Facades\Log; use Symfony\Component\HttpFoundation\Response;
class AssignRequestId {
public function handle(Request $request, Closure $next): Response { $requestId = (string) Str::uuid();
Log::withContext([ 'REQUEST_ID' => $requestId ]);
$request->headers->set('Request-Id', $requestId);
return $next($request); } }
|
建立 app/Http/Middleware/LogRequestResponse.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
| <?php
namespace App\Http\Middleware;
use App\Helpers\Helper; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Symfony\Component\HttpFoundation\Response;
class LogRequestResponse {
public function handle(Request $request, Closure $next): Response { $response = $next($request);
Log::info('LOG_REQUEST_RESPONSE', [ 'REQUEST_METHOD' => $request->method(), 'REQUEST_URL' => $request->url(), 'REQUEST_BODY' => Helper::sanitize(json_decode(str_replace("\\n", '', $request->getContent()), true)), 'RESPONSE_STATUS' => $response->getStatusCode(), 'RESPONSE_BODY' => Helper::sanitize(json_decode(str_replace("\\n", '', $response->getContent()), true)), 'TIME' => now(), ]);
return $response; } }
|
修改 app/Http/Kernel.php
檔,將中介層添加到 api
列表中。
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
| <?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel {
protected $middlewareGroups = [
'api' => [ \App\Http\Middleware\AssignRequestId::class, \App\Http\Middleware\LogRequestResponse::class, ], ];
}
|
建立監聽器
建立 app/Listeners/LogRequestSending.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
| <?php
namespace App\Listeners;
use App\Helpers\Helper; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Support\Facades\Log;
class LogRequestSending {
public function __construct() { }
public function handle(object $event): void { $request = $event->request;
Log::info('LOG_REQUEST_SENDING', [ 'REQUEST_METHOD' => $request->method(), 'REQUEST_URL' => $request->url(), 'REQUEST_BODY' => Helper::sanitize(json_decode(str_replace("\\n", '', $request->body()), true)), 'TIME' => now(), ]); } }
|
建立 app/Listeners/LogResponseReceived.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
| <?php
namespace App\Listeners;
use App\Helpers\Helper; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Support\Str; use Illuminate\Support\Facades\Log;
class LogResponseReceived {
public function __construct() { }
public function handle(object $event): void { $request = $event->request;
$response = $event->response;
Log::info('LOG_RESPONSE_RECEIVED', [ 'REQUEST_METHOD' => $request->method(), 'REQUEST_URL' => $request->url(), 'REQUEST_BODY' => Helper::sanitize(json_decode(str_replace("\\n", '', $request->body()), true)), 'RESPONSE_STATUS' => $response->status(), 'RESPONSE_BODY' => Helper::sanitize(json_decode(str_replace("\\n", '', $response->body()), true)), 'TIME' => now(), ]); } }
|
修改 app/Providers/EventServiceProvider.php
檔,將監聽器添加到 listen
列表中。
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
| <?php
namespace App\Providers;
use App\Listeners\LogRequestSending; use App\Listeners\LogResponseReceived; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Http\Client\Events\RequestSending; use Illuminate\Http\Client\Events\ResponseReceived; use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider {
protected $listen = [ Registered::class => [ SendEmailVerificationNotification::class, ], RequestSending::class => [ LogRequestSending::class, ], ResponseReceived::class => [ LogResponseReceived::class, ], ];
public function boot(): void { }
public function shouldDiscoverEvents(): bool { return false; } }
|
參考資料