Minecraft 微软正版验证流程及 Python 实现

Minecraft 微软正版验证流程及 Python 实现


欢迎阅读文章。文章是帆域空间的主题内容组成,开始阅读吧!

前言

Minecraft Mojang 账户迁移至 Microsoft 微软账户似乎已经近乎尾声,新的微软账户需要新的正版验证方式。这里我们将讨论整套的验证流程,并研究其使用 Python 实现的可能性。

本教程使用到的 Python 模块

requests
PySide2(或 PyQt5)

(Tip:本文系自帆域旧站点 www.fancraft.top 搬运而来。)

开始

在浏览器窗口登录

首先,第一步是需要玩家登陆他本人的微软账户。为了方便玩家在这个页面进行更多操作,我们需要创建一个浏览器窗口,在其中加载微软账户的登录页面。PyQt 和 PySide 提供可用的浏览器窗口,您需要做的是在这个窗口中加载下面这个 URL:

https://login.live.com/oauth20_authorize.srf
?client_id=00000000402b5328
&response_type=code
&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL
&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf

请不要修改这其中的任何内容,这是登录 Minecraft 专用的页面。您可以在自己的浏览器中尝试访问这个 URL,进行登录之后,您应当被重定向到另一个空白页面,其 URL 应为:

https://login.live.com/oauth20_desktop.srf?code=<code>&lc=<不重要>

我们需要做的,就是提取这个重定向 URL 中的 <code> ,这就是第一步。

如下的 Python 代码可以实现这个步骤:

注意,虽然此代码被写在我的某个启动器项目中,但只有这样的代码并不能真正创建一个可见的窗口。如果您想要直接使用此代码,请使用搜索引擎学习如何添加 QApplication(sys.argv)。另外,FormAuth() 是一个自定义的 Widget 窗口类,auth_microsoft_2 是连接到第二步的绑定函数。

关闭窗口,开始验证

重定向并获取到 code 之后,接下来您需要使用这个 code 获取微软授权令牌 access_token。此后的步骤不再需要浏览器窗口,其一是因为不再需要用户确认任何信息,另外是防止一些不必要的用户隐私泄露。

下一步,向 https://login.live.com/oauth20_token.srf 发起 POST 请求,负载格式如下:

{
  "client_id": "00000000402b5328",
  "code": <code>,
  "grant_type": "authorization_code",
  "redirect_uri": "https://login.live.com/oauth20_desktop.srf",
  "scope": "service::user.auth.xboxlive.com::MBI_SSL"
}

code 对应的值中装载上一步获取的 code,其它的值不做改变;在请求头中设置 Content-Type: application/x-www-form-urlencoded,然后发送请求。

响应看起来应当如下:

 {
   "token_type":"bearer",
   "expires_in":86400,
   "scope":"service::user.auth.xboxlive.com::MBI_SSL",
   "access_token":<access_token>,
   "refresh_token":<refresh_token>,
   "user_id":"889ed4a3d844f672",
   "foci":"1"
 }

从响应中提取 access_tokenrefresh_token 两个令牌,前一个令牌应该比后一个令牌长一点(就一点,假的,长了好多)

access_token 是进行下一步验证所需要的微软验证令牌,我们现在已经通过了微软的身份验证。下一步,是向 Xbox live 进行身份验证,这也是微软的服务之一。验证 URL 为 https://user.auth.xboxlive.com/user/authenticate,您需要向其发送 POST 请求,负载如下:

{
  "Properties": {
    "AuthMethod": "RPS",
    "SiteName": "user.auth.xboxlive.com",
    "RpsTicket": access_token // 第二步中获取的访问令牌
    },
  "RelyingParty": "http://auth.xboxlive.com",
  "TokenType": "JWT"
 }

不要忘记设置 Content-Type: application/json;帆帆测试时没有设置 Accept: application/json 也能进行验证,如果您只接收到奇奇怪怪的返回值和返回代码,不妨加上试试。

如果没有异常,您应当收到如下响应:

{
  "IssueInstant":"2020-12-07T19:52:08.4463796Z",
  "NotAfter":"2020-12-21T19:52:08.4463796Z",
  "Token":token, // 保存它,这是你的 Xbox live 令牌
  "DisplayClaims":{
     "xui":[
        {
           "uhs":"uhs" // 保存它,这是一个用户信息哈希值
        }
     ]
  }
}

保存 tokenuhs(是 user hash 的意思),然后开始下一步验证。

