備碼流程深度解析:ElyDeviceCodeStep逐行解讀)
【免費(fèi)下載鏈接】LauncherThis fork of Prism Launcher adds integrated support for Ely.by accounts.項(xiàng)目地址https://gitcode.com/GitHub_Trending/ely/Launcher點(diǎn)擊查看免費(fèi)下載Ely Prism LauncherPineconeMC是一款基于 Prism Launcher 的 Minecraft 啟動(dòng)器分支為 Ely.by 賬號(hào)提供OAuth2 設(shè)備碼Device Code登錄。本文逐行解讀核心類ElyDeviceCodeStep的實(shí)現(xiàn)幫助你完整理解設(shè)備碼登錄流程是如何一步步跑通的。一、什么是 OAuth2 設(shè)備碼流程為什么啟動(dòng)器需要它設(shè)備碼流程RFC 8628是為不方便內(nèi)置瀏覽器登錄的程序設(shè)計(jì)的啟動(dòng)器向授權(quán)服務(wù)器申請(qǐng)一組設(shè)備碼 用戶碼用戶打開瀏覽器在官方網(wǎng)頁(yè)上輸入用戶碼并登錄啟動(dòng)器在后臺(tái)定時(shí)輪詢直到服務(wù)器確認(rèn)用戶已授權(quán)授權(quán)完成后服務(wù)器下發(fā)access_token和refresh_token。這個(gè)流程的安全價(jià)值在 README.md 中說(shuō)得非常清楚你的賬號(hào)密碼永遠(yuǎn)不經(jīng)過(guò)啟動(dòng)器你只在瀏覽器里登錄 Ely.by 官方頁(yè)面啟動(dòng)器拿到的只是一個(gè)權(quán)限有限的令牌。這就是 Ely Prism Launcher 相比填賬號(hào)密碼式 fork 的最大賣點(diǎn) 。二、代碼結(jié)構(gòu)總覽Ely 版只寫了 34 行設(shè)備碼流程的絕大部分邏輯由父類完成Ely 版只需替換三個(gè)參數(shù)。兩個(gè)關(guān)鍵文件子類ElyDeviceCodeStep.cpp含頭文件 ElyDeviceCodeStep.h父類MSADeviceCodeStep.cpp// ElyDeviceCodeStep.h class ElyDeviceCodeStep : public MSADeviceCodeStep { public: explicit ElyDeviceCodeStep(AccountData* data); QString describe() override; };父類在 MSADeviceCodeStep.h 中聲明了整套狀態(tài)機(jī)成員作用m_clientId/m_scopesOAuth2 客戶端標(biāo)識(shí)與權(quán)限范圍m_deviceCodeUrl/m_tokenUrl申請(qǐng)?jiān)O(shè)備碼、換取令牌的端點(diǎn)m_pool_timer輪詢計(jì)時(shí)器每次到期發(fā)起一次令牌請(qǐng)求m_expiration_timer一次性到期計(jì)時(shí)器超時(shí)自動(dòng)中止interval輪詢間隔默認(rèn) 5 秒可被服務(wù)器動(dòng)態(tài)調(diào)整三、構(gòu)造函數(shù)逐行解讀Ely 專屬的 3 個(gè)參數(shù)ElyDeviceCodeStep.cpp 的構(gòu)造函數(shù)只有 4 行卻完成了從微軟切換到 Ely的全部工作ElyDeviceCodeStep::ElyDeviceCodeStep(AccountData* data) : MSADeviceCodeStep(data) { m_clientId APPLICATION-getElyClientID(); m_scopes account_info offline_access minecraft_server_session; m_deviceCodeUrl QUrl(https://account.ely.by/api/oauth2/v1/devicecode); m_tokenUrl QUrl(https://account.ely.by/api/oauth2/v1/token); }逐行拆解m_clientId APPLICATION-getElyClientID()讀取 Ely 平臺(tái)的 Client ID。實(shí)現(xiàn)見(jiàn) Application.cpp——優(yōu)先取用戶設(shè)置里的ElyClientIDOverride否則用編譯期常量BuildConfig.ELY_CLIENT_ID。m_scopes權(quán)限范圍與微軟的XboxLive.SignIn不同Ely 申請(qǐng)的是三個(gè) scope——account_info讀取賬號(hào)信息、offline_access允許頒發(fā) refresh_token實(shí)現(xiàn)離線續(xù)期、minecraft_server_session加入服務(wù)器會(huì)話的憑證。兩個(gè) URL指向 Ely 自己的 OAuth2 端點(diǎn)而不是login.microsoftonline.com父類默認(rèn)值。最后 describe() 只是把進(jìn)度條文案改成Logging in with Ely.by account(device code).讓用戶明確當(dāng)前登錄的是 Ely 通道。四、perform()向服務(wù)器申請(qǐng)?jiān)O(shè)備碼父類的 perform() 是流程的起點(diǎn)QUrlQuery data; data.addQueryItem(client_id, m_clientId); data.addQueryItem(scope, m_scopes); auto payload data.query(QUrl::FullyEncoded).toUtf8();要點(diǎn)有三表單編碼請(qǐng)求以application/x-www-form-urlencodedPOST 到m_deviceCodeUrl只帶client_id和scope兩個(gè)參數(shù)——此時(shí)還不需要任何用戶憑證。網(wǎng)絡(luò)層封裝通過(guò)Net::Upload::makeByteArray創(chuàng)建請(qǐng)求用RawHeaderProxy附加請(qǐng)求頭并enableAutoRetry(true)讓傳輸層自動(dòng)重試。任務(wù)化執(zhí)行請(qǐng)求被包進(jìn)NetJob命名MSADeviceCodeStep完成后回調(diào) deviceAuthorizationFinished()。五、deviceAuthorizationFinished()解析響應(yīng)彈出登錄頁(yè)服務(wù)器響應(yīng)是一個(gè) JSON被解析為 DeviceAuthorizationResponse 結(jié)構(gòu)device_code / user_code / verification_uri / expires_in / interval處理邏輯按順序做了四件事雙重校驗(yàn)先檢查 HTTP 層是否成功、JSON 中是否帶error字段再確認(rèn)device_code、user_code、verification_uri、expires_in四項(xiàng)必填字段齊全缺任何一項(xiàng)都以STATE_FAILED_HARD終止。通知界面emit authorizeWithBrowser(verification_uri, user_code, expires_in)。信號(hào)沿 AuthFlow.cpp 中建立的連接冒泡到 MSALoginDialog.cpp 的authorizeWithBrowserWithExtra()——它把用戶碼顯示為等寬字體文本、提供一鍵復(fù)制按鈕并用qrencode現(xiàn)場(chǎng)繪制出驗(yàn)證頁(yè)的二維碼掃碼即可登錄 。啟動(dòng)到期計(jì)時(shí)器m_expiration_timer設(shè)為一次性、時(shí)長(zhǎng)expires_in秒超時(shí)直接調(diào)用 abort() 停止一切并報(bào)錯(cuò)。啟動(dòng)輪詢計(jì)時(shí)器調(diào)用startPoolTimer()進(jìn)入等待狀態(tài)。一個(gè)精妙細(xì)節(jié)在 startPoolTimer()如果到期剩余時(shí)間已不足一個(gè)輪詢間隔它會(huì)重新調(diào)用perform()申請(qǐng)一組新的設(shè)備碼避免輪詢一次都沒(méi)發(fā)出去碼就過(guò)期了的邊界情況。六、輪詢機(jī)制authorization_pending 與 slow_down 的優(yōu)雅處理每過(guò)interval秒authenticateUser() 向m_tokenUrl提交grant_type urn:ietf:params:oauth:grant-type:device_code device_code 上一步拿到的設(shè)備碼authenticationFinished() 對(duì)五種結(jié)果分別處置完全遵循 RFC 8628 §3.5服務(wù)器/網(wǎng)絡(luò)反饋處理方式authorization_pending用戶還沒(méi)在瀏覽器完成登錄 → 按原間隔繼續(xù)輪詢slow_down服務(wù)器嫌輪詢太快 →間隔 5 秒后繼續(xù)連接超時(shí)指數(shù)退避interval * 2防止雪崩式重試其他請(qǐng)求失敗不增加間隔立即再試一次其他error判定失敗STATE_FAILED_HARD終止流程注意輪詢重試復(fù)用的是m_request而非NetJob且只在拿到成功令牌時(shí)才stop()到期計(jì)時(shí)器——任何一次失敗都不會(huì)讓流程誤判為結(jié)束。七、登錄成功token 寫入 AccountData 的 5 個(gè)字段拿到令牌后代碼只寫入了 AccountData.h 中Token結(jié)構(gòu)的幾個(gè)字段m_data-msaClientID m_clientId; // 記錄是哪個(gè)客戶端拿的 token m_data-msaToken.issueInstant 當(dāng)前UTC時(shí)間; // 頒發(fā)時(shí)間 m_data-msaToken.notAfter 當(dāng)前時(shí)間 rsp.expires_in; // 過(guò)期時(shí)間 m_data-msaToken.refresh_token rsp.refresh_token; // 離線續(xù)期用 m_data-msaToken.token rsp.access_token; // 主令牌隨后以STATE_WORKING狀態(tài)發(fā)出finished(Got MSA token)——注意這里不算流程結(jié)束只是本步驟完成接下來(lái)交給上層編排。八、上層編排AuthFlow 如何串起 4 個(gè)步驟AuthFlow.cpp 根據(jù)AccountType和登錄動(dòng)作裝配步驟鏈。Ely 賬號(hào) 設(shè)備碼登錄時(shí)隊(duì)列是ElyDeviceCodeStep—— 本文主角拿到 Ely 平臺(tái)的 OAuth2 令牌ElyYggdrasilTokenStep—— 把令牌換成 YggdrasilMinecraft 服務(wù)器側(cè)令牌MinecraftProfileStepEly—— 拉取游戲檔案玩家名、UUIDGetSkinStep—— 下載皮膚數(shù)據(jù)。AuthFlow::nextStep() 每次取出隊(duì)首步驟執(zhí)行靠AuthStep::finished信號(hào)驅(qū)動(dòng)下一步任何一步進(jìn)入失敗狀態(tài)STATE_FAILED_HARD等都會(huì)通過(guò) changeState() 把賬號(hào)標(biāo)記為Expired/Errored并終止整條鏈。九、安全模型小結(jié)為什么設(shè)備碼登錄更放心 ?密碼零接觸整個(gè) ElyDeviceCodeStep.cpp 中不存在任何密碼字段憑據(jù)交換發(fā)生在瀏覽器與 Ely.by 之間。權(quán)限最小化scope 限定為account_info offline_access minecraft_server_session啟動(dòng)器拿不到超出登錄 Minecraft 所需的能力。令牌可隨時(shí)撤銷失效的只有令牌而非賬號(hào)密碼本身到期由refresh_token靜默續(xù)期體驗(yàn)與安全性兼得。十、小結(jié)一張圖看懂完整生命周期構(gòu)造(替換 clientId/scopes/URL) ↓ perform() ──POST client_idscope──→ account.ely.by/devicecode ↓ deviceAuthorizationFinished()校驗(yàn) → 彈碼二維碼 → 起雙計(jì)時(shí)器 ↓ 循環(huán)輪詢 authenticateUser()pending→繼續(xù) / slow_down→5s / 超時(shí)→退避 ↓ authenticationFinished()成功 → 寫入 msaToken → STATE_WORKING ↓ AuthFlow 繼續(xù)執(zhí)行 Yggdrasil 令牌 → 檔案 → 皮膚ElyDeviceCodeStep本體只有 34 行代碼真正的工作由父類 MSADeviceCodeStep.cpp 的狀態(tài)機(jī)完成——這種模板方法模式讓 MSA 與 Ely 兩條登錄通道共享同一套輪詢、退避與超時(shí)邏輯是理解本項(xiàng)目 OAuth2 認(rèn)證體系的最佳入口。贊分享【免費(fèi)下載鏈接】LauncherThis fork of Prism Launcher adds integrated support for Ely.by accounts.項(xiàng)目地址https://gitcode.com/GitHub_Trending/ely/Launcher點(diǎn)擊查看免費(fèi)下載相關(guān)推薦Ely Prism Launcher認(rèn)證流程源碼解析AuthFlow多步驟編排完整走讀Ely Prism Launcher認(rèn)證流程源碼解析AuthFlow多步驟編排完整走讀 Ely Prism Launcher 是基于 Prism Launch為什么Ely Prism Launcher登錄時(shí)看不到你的密碼Ely.by OAuth2安全設(shè)計(jì)原理為什么Ely Prism Launcher登錄時(shí)看不到你的密碼Ely.by OAuth2安全設(shè)計(jì)原理 使用 Ely Prism Launcher 登錄 ElyEly Prism Launcher實(shí)例數(shù)據(jù)模型MinecraftInstance與BaseInstance完整解讀Ely Prism Launcher實(shí)例數(shù)據(jù)模型MinecraftInstance與BaseInstance完整解讀 Ely Prism Launcher 是創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考