Laravel에서 API 호출 제한 설정 - 섹션 2

7230 단어 apilaravelrestphp
API 요청 제한 시리즈의 두 번째 부분에서 나는 API 단점에 대한 사용자의 요청을 추적하고 사용자의 권한에 따라 제한을 설정하는 사용자 정의 중간부품을 깊이 있게 구축할 것이다.이전 부분에 대한 알림으로, 우리는 사용자를 위해 공공 API를 구축하여 데이터를 얻고 있습니다. 이 사용자들은 서로 다른 구독 층으로 나뉘어져 있으며, 일부 층에 대해서는 시간의 추이에 따라 그들의 API에 대한 접근을 제한해야 합니다.기왕 우리가 모두 따라잡았으니 우리 시작합시다.

이게 어떻게 된 일입니까


정상적으로 작동하기 위해서, 우리는 응용 프로그램의 세 가지 부분인 API, 데이터베이스, 중간부품을 고려해야 한다.이러한 방법은 이전 글에서 사용한 방법과 조금 다르다. 왜냐하면 우리는 사용자가 요청한 정보를 데이터베이스에 저장하는 것이지, 속도제한기를 사용하여 백엔드 제한을 하는 것이 아니기 때문이다.이러한 방식을 통해 우리는 미래 사용 요청에 대한 더 많은 정보를 얻을 수 있으며, 귀하는 본문 말미에 보실 수 있습니다.

데이터베이스 구축


우선, 우리는 우리의 요청을 위해 데이터베이스 테이블과 Laravel 모델을 만들어야 한다.우리는 하나의artisan 명령을 통해 이 점을 실현할 것이다.
php artisan make:model Request --migration
이렇게 하면 요청 모델과 create requests 테이블 마이그레이션이 생성됩니다.내 데이터베이스에는 요청 id, 주어진 노드의 API 영패 호출, 이 노드를 호출한 사용자 id, 요청한 날짜와 시간, 사용자가 호출한 URI 열이 있습니다.영패와 사용자 id는users표의 같은 줄을 인용하기 때문에 두 번째 줄은 좀 여분합니다. 그러나 API를 만들 때 이 문제를 해결하고 싶지 않기 때문에 기존의 것을 계속 사용할 것입니다.마이그레이션 함수는 다음과 같습니다.
    public function up()
    {
        Schema::create('requests', function (Blueprint $table) {
            $table->id();
            $table->string('token');
            $table->integer('user_id');
            $table->datetime('date');
            $table->string('content');
            $table->foreign('user_id')
                       ->references('id')
                       ->on('users');
            $table->foreign('token')
                       ->references('api_token')
                       ->on('users');
        });
    }
모델에 대해 말하자면 이것은 매우 간단하다.시간 스탬프를 사용하지 않는 것은 테이블의 줄이 업데이트되지 않을 뿐만 아니라, 날짜열에 요청한 날짜 시간을 제공했기 때문입니다.우리는 또한 id를 제외한 모든 열을 채울 수 있도록 한다.
// app/Models/Request.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Request extends Model
{

    public $timestamps = false;

    protected $fillable = [
        'token',
        'user_id',
        'date',
        'content'
    ];
}

중간부품 설정


현재 우리는 이미 데이터베이스 층을 설정했기 때문에 우리는 계속 중간부품을 만들 수 있다.요청은 API 토큰을 통해 API를 호출하는 사용자와 연관되기 때문에 사용자와 요청 모델을 참조합니다.이전 부분과 마찬가지로, 우리는 캐리어 영패를 사용하여 사용자에게 신분 검증을 한다.last article에서 논의한 구독 기반의 공공 API 모델을 계속하기 위해 일부 사용자 그룹에 대해 요청 제한을 설정할 것입니다.이번에는 무료 계층 사용자는 매일 API에 한 개만 요청할 수 있고, 가입한 사용자는 무한한 수량의 요청을 할 수 있다.우선 중간부품을 살펴보자.
// app/Http/Middleware/AccessLevel.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Carbon;
use App\Models\Request as ApiRequest;

