fix: JWT 디코딩 시 한글 깨짐 수정 (atob → TextDecoder)
atob()가 UTF-8 멀티바이트 문자를 Latin-1로 처리하여 한글 이름이 깨지는 문제 수정. Uint8Array + TextDecoder 패턴으로 교체. tkpurchase, tkuser nginx에 charset utf-8 추가. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,8 +7,9 @@
|
|||||||
*/
|
*/
|
||||||
export function parseJwt(token) {
|
export function parseJwt(token) {
|
||||||
try {
|
try {
|
||||||
// 토큰의 두 번째 부분(payload)을 base64 디코딩하고 JSON으로 파싱
|
// 토큰의 두 번째 부분(payload)을 base64 디코딩하고 JSON으로 파싱 (UTF-8 한글 지원)
|
||||||
return JSON.parse(atob(token.split('.')[1]));
|
const b = atob(token.split('.')[1].replace(/-/g,'+').replace(/_/g,'/'));
|
||||||
|
return JSON.parse(new TextDecoder().decode(Uint8Array.from(b, c => c.charCodeAt(0))));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("잘못된 토큰입니다.", e);
|
console.error("잘못된 토큰입니다.", e);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ function ensureAuthenticated() {
|
|||||||
// 토큰 만료 확인 함수
|
// 토큰 만료 확인 함수
|
||||||
function isTokenExpired(token) {
|
function isTokenExpired(token) {
|
||||||
try {
|
try {
|
||||||
const payload = JSON.parse(atob(token.split('.')[1]));
|
const b = atob(token.split('.')[1].replace(/-/g,'+').replace(/_/g,'/'));
|
||||||
|
const payload = JSON.parse(new TextDecoder().decode(Uint8Array.from(b, c => c.charCodeAt(0))));
|
||||||
const currentTime = Math.floor(Date.now() / 1000);
|
const currentTime = Math.floor(Date.now() / 1000);
|
||||||
return payload.exp < currentTime;
|
return payload.exp < currentTime;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
export function parseJwt(token) {
|
export function parseJwt(token) {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(atob(token.split('.')[1]));
|
const b = atob(token.split('.')[1].replace(/-/g,'+').replace(/_/g,'/'));
|
||||||
|
return JSON.parse(new TextDecoder().decode(Uint8Array.from(b, c => c.charCodeAt(0))));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("잘못된 토큰입니다.", e);
|
console.error("잘못된 토큰입니다.", e);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name _;
|
server_name _;
|
||||||
|
charset utf-8;
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ function getLoginUrl() {
|
|||||||
if (h.includes('technicalkorea.net')) return location.protocol + '//tkfb.technicalkorea.net/login?redirect=' + encodeURIComponent(location.href) + '&_t=' + t;
|
if (h.includes('technicalkorea.net')) return location.protocol + '//tkfb.technicalkorea.net/login?redirect=' + encodeURIComponent(location.href) + '&_t=' + t;
|
||||||
return location.protocol + '//' + h + ':30000/login?redirect=' + encodeURIComponent(location.href) + '&_t=' + t;
|
return location.protocol + '//' + h + ':30000/login?redirect=' + encodeURIComponent(location.href) + '&_t=' + t;
|
||||||
}
|
}
|
||||||
function decodeToken(t) { try { return JSON.parse(atob(t.split('.')[1].replace(/-/g,'+').replace(/_/g,'/'))); } catch { return null; } }
|
function decodeToken(t) { try { const b = atob(t.split('.')[1].replace(/-/g,'+').replace(/_/g,'/')); return JSON.parse(new TextDecoder().decode(Uint8Array.from(b, c => c.charCodeAt(0)))); } catch { return null; } }
|
||||||
|
|
||||||
/* ===== 리다이렉트 루프 방지 ===== */
|
/* ===== 리다이렉트 루프 방지 ===== */
|
||||||
const _REDIRECT_KEY = '_sso_redirect_ts';
|
const _REDIRECT_KEY = '_sso_redirect_ts';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name _;
|
server_name _;
|
||||||
|
charset utf-8;
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ function getLoginUrl() {
|
|||||||
if (h.includes('technicalkorea.net')) return location.protocol + '//tkfb.technicalkorea.net/login?redirect=' + encodeURIComponent(location.href) + '&_t=' + t;
|
if (h.includes('technicalkorea.net')) return location.protocol + '//tkfb.technicalkorea.net/login?redirect=' + encodeURIComponent(location.href) + '&_t=' + t;
|
||||||
return location.protocol + '//' + h + ':30000/login?redirect=' + encodeURIComponent(location.href) + '&_t=' + t;
|
return location.protocol + '//' + h + ':30000/login?redirect=' + encodeURIComponent(location.href) + '&_t=' + t;
|
||||||
}
|
}
|
||||||
function decodeToken(t) { try { return JSON.parse(atob(t.split('.')[1].replace(/-/g,'+').replace(/_/g,'/'))); } catch { return null; } }
|
function decodeToken(t) { try { const b = atob(t.split('.')[1].replace(/-/g,'+').replace(/_/g,'/')); return JSON.parse(new TextDecoder().decode(Uint8Array.from(b, c => c.charCodeAt(0)))); } catch { return null; } }
|
||||||
|
|
||||||
/* ===== 리다이렉트 루프 방지 ===== */
|
/* ===== 리다이렉트 루프 방지 ===== */
|
||||||
const _REDIRECT_KEY = '_sso_redirect_ts';
|
const _REDIRECT_KEY = '_sso_redirect_ts';
|
||||||
|
|||||||
Reference in New Issue
Block a user