6.8 KiB
6.8 KiB
🎫 OneTake Updater - QR 라이선스 시스템
📋 개요
OneTake Updater는 JWT 서명 기반의 QR 코드 라이선스 시스템을 제공합니다.
프로젝트별로 라이선스를 발급하고, 만료일, 디바이스 제한, 연결 기기 수 등을 관리할 수 있습니다.
🔑 라이선스 구조
1. 라이선스 토큰 구성
라이선스는 Base64 인코딩된 JSON 형태로 발급됩니다:
{
"d": "{라이선스 데이터 JSON}",
"s": "{RSA-SHA256 서명 (Base64)}"
}
2. 라이선스 데이터 필드
| 필드 | 타입 | 설명 | 예시 |
|---|---|---|---|
expiry |
String | 만료일 (YYYY-MM-DD) | "2027-02-06" |
deviceId |
String | 허용된 디바이스 ID ( * = 모든 기기) |
"ABC123" 또는 "*" |
projectName |
String | 프로젝트/카테고리 이름 | "MYPROJECT" |
tvLimit |
Integer | 최대 연결 가능 기기 수 (0 = 무제한) |
5 |
issuedAt |
Integer | 발급 시각 (Unix timestamp, ms) | 1738838400000 |
type |
String | 라이선스 타입 | "standard" |
🎨 라이선스 발급 방법
포털에서 발급
- 관리자 로그인 →
라이선스 발급탭 이동 - 다음 정보 입력:
- 만료일: 라이선스 유효 기간
- 프로젝트 이름: 대분류 카테고리 선택 또는 직접 입력
- Device ID: 특정 기기만 허용하려면 입력, 모든 기기 허용 시
* - 기기 연결 제한: 동시 연결 가능한 수신기(TV 등) 대수 (0 = 무제한)
- QR 생성하기 버튼 클릭
- QR 코드 모달 팝업 확인
발급 예시
만료일: 2027-12-31
프로젝트: MYPROJECT
Device ID: * (모든 기기)
연결 제한: 3대
생성된 토큰 예시:
eyJkIjoie1wiZXhwaXJ5XCI6XCIyMDI3LTEyLTMxXCIsXCJkZXZpY2VJZFwiOlwiKlwiLFwicHJvamVjdE5hbWVcIjpcIk1ZUFJPSkVDVFwiLFwidHZMaW1pdFwiOjMsXCJpc3N1ZWRBdFwiOjE3Mzg4Mzg0MDAwMDAsXCJ0eXBlXCI6XCJzdGFuZGFyZFwifSIsInMiOiJhYmMxMjMuLi4ifQ==
📤 라이선스 배포 방법
1. QR 코드 스캔 (권장)
- 모바일 앱에서 QR 스캔 기능 구현
- 스캔 즉시 토큰 문자열 획득
2. 카카오톡 공유
포털에서 "카카오톡으로 전송" 버튼 클릭 시:
- QR 이미지와 함께 라이선스 정보 전송
- 수신자가 QR 코드를 스캔하여 사용
카카오톡 메시지 구성:
[MYPROJECT] 라이선스 발급
📅 만료일: 2027-12-31
📱 연결제한: 3대
[QR 코드 이미지]
3. 텍스트 복사
- QR 모달 하단의 토큰 문자열을 복사
- 이메일, 메신저 등으로 전달
- 수신자가 앱에 직접 붙여넣기
🔐 라이선스 검증 로직 (클라이언트 구현 가이드)
1. 토큰 파싱
// Base64 디코딩
const decoded = JSON.parse(atob(token));
const licenseData = JSON.parse(decoded.d);
const signature = atob(decoded.s);
2. 서명 검증 (RSA-SHA256)
// public_key.pem을 사용하여 서명 검증
const isValid = crypto.verify(
'sha256',
Buffer.from(decoded.d),
publicKey,
Buffer.from(signature)
);
3. 만료일 체크
const expiryDate = new Date(licenseData.expiry);
const now = new Date();
if (now > expiryDate) {
throw new Error('라이선스가 만료되었습니다.');
}
4. 디바이스 ID 검증
const myDeviceId = getDeviceId(); // 기기 고유 ID 획득
if (licenseData.deviceId !== '*' && licenseData.deviceId !== myDeviceId) {
throw new Error('이 기기에서 사용할 수 없는 라이선스입니다.');
}
5. 연결 제한 확인
const connectedDevices = getCurrentConnectedCount(); // 현재 연결된 기기 수
if (licenseData.tvLimit > 0 && connectedDevices >= licenseData.tvLimit) {
throw new Error(`최대 ${licenseData.tvLimit}대까지 연결 가능합니다.`);
}
🛡️ 보안 고려사항
1. 키 관리
- private_key.pem: 서버에만 보관, 절대 외부 유출 금지
- public_key.pem: 클라이언트 앱에 포함 (검증용)
2. 토큰 저장
- 클라이언트는 토큰을 안전한 저장소에 보관 (Keychain, EncryptedSharedPreferences 등)
- 네트워크 전송 시 HTTPS 사용 필수
3. 재발급 정책
- 만료된 라이선스는 재발급 필요
- 분실 시 관리자가 새 토큰 발급
📊 사용 시나리오
시나리오 1: 단일 기기 라이선스
만료일: 2027-12-31
Device ID: DEVICE-ABC-123
연결 제한: 1대
→ 특정 태블릿 1대에서만 사용 가능, TV 1대 연결 가능
시나리오 2: 무제한 라이선스
만료일: 2099-12-31
Device ID: *
연결 제한: 0 (무제한)
→ 모든 기기에서 사용 가능, 연결 제한 없음
시나리오 3: 프로젝트 단위 라이선스
만료일: 2027-06-30
Device ID: *
프로젝트: COMPANY-A
연결 제한: 10대
→ COMPANY-A 프로젝트 전용, 최대 10대 TV 연결 가능
🔧 API 엔드포인트
라이선스 발급 (관리자 전용)
POST /index.php?action=gen_license
Content-Type: multipart/form-data
expiry=2027-12-31
deviceId=*
projectName=MYPROJECT
tvLimit=5
응답:
{
"success": true,
"token": "eyJkIjoie1wiZXhwaXJ5XCI6..."
}
QR 이미지 생성 (공개)
GET /index.php?action=qr_img&data={토큰}
→ QR 코드 PNG 이미지 반환 (외부 API 프록시)
📱 클라이언트 구현 체크리스트
- QR 스캔 기능 구현
- 토큰 파싱 로직 구현
- RSA-SHA256 서명 검증 구현
- 만료일 체크 로직 구현
- 디바이스 ID 검증 로직 구현
- 연결 제한 관리 로직 구현
- 라이선스 갱신 알림 UI 구현
- 에러 처리 및 사용자 안내 메시지 구현
🆘 FAQ
Q1. 라이선스가 만료되면 어떻게 되나요?
A. 앱이 실행되지 않거나 제한된 기능만 사용 가능합니다. 관리자에게 연락하여 새 라이선스를 발급받아야 합니다.
Q2. Device ID는 어떻게 확인하나요?
A. 앱 내 설정 화면에서 "기기 정보" 또는 "라이선스 정보"를 확인하면 표시됩니다.
Q3. 연결 제한을 초과하면?
A. 새로운 기기 연결 시 "최대 연결 대수 초과" 오류가 발생합니다. 기존 연결을 해제하거나 라이선스를 업그레이드해야 합니다.
Q4. 라이선스를 여러 명이 공유할 수 있나요?
A. Device ID가 *이고 연결 제한이 충분하다면 가능합니다. 단, 보안상 권장하지 않습니다.
Q5. 서명 검증이 실패하면?
A. 토큰이 위조되었거나 손상되었을 가능성이 있습니다. 관리자에게 재발급을 요청하세요.
📞 지원
라이선스 관련 문의: update@onetake.best
포털 접속: https://update.onetake.best