「第一弹」工程实践记录 —— Minecraft Yggdrasil 设计篇
说在前面
本文所涉及的技术栈是 Go 语言。Yggdrasil 是由 Mojang 开发的一种基于 REST 的身份验证协议,主要用于 Minecraft(Java 版 1.6 及更高版本,后续简称为 MC)及其相关游戏。
请注意,这一篇文章主要理解的是实践中的思想,并非手把手的保姆教程(我其实不是很喜欢做保姆教程),对于教程或实践类型,我更期望可以通过我讲解的内容有一套自己的理解体系,这样才能真学到东西,而不是只是用。
距离我上次开 MC 服务器已经过了四五年了,最早接触服务器的时候,还能从 16 年左右开始算,也就是我初中的时候,现在已经大四准备毕业工作了。
那为什么还是打算开一个 MC 服务器呢?感觉更多还是因为热爱吧,还是想自己开一个服务器有人一起来玩(就算最后开成类似于公益的都可以,并不是很期望做成过于付费的体系,主要是因为付费体系的难度权衡要经常调整,不然就会造成付费用户严重倾向。)
因为服务器还在策划,怎么着都要在新年过完之后才开始做详细的策划书之类的内容,但并不影响这一篇文章的内容。
这里做的东西类似于仿制一个 Minecraft 正版登录的一套系统。所以我只要决定了开设 Minecraft Server 对于我对未来的设计来说,他就是我需要开发的内容。也正因为是这样,我手头有一个从零开始的项目,顺带记录一下。
内容准备
这里,由于我自己做过一个脚手架:
(那篇文章,不好意思,这个仓库其实已经创建了很久了,从最早的辅助我的一些工具库,发展到现在已经变化了很多内容了。我还是习惯叫做库,后面我自己也改一下,这东西教叫依赖,自己实现的一些东西可以叫库,基于一些原有的东西再做结构是脚手架;我有些东西有时候我知道是啥,但是有的时候说不上来那个词,不好意思。)
(这个还用不到,归到第二弹才开始用到实际技术栈选择和基础框架建设之类的东西。原本不打算分章节的时候打算写一块的,这里现在既然写了,意思基本就是后续的一些项目设计和架构设计根据我这个脚手架的基础进行设计,可以的话给个 star 呗)
https://github.com/bamboo-services/bamboo-base-go
https://linux.do/t/topic/1555985
对于剩下所需要准备的资料,从下面依照思维顺序开始一步一步引入,不在这里一次性说明所有的需要的依赖项。不然就很像一个教程只是教别人如何构建一个 Minecraft Yggdrasil,这并不是我的初衷。
不需要被 Yggdrasil 这个名词感到害怕,我在后续部分有对这个名词进行解释。另外大概你只要知道 Minecraft(我的世界)是什么东西就可以了。
思考
首先,我们先明确我们要做什么?为什么要这么做?我做这个有什么意义?
因为对于一个 MC 私服 (后续可能称为:MC 服务器) 来说,其实并没有必要实现一套 Yggdrasil(非官方的技术登录系统)。市面上有很多的插件,例如 AuthmeReloaded 啊 FastLogin 之类的插件,就算不使用插件,也存在 LittleSkin 现成的皮肤站,自己都可以部署一个,内部也存在实现了一套 Yggdrasil 技术规范的内容。
所以,就有一个问题,单纯“为了让服务器能玩”而实现 Yggdrasil,本身是没有必要的。
但是最大的问题就是在于,大多数私服的技术体系本身是高度碎片化的。
现在的 MC 玩家已经少了很多了,加上在我开服务器的时候大多数除了顶头能力的有完全自己的技术栈。其他都是 MC 社区【例如 MCBBS(已经挂了)、MineBBS 之类的社区】,在这里面有很多的插件,可以自己组合实现服务器的很多功能。
大多数也是学生或者热爱的人,那么在这一批的人次里面,期望又要熟悉技术开发和运营本身就是比较难的事情。所以私服这里技术体系还是很高度碎片化的,而且想做出出众的很难的呀。
OK,吐槽完了。下面还是站在从需求出发,为什么需要实现这一个内容?
对于目前的 MC 服务器体系来说,非常杂。包括 MC 的原生正版机制 UUID。如果有些服务器需要实现正版离线一块登录并且还要保证 UUID 相关的问题。对于正版来说(Microsoft Xbox 购买的正版账号),Mojang/Session Server 在在线模式下分配并返回一个UUID,对于离线的用户生成机制是基于 UUIDv3(MD5) 来对文本 OfflinePlayer:<Username> 进行生成。
以及后续的皮肤问题,离线用户其实并没有皮肤,服务器就算能够显示皮肤,很多情况也是因为 SkinsRestorer 之类的皮肤插件实现的皮肤可以查看。对于 SkinsRestorer 来说,这里其实对于离线用户本身依然是没有自己的皮肤的;内置了 MojangServer 正版皮肤的获取,也有 LittleSkin 皮肤的获取。离线用户依然要到其他地方上传自己的皮肤
(体验来说就会相对割裂,上面举例的只是一小部分的问题,就会让玩家在很多地方辗转折腾,并不存在一个体系;当然你可能在这里有一个疑问,例如 LittleSkin 来说,其实是一个非常好的网站。因为离线用户也可以实现只要在这里安装了 SkinsRestorer 插件就可以显示自己皮肤,在很多服务器都不需要额外折腾对吧。)
在这里我想说的是,对于玩家角度来说这个做法实际上不是错的,而且很方便,因为统一了。但是对于服主(经营者)来说,并没有整理成自己的体系,说难听点就是没有在某些方面体现出自己的地方一些便捷特色或者游戏内特色也会导致因为同质类型或者服务器内游戏环境导致玩家离开。那么再换一个角度思考,既然插件 SkinsRestorer 可以实现获取正版皮肤以及 LittleSkin 的皮肤,那么为什么我不能集成到自己实现 Yggdrasil 技术规范的项目里面呢,新用户自动尝试获取皮肤对吧。
并且这一套系统做完,账号也是自己的管理体系下。后面可以很好对接到很多的服务,例如自己开设一个内部论坛也好,或者工单(就算不做公益也能做指定账号充值体系)。
最终这样可以减少不少辅助插件的开销,不用很多杂七杂八的插件。因为这一类插件很多时候就是解决开设离线服务器导致的状态无法幂等而进行处理的,还可以防止批量注册机注册小号账号(在原始的 AuthmeReloaded 插件很多情况下都是可以直接用 /register 进行注册,或者换账号注册。忘记密码如果没有配置 email 还是比较麻烦的,相比能够在网站进行在线处理是麻烦很多的)。
那么,现在再站在运营方角度来考虑。因为自己开设服务器的时候,虽然用户(玩家)一定是最高的【用户是上帝】,但是在有些地方,立场需要站在运营方进行考虑(换句话来说,就算你有些东西再痛恨,相对来说还是很方便,能够尽可能留住用户方向考虑,那要体现出花费了心思)。
这个时候就有人要问了。哎呀筱锋,对于整这么一套自己的东西需要自己上传皮肤自己注册一套不麻烦吗,一些玩家觉得麻烦就不来了就走了,那咋办?
请注意,虽然说用户是上帝,但是不是每一个人都是上帝。对于只是随意找找服务器玩玩做开销和期望找一个容纳的社区这个方式不太一样。因为对于目前的 Minecraft 环境来说,期望通过游戏内容和独家内容撑起来其实相对来说比较艰难。并且这一类服务器并不背靠网易代理的我的世界,是可能存在因为没有背靠网易代理而说非法开设服务器之类的话术。所以需要明确自己受众的目标玩家是哪一类。不能过于盲目接受任何类型的玩家,并不利于形成自己的游戏社区环境。
也所谓无规矩不成方圆,在这里体系化做出来后,给玩家展现出来的是这家服务器底子不错。看上去正规没毛病,体制服务完善,相对来说用户的体感就会不错,如果游戏内环境做的不错,那么就可以提升环境内用户留存率。
需求整理
现在,我们需要思考明确一下,它是什么?
- 从定义来说他是: 随着 Java 版 1.6.1 的发布,Mojang 引入了一个名为 Yggdrasil 的新认证系统,根据 Mojang 的说法,开发者应采用 Yggdrasil 身份验证系统来实现自定义登录,但他们强烈建议不要收集用户的凭据。此身份验证方案已被 Microsoft 身份验证 取代。
- 从解释理解来说: 他是 Minecraft Server 内置的用户识别模块,在玩家在 HMCL 或者 PCL2 启动器登录后,可以拿到一个状态,服务器会向 Yggdrasil 问,这个哥们真没问题吧。 Yggdrasil 说,保真的;信任链条闭环,那么你就顺利进入服务器了。
那么,他的核心需求就是 “登录” 。首要目的,或者说一定要实现的内容就是实现 Minecraft Server 以及 Minecraft Launcher 端的登录态的桥梁。剩下可以按需随意进行扩展。
这里,你确定的是一个最核心的流程。他本质目的是干什么,如果只是单单实现其本质目的,那么现在干的所有内容都属于重复造轮子。现成非常多这种的内容没有必要自己实现。
可以思考一下。
请注意,下面说的东西就有点跟说官话差不多了,毕竟做需求整理和需求分析的。说的会稍微明确一些,这里面有很多东西实际上不说都懂,说出来就显得那啥。但是做需求分析就应该说出来。
- 统一认证服务(SSO): 这个 Yggdrasil 可以实现所有服务器之外用户登录行为的扩展。因为所有的行为都可以分配到唯一的 UUID,所以可以根据这里做一个唯一用户主键。例如就可以实现论坛发帖、在工单系统反馈、甚至在网页商城内购的唯一凭证。(请注意,由于我自己有一套自己写好的 OIDC OAuth2 服务,所以我并不打算这里实现统一认证服务,但是基于这个逻辑,依然是保证 Yggdrasil 对应后续其他例如工单之类的内容都可以有保证唯一 ID 的信息)
- 数据主权: 基于从根源数据就是自己的,所有玩家的行为画像、登录习惯、资产数据,不会存在第三方例如 LittleSkin 之类的内容(虽然 AuthmeReloaded 也可以实现,但是数据量有限,自己实现这个逻辑实际上比 AuthmeReloaded 简单,而且可控,扩展性更强)也很方便做后续类似于“玩家年度报告”的内容,增强玩家个人荣誉感和社区感。
- 消除非幂等,插件减负: 目前大多数离线服务器为了解决登录问题(尤其在线和离线同时兼容的情况下),不得不堆砌大量的辅助插件。由于各插件实现逻辑的差异,往往会导致 UUID 生成算法不一致,皮肤加载延迟或失效等问题,因为身份验证的状态是非幂等的。这样可以让服务器以“正版模式”运行,从底层实现 UUID 生成的一致性。这不仅能砍掉 80% 的辅助插件,降低服务器性能开销,更能确保玩家数据在不同子服、不同模组间的绝对兼容与唯一性。
- 风控管理: 像例如 AuthmeReloaded 之类的插件,实现其登录是游戏内
/login实现的,往往发生在玩家已经进入世界之后。而且对于 AuthmeReloaded 来说,主要是实现登录,并没有符合国内例如手机号验证或者邮箱验证之类的内容。相对来说是很好刷账号的,就算限制同一 IP,因为大部分国内网路环境原因,限制 IP 基本没啥用(重启下路由器呗或者之类的事情就解决了)。而且有很多辅助客户端,可以自动执行指令批量注册。但是从启动器就卡死的地方就很少了。 - 生态闭环: 在这里系统的最大价值在于将 MC 账号与我们自己的业务数据库(如论坛、商城、工单系统)深度绑定。玩家信息不再是散落在不同插件数据库里的条目,而是拥有统一画像的生态用户。
最终就可以整理还需要的功能需求如下:用户体系、皮肤体系、服务体系、成就体系、消息推送体系、商城体系、开放接口体系、论坛体系(后期了)等【这里说“等”是我没想到的,因为实现上面部分的功能已经完成我所设想的体系了,基本足够了】。
当然说了这么多,其实这里面做的东西有大材小用的地方。可能对于我自己来说可能想的太好了(指的是我的服务器),我期望我的服务器可以开好,也可以后续很多人来玩,也有可能直接没落。但是如果面对现实来挂钩例如开销时间和钱(社会衡量体系)来说,我做的这个东西相对来说意义不算大。因为我做完这个内容也可能因为导致运营不善导致服务器很快没掉。这里驱动我的更多是热情,而不是赚钱。
可行性分析
还没开始写代码哦,这个文章教的是整个过程体系过程和架构思考的过程。那么需求确立了,就要开始探究对于这一套需求体系。是否真的可以做出来。
说实话,写这一段逻辑对我来说稍微有点“碎碎念”了,按我接触过的开发来说,这套方案 绝对是可以实现的 !(即使有一些偏差,但是这些地方都是比较细节方面,大体方向不影响则问题不大,这里指的是实际干活来说。毕竟实践来说按照理论这么干,就过于死板显得不可变化,进度有的时候会拖的非常非常长)。
嗯嗯!要把这块写出来,是为了体现一个 必要的思考过程 过程。虽然对于相对熟悉的内容来说,可以直接凭借一些历史总结经验直接给出“可行”方案,但是需要建立在持续思考和积累行为上。所以这里我就写的详细一些,把一些“直觉”写出来哈。
我这里的探索分析,并不是分析 Minecraft Yggdrasil 是否可行,他一定可行。因为已经被 LitteSkin 或者 Blessing Skin 实现过了,所以代码来说,一定是可行的。
这里探索分析的内容是,功能需求是否能够集成到 Yggdrasil 做成体系成套。分析可行性分析的是是否能够体系成套或者后期实现的时候逻辑闭环,而不是探索单面(或单体)是否可行。
我解释一下我上述说的内容喵~
- 可行性分析不应该分析单面技术是否可行,我认为的阶段里面,这个层面其实在需求调研的时候(不管是不是公司里面,公司需求也会有评审),就应该看这一项技术是否可行。在这里才是探索单面技术是否可行的时候。(例如:需求评审的时候,假设 Minecraft Server 支持 Yggdrasil 或者另外的 OAuth2,为什么不用 OAuth2 而用 Yggdrasil;在这里就是进行具体单面技术的评审是否可行。或者说 Yggdrasil 这里面用到 RSA 签名,去探索 Go 语言下 Yggdrasil 的 RSA 可行性,这是不对的。它一定可以。对于任何语言来说,属于计算机基础的东西,他基本一定可以这么干,不可以对于非绝对出来几个月的语言来说这一套都会有相关依赖可以使用。而类似于 Yggdrasil 协议体系都是基于语言实现之上的,只要语言可以做到要求的输出协议及格式,那就可以做到。)
- 对于逻辑闭环来说
- 只要可以解决用户的根本唯一问题(即主键用户唯一键做到的极大边界值),后续的扩展根据设计来说只要设计的不差,都可以加表或者扩展字段都可以实现这些内容。
- 另外一个就是,你所实现的内容是否过于与核心内容分割(他是不是应该需要做的,还是可以割舍的,或者不适合在这里面出现的)。
首先我先列出来上述所我说到的一些重要内容:
- 确认采用 Minecraft Yggdrasil 进行
- 自己存在一个 OIDC OAuth2
- 主要需要实现的内容是为 Minecraft Client 提供登录锚点,以及 Minecraft Server 提供认证锚点
- 需要提供服务器特点绑定内容(如:【工单系统,举报系统】服务体系、成就体系等)
综上,在这里的可行性分析,那我们来开始分析一下这里是否可行 nia~。
对于常规的的 Yggdrasil 来说,是否支持 OIDC OAuth2 登录呢?
我们先来解析一下常规的 Yggdrasil 登录,本质上来说与正常网站的注册登录毫无差异;核心内容体现在跟 OAuth2 一样有一套明文规定对外抛出的接口应该需要怎么样。所以解释跟正常的站点一样,注册时候采用账号密码进行注册,登录的时候采用账号密码登录。
那么这个登录流程根据 Yggdrasil 服务端技术规范 的内容,其客户端登录流程流程解释如图
flowchart TD
A[用户在启动器输入账号密码] --> B[POST /authenticate]
B --> C{验证账号密码}
C -->|失败| D[返回错误信息]
C -->|成功| E{该账号有多个角色?}
E -->|是| F[返回 availableProfiles 列表]
F --> G[用户选择角色<br/>xiao_lfeng 或 happyvally_lmx]
G --> H[返回 accessToken + selectedProfile]
E -->|否| H
H --> I[启动器启动 Minecraft 客户端]
I --> J[客户端携带 accessToken 加入服务器]
J --> K[服务器向 Yggdrasil 验证 session]
K --> L{验证通过?}
L -->|是| M[允许玩家加入]
L -->|否| N[拒绝加入]
而服务端的验证流程如图:
flowchart TD
A[玩家请求加入服务器] --> B[服务器生成 serverId]
B --> C[发送 serverId 给客户端]
C --> D[客户端携带 accessToken<br/>向 Yggdrasil 报告 serverId]
D --> E{Yggdrasil 验证 accessToken}
E -->|无效| F[返回 403 错误]
F --> G[客户端显示认证失败]
E -->|有效| H[Yggdrasil 记录 session<br/>username + serverId]
H --> I[客户端发送加密响应给服务器]
I --> J[服务器调用 hasJoined API<br/>查询该 username 的 session]
J --> K{Yggdrasil 查找 session}
K -->|未找到| L[返回空/204]
L --> M[服务器拒绝玩家加入]
K -->|找到| N[返回 Profile JSON<br/>包含 UUID、皮肤等信息]
N --> O{服务器验证 Profile}
O -->|验证失败| M
O -->|验证成功| P[服务器允许玩家加入]
P --> Q[加载玩家数据、皮肤、披风]
Q --> R[玩家进入游戏世界]
那么在在这里,现在关注点你需要注意到 客户端 这里的流程中 验证账号密码 ;这里是一个核心疑问地方。这里需要验证账号密码登录。
- 疑问点: 如果采用 OIDC OAuth2 作为主要登录,不采用账号密码的设计,那么账号密码从哪里来?
- 疑问点: 又或者说,客户端(如 HMCL/PCL2)能否自定义重定向到 OAuth2 换取登录态回跳到 Yggdrasil 换取登录态后来激活类似于协议链接(常见 http 属于 http 协议,浏览器可以可以通过不同的前缀协议打开不同软件,例如 Telegram 可以使用 tg://resolve?domain=xiao_lfeng 协议链接方式来打开软件进行授权)。
其实这里有一个不好意思的地方,我既然直接说出来了这里的两个疑问点,代表我本身就推测出来可能存在的问题,这个很大程度也是经验导向,如果真的想问如何推理出来这个疑问点。我也不好回答。我努力整理了一下了:有一些经验的地方是一定要凭借的;之后就是在使用 Minecraft Launcher(我的世界启动器)时候或者了解 Yggdrasil 时候,是否直接注意过自定义登录的地方以及客户端实现方案。而不是直接凭借专有名词的技术栈 Yggdrasil 直接看原理导向等等(这里当然没有总结完,只是我当时写文章的时候尽力想了一下,看看我后面能不能补充一下。但是有一个地方确实,能够提出这里的地方要么你就是真实受伤用户,要么你做过类似的内容能够举一反三来说明出来,存在经验导向在内的【根据已有或者已实践的内容进行推导】。)
以上部分为根据概念疑点以及自身需求来进行合理推测是否可行。这里是需要验证的是否可行。
我们开始逻辑闭环哈,上面是可能抛出来的疑问点,要解决的疑问点有两个。第一个密码从何而来,因为 OAuth2 授权不会提供密码,并且无法保证 OAuth2 的用户名是否是用户真的需要当做的用户名。第二个问题就是对于我这里的差异性,采用 OAuth2 属于现代化授权方案,那么是否存在 HMCL/PCL2 有所更新实现了这一套允许的方案。
账号密码思考验证
对于第一个地方,账号密码的问题。这里并没有什么可以查找的内容,只需要确定实现逻辑即可。这里我给出几种解决方案。
- 最原本的方案,获取 OAuth2 提供 scope 为 profile 可以拿到 username 当做用户信息。如果发现是新用户,要求设置一个初始化密码。(缺陷:用户后期无法修改用户名,并且 OAuth2 对应账号是 1:1 自定义及可客制化程度巨低,不如不引入 OAuth2)
- OAuth2 作为平台登录,进入后引导要求创建一个基础用户名,以及设置一个游戏密码。在这里实现用户和游戏用户名关系为 1:N 一个用户可以创建多个用户名(即多个不同的 UUID 游戏账号,也可以修改名字,并且可以实现对于不同的 Tier 等级机制允许创建不同个数的游戏账号)(账号管理的复杂度增加,相当于一个用户存在多个游戏账号,存在管理和代码的逻辑麻烦。如果说采用这个形式但是还是保证 1:1 的情况下进行代码设计。那么就可以直接按照第一个方案进行修改)
- 依然是 OAuth2 作为平台登录,采用令牌方式,创建用户的时候采用令牌方案。玩家在 Web 端发起登录,将会生成一个临时 code 作为密码,玩家携带这个令牌作为密码在客户端(HMCL/PCL2)进行登录。(隐私安全性极强,代价是登录较为麻烦复杂,若期望用户登录过程丝滑流畅并不推荐此登录方案。并且 HMCL/PCL2 并不支持点击登录打开 Web 方式直接跳转到指定页面。否则这个方案可以实现,那么就可以做到类似于 OAuth2 的回跳方式跳回客户端实现登录)
那么进行权衡比较,第二种是相对合适的。安全性不错,用户上手难度不大,并且可以根据游戏内等级机制构造不同 Tier 方式进行分发不同游戏账户。
其实这是我的难点,因为我有的时候会跟他们一块玩游戏,但是身份是服主不好玩自身还带权限。所以需要注册一个新的用户进行游玩,但是本质都是我。那么 OAuth2 可以做到只有一个“我”,但是实际游戏内角色可以不同。以及可以为其他玩家授权管理,建筑师等特殊角色。又或者说,我的游戏社区中有一个人认识的玩家批次不同(有一群好友 A,和一群好友 B 一块玩)这样可以很方便分开游戏账号来玩,避免混淆。
如果你想问,如果开放多个账号用户刷免费礼物怎么办?说个实在话,如果管的太严格了,什么一定保证一个人只有一个账号或者想尽各种办法限制一个账号。那么游戏的可玩水平一定下降(用户一定觉得限制太多了,就没意思了),在这里考虑不如考虑对于礼包的配置如何处理更合理,少量不是特别多用户这个行为下不会影响游戏资源平衡性。因为就算你限制死他们也有办法,不如 Tier1 情况之类只给一个,后面时间足够,奖励到 Tier2 后允许 2 个游戏账号。也可以从玩家心理角度(激励相容)变向不会考虑刷一堆小号的做法。
激励相容: 【Gemini解释】源于机制设计理论,意思是你设计的规则,能让玩家在追求自己利益最大化(比如想要更多角色、更好的礼包)时,行为正好符合你作为服主期望的目标(比如保持服务器活跃、不恶意刷号)。通过 Tier 等级来解锁账号上限,就是让玩家的“贪婪”变成了“长期留存的动力”。
那么,最终的结构定义就变为了
| 定义 | 解释 | 备注 |
|---|---|---|
| 平台账号 | 平台账号,不可改变 | 代表玩家(或用户)的唯一表达式 |
| 游戏账号 | Yggdrasil 的 profile(name + UUID) | 根据 Tier 机制(或者其他方式),可以提供多账号 |
| 游戏口令 | 唯一密码,平台内设置游戏账号 | 多 GameProfile 都保证其密码的唯一性 |
| 绑定关系 | Account 1 -> N GameProfile | 采用 1:N 关系 |
现在就明确了如果使用 OIDC OAuth2 作为 Yggdrasil 的平台登录,实际游戏身份从何而来。下面给你画一张架构设计图,这个图在实际中应该是自己可以想明白知道是什么样子就可以。我画出来是为了解释我的想法。

这里就可以比较出相比最初的账号密码注册,不采用 OAuth2 的方式差异。在这里实际上节省的是因为缺少注册时候提交的账号以及密码这里的缺陷导致需要思考的内容。(所以也就是说,如果代码或者相关的实践比较多的话,我上述说的很大部分的内容,实际上都可以按照常规经验进行总结快速得出。例如如果你做过 OAuth2 对接其他系统的开发,以及了解 Yggdrasil 的情况下(相比于账号密码登录,学习阶段最早认识的东西,差异性在哪),如何快速进行分析迭代找出相对合理的。
客户端思考验证
对于客户端的验证,最好的方案就是直接下载一个 HMCL 或者 PCL2 直接上手尝试,然后再去推理验证。
这里我的电脑是 Macbook,所以我就用 HMCL 了,这玩意提供 .jar 包版本的,可以直接启动。

这里因为不是所有读文章的人都玩过,或者摸索过这类东西。我这里只是举例意思,如果是自己有项目去做分析的时候,如果某些内容可以直接尝试,就直接尝试这个过程去试试。
在这里,尝试的过程就是找到账户这里添加 认证服务器 ,这里会弹出来一个认证的窗口。

由于本项目使用的是 Yggdrasil 技术规范,也就是说,这个东西并不是全新的,市面上一定有存在的。而且不少,所以才会在这里提供出来“外置登录(认证服务器)”字样,在这里由于 MC 圈基本熟悉例如 LittleSkin 之类的内容(只是玩家不一定知道可以当做认证服务器而已)。这里我们可以自己尝试添加一个 LittleSkin 的内容进行测试。




现在客户端部分的尝试已经完成了,已经成功登录并且选择了其中一个账号了。现在,开设一个服务端进行登录尝试。在登录尝试中将会使用默认的官方配置和启动时候通过 jvm 参数修改的方式启动服务端尝试认证服务。
请注意,我这里描述的通过 Jvm 参数 是错误的。我做实践类型文章的时候,并不会全流程做完才开始写,这样会疏漏我中间的一些关键节点。这里就是我其中一个先入为主的概念(而且是我对于 Yggdrasil 第三方文档内并非有完整的认知)。所以我保留我的错误写法。表明我的思考过程。
在实际的文档中, Yggdrasil 技术规范是 Mojang 所表态的技术规范,他并不是最终的服务器部分呈现形式,服务器部分需要使用 authlib-injector.jar 。为什么?
这里牵扯到 Java 有关的内容,对于 Java 的服务器配置来说,可以使用
bukkit.yml、spigot.yml也好server.properties也罢,更甚至可以采用 jvm 虚拟机强制变量替换-Dxxx=yyy。 都不存在一个“标准参数”可以让服务端说:我不用 Mojang 的认证服务器了。所以,这里需要 authlib-injector.jar 原因就是需要当做 Java Agent + ClassLoader Hook 方式进行劫持替换。(为什么?Minecraft 的认证地址是硬编码在 Authlib 内部的;所以是必须使用这个 jar 的!)
所以上述我说的 通过 jvm 参数修改的方式启动服务端尝试认证服务 ,是我作为经验总结里面大部分 SpringBoot 相关开发进行的先入为主的概念导致。
碎碎念:所以说经验这玩意,有时候不一定是好事,它会趋向你从你的经历中思考事情。但是同时,你也需要有自己批判的目光在内,不能让自己一直错下去,得纠正自己。不过也不是说经验直接代入就是错误的,烦的应该是知错不改。在有的时候,没有自己的一套层级逻辑进入(即使是错的),方向不知道从何开始找起,就算这个是错的,可以通过这里可行性论证分析来确认最终结果(这就是为啥来说必须要做可行性分析,分析的内容并不是具体的逻辑正确与否,而是逻辑是否闭环)。
咳咳,扯远了。回到这里,现在开设一个服务器。目前采用直接链接的 Mojang 的认证服务器,进行认证尝试。

这里直接出现认证错误,直接认证用户名失败。
现在开始尝试注入,在这里是成功实现了的。
1 | /Users/xiaolfeng/Library/Java/JavaVirtualMachines/azul-21.0.7/Contents/Home/bin/java \ |

至此,通过自己的实现这个过程去验证过程流程和完整性,自己就会得出一个思维链是否成立。可以画出图像如下所示:

在这里通过这个完整的过程总结来看,在 HMCL 中并不能实现类似于 OAuth2 那样进行回跳方式进行处理操作,使用的是账号密码进行登录,最后选择指定用户进行授权的过程。解决了上述疑问的问题: 能否自定义重定向到 OAuth2 换取登录态回跳到 Yggdrasil 换取登录态后来激活类似于协议链接
不过我在浏览 Github 项目的时候,我看到一个草案,在 authlib-injector(Yggdrasil 协议技术的第三方连接服务端实现)需要开始支持 OAuth2 授权。但是目前这个草案被关闭了(标记 Issue 为暂时没有规划,后面再看看有没有这方面的更新计划了)
第一弹总结
在这一弹里,主要说的是在实际写代码之前,也就是对这个项目立项。这个项目需要什么的范围内来写的。从你最先开始思考为什么要他,以及缺少的需求进行补齐进行的。
对于可行性分析这里,我只举例了登录授权过程的例子,因为我刚好想到这里其中两个疑问点(也正巧是我期望从实践方向和原理直接导向方向【也可以叫做经验导向】)。
原本还想找多几个例子了,从疑问点来说不需要嘞~
这里我第二个总结的内容就是,在我认为的工程化体系中,不能说单单只会技术或者更直白点,只会代码如何写。应该需要了解工程实际的整体思考内容(这个是实习后的感悟)。这样才是实质上的提升,技术相对来说绝对是“最好学”的,思维永远是最难学的。我也不能保证我的思维一定很好【毕竟才大四,还有很长的路,我也没实际接触过更加优秀的人,只能一步一步自己探索提升自己】。
这次学聪明了(bushi,这次想着分开写了。其实主要是工程实践类型的,我一般都是边做边写的。如果真的等我边做边写这个项目已经完成了之后再发这个文章,那就到了过年期间了。总感觉怪怪的,还是想着拆开来发吧。这样阅读压力也没那么大。
之前这个文章 凌中的锋雨 | 了解 AI 及其工具运行逻辑来自我提效 花了我两三天的时间完成它,写完后三万多字。我自己写的都不想写了。估计你们看到也疲惫不太想看了,这次做成分批发【才…才不是我期望多一些阅读量呢 (傲娇】。
我的文章并不属于科普或者完整教程类型文章,都是属于引导式教导风格,说的可能比较接地气。如果存在不严谨的地方欢迎指正。