下一步的验证方是 XSTS,XSTS 会返回我们可用的 XSTS 令牌(没错,还是一个中间令牌)。验证 URL 是 https://xsts.auth.xboxlive.com/xsts/authorize,依然是 POST 请求,负载如下:

{
  "Properties": {
      "SandboxId": "RETAIL",
      "UserTokens": [
          token // 你上一步中获取的 token 就填在这儿
      ]
  },
  "RelyingParty": "rp://api.minecraftservices.com/",
  "TokenType": "JWT"
}

同样设置 Content-Type: application/json,然后发送,响应应该如下:

{
  "IssueInstant":"2020-12-07T19:52:09.2345095Z",
  "NotAfter":"2020-12-08T11:52:09.2345095Z",
  "Token":token, // 保存它,这是你的 XSTS 令牌
  "DisplayClaims":{
    "xui":[
       {
          "uhs":"uhs" // 与上个请求相同
       }
    ]
  }
}

现在,我们终于可以回归到 Minecraft 本身上了。通过 XSTS 令牌和 uhs,我们可以获取到用于启动游戏的 Minecraft 访问令牌。接下来让我们转向 https://api.minecraftservices.com/authentication/login_with_xbox,向其发送 POST 请求,附上一个简洁干净的负载:

{
  "identityToken": "XBL3.0 x=<uhs>;<xsts_token>"  // 在这里添加之前获取的 uhs 和 XSTS 令牌
}

您应当收到如下响应:

{
  "username" : "some uuid", // 这并不是该用户的 UUID
  "roles" : [ ],
  "access_token" : minecraft_access_token, // JWT,可以使用的 Minecraft 访问令牌
!
  "token_type" : "Bearer",
  "expires_in" : 86400
}

保存这个 minecraft_access_token,然后——不要着急,直到现在为止我们都还没有获取这个微软账户拥有的 Minecraft 用户名——我们甚至没有检查其是否真的拥有 Minecraft 呢!

接下来的步骤继续需要我们向 Minecraft 进行验证,向 https://api.minecraftservices.com/entitlements/mcstore 发送一个 GET 请求,把 minecraft_access_token 塞到请求头里:

Authorization: Bearer token // 只有 token 是你获取的 Minecraft 访问令牌,Bearer 不要动它,不然会报 401!

如果对应的账户拥有游戏资格,则会返回一堆东西;如果不然,则返回空负载。

检测到返回了有效的内容之后,我们就可以继续获取这个账户的 Minecraft 用户名和 UUID 用来启动游戏。向 https://api.minecraftservices.com/minecraft/profile 发送一个 GET 请求,使用与上一步同样的请求头,接收到如下负载:

{
 "id" : UUID, // 账号的真实 UUID
 "name" : PlayerName, // 该账号的 Minecraft 用户名
 "skins" : [ {
   "id" : "6a6e65e5-76dd-4c3c-a625-162924514568",
   "state" : "ACTIVE",
   "url" : url,  // 指向一个纹理,应该是皮肤的图片文件
   "variant" : "CLASSIC",
   "alias" : "STEVE"
 } ],
 "capes" : [ ]
}

从中提取 nameid 两个值,其他的值可选。现在,我们就已经获得了启动 Minecraft 所需的全部信息。

以下是整个步骤的 Python 实现,使用了 requests 网络库。

附注

我是个菜鸟,别骂我(抱头就跑 啊 头没了)

本人 Python 目前只有入门水平,这边给的代码也跑不起来(因为你没有我这边的一整个环境,我各种引用外置库搞得乱七八糟的(捂脸))

过阵子我会把这个项目传到 GitHub 或者 Gitee 上,然后大家可以去研究,现在先将就着看一看吧。

欸嘿~(再次抱头就跑)


验证流程中有一处获取了 refresh_token,这个令牌可以用于刷新对应的 access_token 的有效期,从而确保最终的 minecraft_access_token 的有效性,在外部链接第一条中已有详细描述,这里不再说明。

外部链接

Zh:Microsoft Authentication Scheme – wiki.vg

【编程开发】初探新版Minecraft正版验证方法 – 哔哩哔哩 (bilibili.com)

Minecraft新版验证方法的解决方案 – 知乎 (zhihu.com)


本文已经结束,下方是随机推荐。此外,您也可以在本站发布文章哦~
© 版权声明
THE END
喜欢就支持一下吧
点赞7赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容