라이센스 토큰을 사용하여 서비스 라이선싱 유효성 검사
Microsoft GDK(게임 개발 키트) 런타임을 내의 라이선스 토큰은 클라이언트를 믿을 필요 없이 실행 중인 앱에 대한 유효한 라이선스가 클라이언트에 있는지를 확인하기 위해 게임 서비스에 대한 수단을 제공합니다. 이들 토큰은 PC에서 실행되는 앱의 라이선스를 확인하는 데 사용되며, Xbox 앱에는 필요 없습니다.
라이선스 토큰은 JWT(JSON 웹 토큰)로 포맷되며 사용 가능한 JWT 처리기를 사용하여 압축을 풉니다. 유효성 검사 테스트의 경우 http://jwt.io의 JWT 디코딩 도구에 라이선스 토큰을 입력할 수 있습니다.
라이선스 토큰에는 다음 표에 나와 있는 섹션이 있습니다.
섹션 | 설명 |
---|---|
헤더 | 토큰의 유효성을 검사하는 데 사용할 올바른 인증서를 결정하는 데 사용되는 x5t를 제공합니다. |
페이로드 | 클라이언트의 라이선스에 대한 추가 정보를 제공 하는 LicenseTokenClaim 값에 base64로 인코딩된 문자열을 포함합니다. 또한 LicenseToken 의 만료 날짜를 제공합니다. |
서명 | 토큰의 무결성과 소스에 대한 유효성 검사를 위한 표준 JWT 서명입니다. 유효성 검사를 위해 Microsoft에서 다운로드한 서명 인증서의 공개 인증서를 사용합니다. |
클라이언트로부터 라이선스 토큰 받기
라이선스 토큰을 얻으려면 클라이언트는 이 항목의 뒷부분에서 설명한 대로 제품의 Store ID와 사용자 지정 개발자 문자열을 전달하는 XStoreQueryLicenseTokenAsync API를 호출해야 합니다. 이 API는 현재 Microsoft Store 앱에 로그인한 사용자를 기반으로 하는 앱에 대한 라이선스 토큰을 검색합니다. 개발 샌드박스를 사용하는 경우 테스트 계정은 Xbox Windows 앱과 Microsoft Store 앱에 로그인해야 합니다. 토큰이 검색되면 유효성을 검사하기 위해 사용자의 서비스로 해당 토큰을 보냅니다. 클라이언트에서 서비스로 들어오는 결과의 신뢰가 무효화되기 때문에 클라이언트에서 라이선스 토큰의 유효성을 검사할 수 없습니다.
라이선스 토큰을 얻는 방법에 대한 예시는 인게임 스토어 샘플을 참조하세요.
서비스에서 라이선스 토큰 유효성 검사
라이선스 토큰을 처리하는 방법에 대한 전체 코드 예제는 게임 서비스 샘플을 참조하세요.
토큰에 서명 하는 데 사용 된 인증서에서 RSA 공개 키를 가져와야 합니다.
인증서를 다운로드하는 데 사용할 전체 URL을 확인하려면 certificateId
다음 중 한 가지 방법으로 결정해야 합니다.
- base64로 인코딩된 페이로드 내에서
certificateId
값을 추출합니다. - 헤더에서 x5t 값을 바이트 배열로 base64로 디코딩하고 이를 문자열로 변환합니다. 이 작업을 수행하는 방법에 대한 예시 코드는 게임 서비스 샘플에 나와 있습니다.
-
certificateId
한 후 디코딩된 문자열에서 이 값을 가져온 다음 이를https://licensing.mp.microsoft.com/v8.0/licenseToken/fullCertificate/{certificateId}
에 추가하여 인증서의 직접 다운로드 링크를 가져옵니다.
결과는 raw 인증서 데이터 포함된 XML 문서로, 이는 X509Certificate2와 같은 인증서 개체를 만드는 데 사용할 수 있습니다(예시 코드는 게임 서비스 샘플 참조). 라이선스 토큰의 유효성이 검증될 때마다 다운로드할 필요가 없도록 이 인증서를 캐시해야 합니다.
인증서의 RSA 공개 키를 사용하는 경우 표준 JWT 서명 유효성 검사를 사용하여 라이선스 토큰이 신뢰할 수 있는 출처에서 보낸 것이며 토큰 내용이 수정되지 않은 상태인지를 확인할 수 있습니다.
라이선스 토큰에서 정보 사용
라이선스 토큰의 페이로드에는 추가 JSON 데이터의 base64로 인코딩된 문자열인 LicenseTokenClaim
값이 포함되어 있습니다.
문자열의 첫 번째 부분은 디코딩 후 무시해도 되므로 JSON 데이터의 시작 부분을 나타내는 첫 번째 "{"를 찾습니다.
이 방법은 다음 예제에서 확인할 수 있습니다.
[Unicode character string that can be ignored]
{
"certificateId": "C4FC9E583CC4D5FEB96712619B5BE7499FECB5FA",
"customDeveloperString": "anti-replay string",
"licensableProducts": [
{
"endDate": "9999-12-31T23:59:59.9999999+00:00",
"isShared": false,
"id": "fc80277459b04bc7a158b49c0c5574e1",
"productId": "9NN4ZHKML55R",
"skuId": "0010",
"userId": "m8jGdShdpG8vu9nIQiAn3lBIQJ+TD0r2jAJvfmGYmGI="
}
],
"payload": "T3Jqb3H+YHkjgBksJcsBaL6noHabm5JfyCYaV9nnV+XTiAzNfHKCdUqK2KZkZNk7aYfsVJ0CL2mFQg8XdYtxOv+YmHi+6qhXv6Wp5mx3e4+ZFavbobwjPbVgVsKpDV3TxKdUCIhVPPtDOziqWsUB3+z4plopXM+SargAqqBchQOQklRf5z4NXkAqWer31MmZWwXeEcsfH7Ac/usMlrQakT1IepxnR7+bZIKzp7B9QcWN2lJzyP4TYg8gVnYBGT9cRWxy/IgY0gL5FYNLnDJM1A3D2JcmsCsKuCVpzzn2eXdSAGha00oqBdCcQMr34da54x1s47lvZTdP+Z4Z/BjSQw==",
"tokenVersion": 1
}
클라이언트에 제품에 대한 유효한 라이선스가 있는 경우 이는 licensableProducts
목록에서 결과로 반환됩니다.
endDate
값은 UTC 시긴에 표시되고 payload
문자열은 나중에 사용되도록 예약됩니다.
customDeveloperString 매개 변수를 사용하여 재생 공격 방지
클라이언트는 유효한 토큰의 전송을 서비스로 가로채고 유효한 토큰을 재생할 수 있기 때문에 XStoreQueryLicenseToken
API의 customDeveloperString
매개 변수를 적절히 사용하는 것이 중요합니다.
이 문자열은 서버에서 생성되고 원하는 각 라이선스 검사에 대해 고유해야 합니다.
문자열이 생성되면 문자열을 XStoreQueryLicenseToken
API에 전달하는 클라이언트로 보내야 합니다.
그런 다음 값이 라이선스 토큰의 페이로드에 포함됩니다. 토큰에 대한 유효성 검사 시그니처에서 수정되는 경우가 방지됩니다.
클라이언트가 토큰을 서비스로 보낸 후에는 customDeveloperString
값이 서버에서 생성하여 클라이언트로 보낸 값과 정확히 일치하는 것을 확인할 수 있습니다.
이 값이 일치하지 않는 경우에는 토큰의 모든 다른 측면이 계속 유효하기 때문에 오래된 토큰이 서비스를 속이기 위해 이를 재생하는 것을 의미할 수 있습니다.
customDeveloperString
이(가) 수행한 각 라이선스 검사에 대한 임의 문자열 또는 GUID가 되는 것이 좋습니다.