본문 바로가기
기능메모

[laravel] api key로 보안

by 성동원 2024. 3. 6.

나는 laravel로 API 서버를 열었다.

 

그래서 예를들면..

 

ex) http://www.abc.com/api/hello  



위 처럼 나의 도메인이 www.abc.com  이고
api 루트가 /api/hello 라면

누구든지 저 api 주소로 내가 준비한 데이터를 가져갈 수 있다.

 

나는 내 데이터를 소중히 여겨 아무나 못가져가도록 하고 싶었다.

 

현재 생각한 방법으로는..

 

  1. API KEY를 이용해서 요청자에게 API KEY를 입력해야지만 나의 데이터를 줄 수 있다.
  2. 허용된 도메인의 대한 요청에만 데이터를 주겠다.

2가지 방법이다.

 

현재는 1번에 대한 방법에 적용을 해보았고, postman으로 테스트시 잘 적용 된 것 같다.

 

물론 1번에도 엄청난 응용을 할 순 있지만.

지금은 단순 token 인증이다.

 

현재 프로젝트에서.

php artisan tinker

 

명령어 실행.

 

그럼 뭘 입력하라는 듯한 상태로 바뀐다.

Str::random(64);

 

를 입력.

 

 

이렇게 token을 만들어준다.

라라벨에 이러한 기능이 있다니..

 

그리고 나서.

front에서 header 쪽에 bearer {api_key} 를 포함하여 요청을 하게 되면 데이터를 주게 된다.

 

만약 틀리거나 포함하지 않았을 시엔 에러를 돌려주면 된다.

 

위 로직을 적용하기 위해

 

php artisan make:middleware ApiKeyMiddleware

 

컨트롤 하기 위한 미들웨어를 하나 생성 해줌.

그렇다면 app\Http\Middleware\ApiKeyMiddleware.php 가 생성이 된다.

 

 

 

처음엔 위 와 같은 화면이 나온다. 여기를 수정해 줄 것이다.

 

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class ApiKeyMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->bearerToken() === config('auth.api_key')) {

            return $next($request);
        }

        return response()->json(["message" => '인가되지 않은 접근입니다.'], 403);
    }
}

 

 

해석을 해보자면. $request->bearerToken() 은 내장 함수로써 client에서 요청한 bearer token을 내가 지정한 api_key 토큰과 비교 하는 것이다.

 

맞으면 다음.

 

아니면 인가되지 않은 접근이라는 메세지 띄우기.

 

 

여기서. config('auth.api_key') 라는 부분을 또 설정 해줘야 한다.

 

config\auth.php로 가보자.

 

 

맨밑에 'api_key' => env('API_KEY') 를 추가 해준다.

 

그리고 나서 .env 파일로 가보자.

 

 

.env 파일 아무대나 위 와 같이 작성해주면 끝.

 

다시 middleware의 코드를 해석해보자면.

 

1. if 문 에서 client에서 보낸 bearer token과 내가 준비한 bearer token과 비교를 할 것이다.

2. 근데 나의 token은 config(auth.api_key')에 저장되어 있다.

3. auth.api_key는 config\auth.php에 있다.

4. api_key는 env('API_KEY')를 지정함으로. env 파일에 등록한 것을 봐라.

 

위 와 같이 했을 시에 postman 테스트 결과이다.

 

성공시.

 

 

실패시

 

 

 

여기서 단점 및 보안 관련해서 작성해보자면.

 

1. 아무래도 API_KEY가 고정값이다보니 API_KEY가 노출되거나 누군가 알게 된다면 누구든지 나의 데이터를 쓸 수 있다.

2. 보안으로는. 위에 2번째 허용된 domain에 대한 요청만 응답하기 추가를 하게 된다면 2중 보안이 될 수 있다.

3. 고정된 API_KEY가 아닌, 나만의 박스를 만들어서. 허용된 client쪽과 합을 맞추는 것이다.

 ex) '회사이름' + {오늘날짜} =

예를들어서 위 와 같이 매일 바뀌는 변수를 중간중간 끼워 넣는다면, 해커 입장에선 해킹하기가 쉽진 않을 것이다. 위는 단순한 예고. 사실은 더 복잡한 서로의 약속을 정하고 적용한다. 물론 저 매일 바뀌는 패턴이 털리면 똑같이 털리는건 매한가지..