BIG
- JSON Web Token(JWT)이란..?
JSON Web Token(이하 JWT, 토큰)은 웹표준(RFC 7519)으로써 암호화와 검증(Signature) 기능을 가진 인증 토큰입니다. - JWT 구조는 아래와 같습니다.
Base64(Header).Base64(Payload).Base64(Signature)- Header에는 사용 된 보안 메커니즘(암호 알고리즘 등)에 대한 정보가,
Data에는 전달할 정보가,
Signature에는 Base64(Header).Base64(Data)를
Header에 명시된 알고리즘으로 암호화된 문자열이 담깁니다.
- Header에는 사용 된 보안 메커니즘(암호 알고리즘 등)에 대한 정보가,
- 예시
- 토큰
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c - 포함된 정보
Header : {"alg": "HS256","typ": "JWT"}
Payload : {"sub": "1234567890","name": "John Doe","iat": 1516239022}
Signature : HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload), your-256-bit-secret)
- 토큰
- JWT의 무결성을 보장하기 위해 여러 서명 알고리즘(alg)을 사용할 수 있습니다.
- RSA based
- Elliptic curves
- HMAC
- None
- 장단점
- 장점
- JWT는 인증에 필요한 모든 정보를 담고 있기 때문에 인증을 위한 별도의 저장소가 없어도 된다.
- 세션(Stateful)과 다르게 서버는 무상태(StateLess)가 된다.
- 확장성이 우수하다.
- 토큰 기반으로 다른 로그인 시스템에 접근 및 권한 공유가 가능하다.
- OAuth의 경우 소셜 계정을 통해서 다른 웹서비스에 로그인 할 수 있다.
- 단점( 장점을 가지려면 그에 상응하는 단점도 발생한다. )
- 쿠키/세션과 다르게 토큰의 길이가 길어, 인증 요청이 많아질수록 네트워크 부하가 심해진다.
- Payload 자체는 암호화가 되지 않아 중요한 정보는 담을 수 없다.
- 토큰을 탈취당한다면 대처가 매우 어렵다.
- JWT는 매우 복잡한 표준이어서 사용자가(개발자) 잘못 이해할 가능성이 있다.
설정이 잘못되는 경우 최악에 모든 사용자가 유효한 JWT를 생성해서 다른 사용자인척 할 수 있다.
이는 초보개발자들 사이에서 나오는 실수가 아니고, 실제로 Auth0에서 이러한 버그를 만들어낸 적이 있다.
이는 많은 보안 전문가들이 JWT를 싫어하게 되는 이유 중 하나가 되었다.
JWT는 수많은 기능을 제공하고 있기 때문에,
개발자들이 잠재적으로 실수 할 수 있는 범위가 넓다. - 로그아웃에 문제가 있다.
전통적인 세션을 활용하는 방법의 경우, 단순히 세션 스토리지에서 해당 세션 값을 날리면 되었고 이것으로 충분했다.
그러나 JWT와 다른 무상태 (stateless) 토큰으로는 이것이 불가능하다.
우리는 이 토큰을 지울 수 없다.
왜냐하면 이는 스스로 정보를 담고 있는 토큰이며,
토큰의 상태를 관리하는 중앙 인증 관리 시스템이 없기 때문이다.
이는 아래 세가지 방법으로 해결할 수 있다.- 토큰의 생명 주기를 굉장히 짧게 하는 방법 (5분 이내).
해당 시간이 지나면, 새롭게 토큰을 만든다. - 시스템에서 최근에 만료된 토큰을 저장해 두는 것
- 서버 로그아웃 기능 자체를 없애고,
클라이언트에 토큰 삭제를 맡기는 방법 좋은 시스템의 경우엔 앞에 두가지 방법을 선택한다.
그러나 두 문제의 해결책에서 볼 수 있는 것처럼,
두 방법은 모두 중앙에서 인증을 관리해야 하는 시스템이 필요하며
이는 더 이상 JWT의 장점을 유효하지 않게 만든다.
- 토큰의 생명 주기를 굉장히 짧게 하는 방법 (5분 이내).
- JWT의 크키는 상대적으로 크기 때문에, 쿠키에 JWT를 담을 경우 오버헤드가 발생한다는 것이다.
- 장점
- PHP JWT CLASS SAMPLE
<?php
class jwt{
protected $alg;
function __construct(){
//사용할 알고리즘
$this->alg = "sha256";
}
function hashing(array $data){
// 토큰의 헤더
$header = json_encode(array(
"alg"=>$this->alg,
"typ"=>"JWT"
));
$payload = json_encode($data);
$signature = hash($this->alg, $header.$payload);
return base64_encode($header.".".$payload.".".$signature);
}
function dehashing($token){
// 토큰 만들때의 구분자 . 으로 나누기
$parted = explode(".", base64_decode($token));
$signature = $parted[2];
// 위에서 토큰 만들때와 같은 방식으로 시그니처 만들고 비교
if(hash($this->alg, $parted[0].$parted[1]) == $signature){
// echo "good";
}else{
//echo("잘못된 signature 입니다");
}
$payload = json_decode($parted[1],true);
return $payload;
}
}
?>
- 로그인 정보 저장 (JWT를 사용하여 해싱하고, 쿠키로 저장) 예제
<?php
// 쿠키변수 생성
function set_cookie($cookie_name, $value, $expire){
setcookie(md5($cookie_name), base64_encode($value), time() + $expire, '/');
}
// 쿠키변수값 얻음
function get_cookie($cookie_name){
$cookie = md5($cookie_name);
if (array_key_exists($cookie, $_COOKIE))
return base64_decode($_COOKIE[$cookie]);
else
return "";
}
$user_id='user1';
$user_nm='홍길동';
$city='서울특별시';
$jwt = new jwt();
$login_token = $jwt->hashing(array(
"user_id"=> $user_id,
"user_nm"=> $user_nm,
"city"=> $city
));
//Cookie 저장 : 1달
set_cookie("token", $login_token, 2592000);
?>
- JWT 정보 가져오기 (저장된 JWT를 가져와 디코딩한 후, 사용자 정보를 출력하고 상수로 정의)
<?php
$get_login_token = get_cookie("token");
$jwt_data = $jwt->dehashing($get_login_token);
echo $jwt_data["user_id"]."<br>";
echo $jwt_data["user_nm"]."<br>";
echo $jwt_data["city"]."<br>";
define('SESSION_USER_ID', $jwt_data["user_id"]);
define('SESSION_USER_NM', $jwt_data["user_nm"]);
define('SESSION_CITY', $jwt_data["city"]);
echo SESSION_USER_ID."<br>";
echo SESSION_USER_NM."<br>";
echo SESSION_CITY."<br>";
?>
참고출처 : https://velog.io/@thelm3716/JWTvul
LIST
'!!...PHP > !!...HowTo' 카테고리의 다른 글
[How To] AWS S3 File Upload Using PHP & composer (0) | 2023.11.16 |
---|---|
[How To] Using JWT( JSON WEB TOKEN ) with PHP Type_02 (0) | 2023.09.28 |
[How To] composer 설치 & phpspreadsheet 설치 (0) | 2023.08.22 |
[How To] Apache PHP MariaDB 환경에서 WAS_02...? (0) | 2023.05.22 |
[How To] PHP 메모리 부족 메시지( Fatal error: Allowed memory size of ~ ) 출력상황 처리 방법 (0) | 2022.10.05 |