개요
웹 사이트에서 인증을 다룰 때는 대표적으로 세션 방식과 JWT Token 방식이 존재합니다.
둘 다 매커니즘은 쿠키로 세션ID 또는 암호화된 JWT Token를 발급받아 프론트와 백엔드간 쿠키를 주고받고 인증을 허가하는 방식이나, 세션 방식의 문제점 중 하나는 URL을 이동할 경우 세션이 만료되어 로그인을 다시 해야 한다는 단점이 존재하며, JWT Token에서는 서버에 세션 정보를 저장하지 않아 서버의 부하를 줄일 수 있고, 유효 기간과 사용 범위 등을 정해 보안적인 측면에서 확장된 제어가 가능하며, 필요에 따라 토큰에 정보와 권한을 포함시켜 인증과 인가를 분리해 관리가 가능합니다.
오늘은 그 JWT Token 방식을 PHP & Laravel에서 구현하는 방법을 알아보고자 하며, 직접 처음부터 끝까지 구현할 수도 있겠지만, 라라벨에서는 이미 JWT Token 방식을 손쉽게 사용할 수 있는 패키지를 제공하고 있습니다.
(백엔드에서 사용할 로그인 API 기준으로 작성했습니다. 프론트엔드측 코드는 별도로 넣지 않았습니다.)
제한 사항 (반드시 확인)
Laravel Version : 5.2 버전 이상
PHP : 5.5.9 버전 이상
JWT-Auth 패키지를 사용하는 장점
- 일반적으로 직접 구현하는 것보다 성능이 뛰어나다.
- 토큰을 라라벨 프로젝트 내부에서 발급, 서명, 보관, 유효성 검증, 만료 처리, 캐싱 작업을 진행해 관리할 내용이 적다.
- 사용 또한 손쉽게 가능하다.
구현 방법
1. 패키지 설치 (프로젝트 루트 폴더에서 진행)이후 “{프로젝트경로}/config/jwt.php” 파일 생성 확인
composer require tymon/jwt-auth
2. JWT-Auth 구성 파일 생성 (프로젝트 루트 폴더에서 진행)
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
3. 서명에 사용할 시크릿 키 생성 (프로젝트 루트 폴더에서 진행))
php artisan jwt:secret
이후 .env 파일 내부에 JWT_SECRET 변수에 값이 추가되었을 것임(이 시크릿 키는 config/jwt.php에 'secret' => env('JWT_SECRET'),로 지정되어 있음).
4. config/auth.php에서 driver 지정
'guards' => [
...
'api' => [
'driver' => 'jwt',
'provider' => 'users'
]
],
...
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
5. User 모델에서 JWTSubject를 상속 (User Model은 현재 사용할 프로젝트에서 사용자들의 정보를 저장할 모델을 미리 생성해놓아야 함)
...
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
...
public function signup(Request $request): JsonResponse
{
$user = AdminUser::create([
'email' => $request->input('email'),
'password' => bcrypt($request->input('password')),
]);
return response()->json($user);
}
public function login(Request $request)
{
$credentails = $request->only('email', 'password');
// attempt의 응답값으로 액세스 토큰이 반환됨.
$token = auth('api')->attempt($credentails);
// 응답값에 토큰 정보 추가
return response()->json([
'result' => true,
'token' => $token
]);
}
public function logout(): JsonResponse
{
auth('api')->logout();
return response()->json([
'code' => 200,
'message' => '로그아웃 되었습니다.'
]);
}
}
6. AuthController에서 로그인, 회원가입, 로그아웃 기능 구현
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class JWTAuthController extends Controller
{
public function __construct()
{
}
/**
* 회원가입
*
* @param Request $request
* @return JsonResponse
*/
public function signup(Request $request): JsonResponse
{
$user = AdminUser::create([
'email' => $request->input('email'),
'password' => bcrypt($request->input('password')),
]);
return response()->json($user);
}
/**
* JWT 로그인
*
* @param Request $request
* @return JsonResponse
*/
public function login(Request $request): JsonResponse
{
$credentials = $request->only('email', 'password');
if (!$token = auth('api')->attempt($credentials)) {
return response()->json([
'result' => false,
'code' => 401,
'message' => '이메일 또는 비밀번호가 올바르지 않습니다.'
]);
}
$user = auth('api')->user();
return response()->json([
'result' => true,
'user' => $user,
'token' => $token
]);
}
/**
* 로그아웃
*
* @return JsonResponse
*/
public function logout(): JsonResponse
{
auth('api')->logout();
return response()->json([
'code' => 200,
'message' => '로그아웃 되었습니다.'
]);
}
}
7. 로그인한 사용자만 조회 가능한 정보 얻는 컨트롤러 생성
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
class ApiController extends Controller
{
public function __construct(
{
}
public function getValue(): string
{
return '로그인을 해야 해당 정보를 볼 수 있을걸요?';
}
}
8. API 정의 (config/api.php)
Route::post('/register', [App\Http\Controllers\JWTAuthController::class, 'signup']);
Route::post('/login', [App\Http\Controllers\JWTAuthController::class, 'login']);
Route::group(['middleware' => ['api']], function () {
Route::get('/need-login-values', [App\Http\Controllers\ApiController::class, 'getValue']);
}
9. API를 사용해 정상 작동 확인
저는 API 사용 시 postman이라는 프로그램을 사용했습니다.
- 로그인 API 호출 결과
- /need-login-values api에 bearer-token 지정 (위에서 발급받은 token의 내용이 들어가야 함)
- /need-login-values 결과 확인
- 로그인하지 않고 /need-login-values 호출 시
'PHP' 카테고리의 다른 글
PHP 표준 권고(PSR) (0) | 2023.07.04 |
---|---|
PHP 기본 문법 요약 (0) | 2023.06.30 |
PHP 전체 개발 환경 정리 (0) | 2023.03.28 |
Java 프로그래머가 PHP를 시작하는 방법 (0) | 2023.03.01 |