class AccessLevel
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {

        $token = $request->bearerToken();
        if (User::where('api_token', $token)->exists()) {
            $user = User::where('api_token', $token)->first();
        } else {
            return response()
                ->json(['error' => 'Bad token'], 401);
        }

        if ($user->access == 0) {
            if ($this->checkLimit($token, today())) {
                return response()
                ->json(['error' => 'Daily call limit exceeded'], 429);
            }
        }
        ApiRequest::create([
            'token' => $token,
            'user_id' => $user->id,
            'date' => Carbon::now(),
            'content' => $request->url()
        ]);
        return $next($request);

    }

    private function checkLimit($token, $date)
    {

        if (ApiRequest::where('token', $token)
            ->where('date', 'like', $date->format('Y-m-d') . '%')
            ->exists()) {
                return true;
            } else {
                return false;
        }
    }
}

이 중간부품에는 많은 것들이 있으니 조금만 소화합시다.지정된 API 라우트에 도달하여 중간부품이 시작됩니다.요청에서 적재 영패를 추출하고 사용자 표를 대조하여 검사합니다.주어진 영패를 가진 사용자가 존재하면 중간부품은 이 사용자를 변수에 등록하고 다른 검사를 계속 수행하지만, 이 영패를 가진 사용자가 존재하지 않으면 중간부품은 401로 되돌아옵니다.이 검사가 완료되면 중간부품은 사용자의 접근 단계를 검사합니다.사용자가 자유 계층 사용자인 경우 checkLimit() 메서드는 사용자가 오늘 API 호출을 수행했는지 확인하고 시작합니다.검사는 당연히 청구표를 통해 이루어진다.만약 사용자가 오늘 요청을 보냈다면, 중간부품은 '요청이 너무 많음' 오류를 되돌려줍니다.
트리거 오류가 없으면, 요청은 데이터베이스에 저장되어 나중에 참고할 수 있습니다. (중간부품이나 통계적 원인에 사용됩니다.)
여느 때와 마찬가지로, 우리는 app/Http/Kernel에 이 새로운 중간부품을 등록해야 한다.api 중간부품 그룹과 $RouteMiddle 소프트웨어에 등록해야 합니다.모든 API 루트에서 이 제한을 터치하지 않으려면 $route Middleware 배열에만 등록하십시오.내 등록은 다음과 같습니다.
// app/Http/Kernel.php

<?php

...
protected $middlewareGroups = [
    'web' => [
        ...
    ],
    'api' => [
        \App\Http\Middleware\ForceJson::class,
        \App\Http\Middleware\AccessLevel::class,
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];

protected $routeMiddleware = [
    ...
    'access.level' => \App\Http\Middleware\AccessLevel::class,
];
api 중간부품 그룹에 중간부품을 등록하지 않으려면 루트/api에 등록해야 합니다.php 파일.우리가 중간부품을 테스트해서 그것이 정상적으로 작동할 수 있도록 하자.

위의 그림에서 보듯이, 우리가 구독하지 않은 사용자의 영패를 제공했을 때, 우리는 하나의 요청만 성공적으로 통과했고, 과도한 요청 오류가 발생하여 우리의 목표를 실현했다.

수집된 데이터 사용


나는 자신의 사이트OnlyResultz에서 이런 기술을 사용하여 사용자의 API 요청을 제한하기 때문에 사용자의 계기판을 통해 사용자에게 관련 API 사용 지표를 보여주고 싶다.이 용례에 대해 매일, 매달, 일생의 요청만 표시하지만, 사용자와 응용 프로그램 관리자에게는 수집된 데이터를 더 많이 사용하는 방법이 있습니다.Blade에서 이러한 기능의 한 예는 Gist에서 찾을 수 있습니다.
결과는 다음과 같습니다.

위의blade 파일에서 $requests 변수를 제공합니다. 이 변수는 요청 모델을 사용하여 사용자에게 관련 요청을 받습니다.블레이드 파일에서 각 지표를 처리하고 읽을 수 있는 형식으로 사용자에게 제공한다.

마무리


이것이 바로 Laravel 시리즈에서 API 호출 제한을 설정하는 이유입니다.만약 이 시리즈의 이전 문장을 아직 읽지 않았다면, 보십시오.다른 글에서는 Laravel의 내장 속도 제한기를 사용해서 본문에서 본 것과 유사한 결과를 실현하는 방법을 설명했다.
다음까지.
표지 사진 작성자Mohamed Hassan 출처Pixabay

좋은 웹페이지 즐겨찾기