Closed cqjjjzr closed 5 years ago
另外最新版(2.1.6)无法使用,HMCL提示不是合法的验证服务器,Fiddler抓包发现服务器返回的是“Undefined property: stdClass::$column_name”。
之前也有人提到过这个功能 ( https://github.com/bs-community/yggdrasil-api/issues/2 ),通过转发请求至 Mojang 官方认证服务器确实可以兼容正版用户直接进服,但是皮肤显示这方面比较难办。
首先 Mojang 官方认证服务器返回的玩家 Profile 都是用 Mojang 的私钥进行过数据签名的,而且原版客户都安也只认 Mojang 的私钥签出来的 Profile。
如果一个【非正版】用户进入了服务器,服务器会从皮肤站获取该玩家的 Profile(用的自定义私钥进行的签名,因为我们不可能拿得到 Mojang 的私钥)。服务器拿到 Profile 后会分发给服务器内的所有玩家,但是玩家中的未加载 authlib-injector 的原版客户端是不认这个数据签名的,所以 【正版】用户将无法加载【非正版】用户的皮肤。反之亦然,使用了 authlib-injector 的非正版用户也将无法加载正版用户的皮肤,因为他们的客户端只认皮肤站的私钥签出来的 Profile。
虽然也可以直接禁用 Profile 的数据签名,但我不确定原版 Minecraft 客户端在 Profile 数据签名缺失的情况下是否能够正常加载皮肤……
那么是否可以让登录部分交给authlib injector,而皮肤的加载交给CSL之类的工具呢?
或者我们让正版用户也加载authlib-injector,但是authlib-injector此时并不去关心启动器已经传入的验证措施,直接patch,让服务器来处理与Mojang API交互的问题是否可行?
关于 Undefined property: stdClass::$column_name
的问题,请提供一下 /storage/logs/laravel.log
日志里的详细报错信息。
翻看了一下,其中并没有什么有用的信息...最早的日志来自setup页面说明日志并没有清空,后面就全部变成trace一样的日志了.
在 .env
中添加一行:
YGG_VERBOSE_LOG = true
然后尝试重现该问题,再提供一下 /storage/logs/yggdrasil-xxx.log
里的日志。
see #5 .
bump. see 楼上的楼上的楼上的楼上的楼上。
我以前尝试过实现,但遇到很多问题。目前 authlib-injector 是不会考虑实现你要求的功能的,除非有人能给出一套完整且可行的解决方案。
https://github.com/bs-community/yggdrasil-api/issues/4#issuecomment-408678226
理论上来讲应该可以,但是我没有试过。
https://github.com/bs-community/yggdrasil-api/issues/4#issuecomment-408678298
这个有什么关系吗?
启动器不加载 authlib-injector 的话,用户使用正版账号登录,启动器从 Mojang 那边拿到 Access Token,传给游戏本体并启动;而如果启动器加载 authlib-injector 却还是使用正版账号登录的话,就是多了一层皮肤站作请求转发,Access Token 最终还是从 Mojang 那边拿到的啊?
这正是我需要的效果啊。而皮肤的加载由CSL之类的实现
https://github.com/bs-community/yggdrasil-api/issues/4#issuecomment-408681131 但这似乎并不是authlib injector需要实现的啊.这是服务端的修改 Misclick, sry.
如果是这样的话那还好,只需要在 join
和 hasJoined
两个 API 做一下转发就好。
如果需要不安装 Mod 显示皮肤的话,那根据 https://github.com/bs-community/yggdrasil-api/issues/4#issuecomment-408678101 所说的,就只能「只有正版用户的皮肤能显示」和「只有非正版用户的皮肤能显示」两者二选一了。
(当然,近期内是不会支持的,我最近忙)
see #6. 但是我闲啊(=・ω・=)
是否可以考虑修改Mojang服务器发过来的Profile数据,重新用皮肤站的私钥签名Profile数据?这样至少可以使得利用 authlib-injector 的用户能正常显示正版用户的皮肤。同时 @yushijinhun 是否可以考虑给authlib-injector实现一个参数,使得agent仅获取验证服务器的metadata,然后去patch签名白名单部分,而不去patch其他部分(authserver/sessionserver)?
@cqjjjzr
修改Mojang服务器发过来的Profile数据,重新用皮肤站的私钥签名Profile数据?这样至少可以使得利用 authlib-injector 的用户能正常显示正版用户的皮肤
做,那正版用户将无法显示所有皮肤。给authlib-injector实现一个参数,使得agent仅获取验证服务器的metadata,然后去patch签名白名单部分,而不去patch其他部分
请问你指在正版上使用 authlib-injector 吗?既然你所说的那些正版用户有使用 authlib-injector 的条件,那为何不让他们直接使用整套 authlib-injector 的逻辑呢?因为官方启动器不支持使用自定义 Yggdrasil API 验证?
@cqjjjzr 对于你所说的 2,请看 Yggdrasil 服务端技术规范#会话部分。
@yushijinhun 声称会给 authlib-injector 制作一个GUI,用于登录,但目前并没有实现(至少MCBBS上是这样说的)。因此对于不支持 authlib-injector 登录的启动器(MultiMC,官方启动器,etc. 不是每个人都喜欢HMCL)就无法登录。
那么你的需求就是,让这些「使用 MultiMC 这类不支持 authlib-injector 的启动器的正版用户」也能进入使用了本插件的 Minecraft 服务器咯?
是的,如果能通过仅加载一个 authlib-injector(不在外部提供 authlib-injector 所使用的 Yggdrasil 服务器的登录信息)就可以实现皮肤的正确加载就更好了。
另外@yushijinhun 如果 authlib-injector patch 且仅 patch 了签名白名单,那么是否所有的皮肤在正版用户处都能正确加载了呢?
另外我在 #6 中提出了新的 commant。
其实早期的 authlib-injector 是支持使用配置文件的,你目前这个需求只需要修改配置文件让其仅替换用于材质数据签名验证的公钥,再通过启动器的自定义 JVM 参数加载即可。不过现在 authlib-injector 不再支持使用配置文件了。
正是需要这个功能。
那么这样做其实意义有限,仅仅是对那些「有正版账号,但是想使用不支持自定义认证服务器地址的启动器的用户」有意义。
目前主流支持 authlib-injector 的启动器并不多。如果这种基于 authlib-injector的解决方案能广泛使用实际上这样的用户非常多。HMCL目前对多实例仍然不如某些启动器完美。而增加对更多启动器的支持始终是好的(且加上这个仅替换公钥的方案相对(hmcl加强多实例支持,GUI方案实现,更多启动器支持authlib injector)来说似乎并不是一个非常复杂的过程,甚至我们可以考虑通过替换authlib 的jar实现)且结合复杂性的考虑我有理由相信@yushijinhun 的GUI方案短时间内无法实现。
另外我想出来用名称获取角色的api的使用场景了。回头会尝试修改。
@cqjjjzr
如果这个 PR 所实现的功能会违背下面的前提,这个 PR 是不会进入到下一个版本中的。
首先,无论是否开启这个功能,BS 用户是一定要能在单人模式下看见自己的皮肤,并在多人模式下看见其他 BS 用户的皮肤的。因此,【查询角色属性】、【按名称批量查询角色】和【服务端验证客户端】这三个 API 的响应,必须优先使用 BS 上的数据,并且对 BS 用户的角色属性进行签名时使用 BS 的密钥。
保证上面这点,是保证 yggdrasil-api 的基本可用性,是不应该被打破的。
修改游戏文件是绝对不允许的,特别是是修改 authlib JAR。
你提出的 https://github.com/bs-community/yggdrasil-api/pull/6#issuecomment-409486873 ,在这里就有了答案:当 BS 和 Mojang 都有数据时一定是 BS 优先,亦即先查询 BS,若未找到,再查询 Mojang。【查询角色属性】和【按名称批量查询角色】这两个请求必须做转发处理,否则会破坏数据一致性(试想服务器里有这个玩家,但却查不到对应角色)。
接下来我们考虑数据冲突问题。首先如果数据存在冲突,一定是 BS 和 Mojang 上有角色名相同,但 UUID 不同的两个角色。UUID 因为生成算法的问题,是不会相同的。这就意味着,我们在只用 UUID 做标识的情况下(【查询角色属性】),不需要考虑数据冲突。而在【按名称批量查询角色】这种情况下,应优先返回 BS 上的角色。
而在处理【服务端验证客户端】时,则略显复杂。我们假设 BS 上有角色 A,Mojang 有角色 B,两者角色名相同,UUID 不同。首先角色 A 必须能正常进服,然后我们考虑角色 B:
我再来看你的需求,我有两种理解方式:
无论实现哪个需求,都需要进行以下操作:使用 BS 上的数据处理【服务端验证客户端】请求失败后,请求转发到 Mojang(暂不考虑其中的签名)。这是你 PR 中做的。
我们分别看这两个需求:
如果你要同时考虑需求 1 和需求 2,那我可以给出一张表: 下面表格中:
BS
代表 BS 用户MOJANG
代表正版用户MOJANG(AI)
代表使用 authlib-inejctor 的正版用户A -> B
表示 A 是否能看见 B 的皮肤使用哪个密钥签名正版用户的角色属性? | BS -> MOJANG | BS -> Mojang(AI) | Mojang -> BS | Mojang -> Mojang | Mojang -> Mojang(AI) | Mojang(AI) -> BS | Mojang(AI) -> Mojang | Mojang(AI) -> Mojang(AI) |
---|---|---|---|---|---|---|---|---|
Mojang | N | N | N | Y | Y | Y | N | N |
BS | Y | Y | N | N | N | Y | Y | Y |
你可能会提问,是否能对不同种类的用户返回不同的角色属性签名。这是不可行的,除非修改 MC 服务端。玩家在进服时,验证服务端将角色属性发送给 MC 服务端,MC 服务端再把角色属性分发给各个客户端,因此分发到每个客户端的角色属性签名都是相同的,无法进行差别对待。
在最后我想给出一个忠告:如果你想作出一个改动,你必须将该改动会影响到的所有方面都考虑清楚,不论这有多么复杂。逃避是无法解决问题的。
我在研究完这篇文档之后会尝试作出修补的PR。如果无法实现则我建议 Fork 一个新的版本包含已有的功能。
EDIT: 使用 307 状态码指引客户端进行转发,避免服务端转发。
如果要支持正版用户使用 authlib-injector,则需要考虑到以下问题:
join 请求转发的逻辑是:如果其中的 accessToken 无效,并且 BS 上查无此角色,就返回 HTTP 307 https://sessionserver.mojang.com/session/minecraft/join
。只有加载了 authlib-injector 的正版用户会触发这种情况。
优点:安全,皮肤站无法获得正版用户的 accessToken。
缺点:authlib-injector 需要做出修改。用户需要添加额外参数来关闭 join 转发,若忘记添加则无法进服。
优点:authlib-injector 无需做出修改,用户直接添加 -javaagent:authlib-injector.jar=$API_ROOT
参数即可。
缺点:皮肤站可以得知正版用户 accessToken。
@yushijinhun
我选择不转发。原因:你提到的折中方案同时吸取了两者的缺点。
ip
参数有一定概率不会失效,如果 Mojang 的服务器会判定 X-Forwarded-For
或 X-Real-IP
请求头,但我们不应依赖此种不稳定的可能性;accessToken
,我认为这是不可接受的;authlib-injector
需要作出的修改并不大,我将在处理完这边的修改之后过去尝试修改;accessToken
,但是无法加入可以给用户一个明确的信号——配置出现了问题;我同时需要实现 1 与 2。首先操作 a) 与 b) 都需要实现。即客户端验证公钥需要替换为 BS 的,同时增加 BS 域名到白名单。
同时在服务端,我会将 Profile 的签名替换为基于 BS 的私钥进行的。这几个决定基于如下考虑:
我认为你对 yggdrasil-api 的考虑有误。本 API 基本可用性应该为“合法的用户必须能够进入服务器”。
但如果你与 @printempw 坚持你们的定义,那么也没有问题,只需要直接优先采用 BS 的数据即可。
你提到的数据冲突的场景分析与我所想一致。
首先考虑「服务器验证客户端」的情况,我认为我们需要允许角色 B 进服。这种情况广泛存在于现行有正版账号,但是因为要进入盗版服务器而在皮肤站上有账号且两者名称相同的用户。
角色 B 不存在于 BS 服务器上,而客户端会先通过 /join
向 Mojang 服务器提交加入请求。而后加入服务器,显然此时如果用户名已经在线服务端会直接拒绝登录。若不在线则服务端向 BS 服务器请求 /hasJoined
。BS 服务器上显然没有这个记录,但 BS 会直接转发 Mojang 服务器的结果,因此 B 能够进服,但 UUID 不同。
我们不需要对同一个人,BS 与 Mojang 的用户名相同,却混合两种方案登录的情况提供支持。服务器会由于 UUID 不同而直接将两者视为不同的用户。
在你的 「验证系统数据一致性」你提出两者有数据的时候 BS 优先。但是这造成如果服务器开启白名单,而某玩家正版账户与 BS 账户重名(常见),此时即使服务器通过 /whitelist <id>
给予了玩家白名单,其在通过正版登录的时候仍然无法进入服务器。
而这种情况造成的最大问题不在白名单上,而在于封禁上。如果有玩家犯事儿甚至无法将其封禁——其直接使用正版账户登录即可。同时 op 也有这个问题。
且如果用了 Mojang 优先,则情况相反,但问题仍旧存在。
目前这种问题我没想出来好的解决方案。我想出的解决方案是服务端手动管理 ops.json
,whitelists.json
与 bans.json
中的条目,或者利用其它工具,例如服务端插件等。你提到皮肤问题无法利用差别对待解决,那么这个问题可以通过差别对待解决吗?
或许我们应该尝试在 BS 服务器上已经存在同样 ID 条目的情况下返回 BS 上的同名 UUID 而非 Mojang 服务器中的 UUID?那么这样若用户先用正版登录,后面又在 BS 上注册了账号会不会导致用户数据的丢失?
从你的忠告可以看出你希望所有问题都能完美解决,在这之后再给个 PR。但是我认为先让一些基础的功能可以运作(例如本例,在不影响 BS 用户的一切正常使用的情况下,让正版用户先能进服,再去考虑皮肤的问题)再去考虑一些进阶的特性(例如皮肤的显示)是必要的。实际上这个问题我并不会逃避,但我认为将其压入 TO-DO List 并让正版玩家先能进服比先在 Issue 里面盖上几十楼之后再一次性提交更好。
按紧急程度排序。
@cqjjjzr 我已经修改了转发方案,请你再看一下。
我赞成 @cqjjjzr 关于不转发 join API 的意见,既然这些「就是想用不支持 authlib-injector 的启动器同时还想进入使用了 authlib-injector 的服务器的正版用户」应该有足够的能力正确配置他的启动器。
@cqjjjzr 我已经修改了转发方案,请你再看一下。
请参看「join API 转发相关」一节中的5. 。另外我们并不清楚客户端是否支持 HTTP 转发。
我已测试,客户端支持 307 重定向。
我仍然坚持我的意见,但我认为可以考虑增加一个服务端的设置项,允许服务器转发 join 请求。另外服务端能否发送客户端可以显示的错误信息?
我认为 BS 的 Yggdrasil API 服务无需转发 join
请求。
虽然我明白即使不转发皮肤站也能获取
accessToken
,但是无法加入可以给用户一个明确的信号——配置出现了问题;
既然你有这个看法,这就意味着上述不转发的优点已经失去。我拒绝无理由地增加配置复杂性,除非你能给出不转发的其他优点。
实际上虽然这个理由非常扯淡,但是我想给出的理由是“这不优雅”。
另外 join
的转发意味着 AI 不作出任何修改,即 AI patch掉了所有的对服务器的引用,这会带来更多问题,例如单人模式下正版用户的皮肤加载,想象一下某人的 BS 与 正版服务器皮肤不一致,结果登着正版显示出了 BS 的皮肤???
authlib-injector 的许可证我不会做出放松。我已经遇到不少服务器修改了 authlib-injector,甚至对 Yggdrasil 协议做出了 breaking changes,这就导致用户只能使用他们的专有启动器,而这与 authlib-injector 的目标相违背。
单人模式下正版用户的皮肤加载,想象一下某人的 BS 与 正版服务器皮肤不一致,结果登着正版显示出了 BS 的皮肤???
这是不存在的。我已经在之前回答了:
接下来我们考虑数据冲突问题。首先如果数据存在冲突,一定是 BS 和 Mojang 上有角色名相同,但 UUID 不同的两个角色。UUID 因为生成算法的问题,是不会相同的。
了解。但是我认为出现多方意见冲突时“加个配置项”是最简单、能满足所有人胃口的。
我需要了解的是 authlib-injector 是否允许其未修改的二进制发行版本随服务器整合包一并shipping?
我需要了解的是 authlib-injector 是否允许其未修改的二进制发行版本随服务器整合包一并shipping?
允许,只要不修改 JAR 包中内容。
我想就玩家名冲突补充一点:如果 BS 上有角色 A,Mojang 有角色 B,两者名称相同。A 和 B 被认为是不同角色。
因此现在主要的冲突点为 join
转发与否,
那么「按名称批量查询角色」的重名冲突呢?
那么「按名称批量查询角色」的重名冲突呢?
那我之前的分析有漏洞,应该禁止 Mojang 同名角色进服。
yggdrasil-api 基本可用性到底是什么?
指启用该功能后不影响 BS 用户的使用。
那我之前的分析有漏洞,应该禁止 Mojang 同名角色进服。
这等价于若某角色希望通过正版登录进服,则其不能在 BS 上存在同名角色?这显然不可接受。特别是可能存在抢注盗注的问题(在大服务器尤其严重)
您好。 请问是否可能实现在Session的校验处实现若无法找到登录情况则去找mojang官方服务器验证Token?因为MultiMC等纯正版启动器并不支持authlib-injector. 谢谢!