跳到主要内容

路由访问权限控制

介绍

本篇将介绍路由访问权限相关的内容,学习完本篇后,你将可以控制客户端是否能访问某些 action。

比如要想控制某个模块的访问权限,即玩家不能直接地访问某个模块的相关功能。 在传统路由中,要实现这些控制是很难的或者说是很麻烦的,但在 ioGame 中却非常的简单。

例如,我们定义一个内部功能模块的主路由为 10,只需在游戏对外服中判断这个主路由即可。 这样,外界就无法访问到我们内部模块主路由为 10 的所有 action 了。


访问权限控制的目的

  1. 避免客户端访问服务器不存在的 action。
  2. 避免客户端访问服务器不公开的 action。
  3. 避免客户端没登录就访问 action。

使用场景

不公开的路由

假设我们在服务器提供了一个增加金币的 action,而这个 action 只能内部访问或者说通过 GM 后台来访问。 如果客户端请求了该路由地址,服务器会给出一个路由不存在的错误码。


不存在的路由

假设服务器只提供了路由为 1-1 的 action,如果客户端请求所填写的路由不存在,服务器会给出一个路由不存在的错误码。


没登录就访问业务方法

假设我们的业务方法是需要登录后才能访问的,如果客户端没有登录就访问我们的 action,服务器会给出一个路由不存在的错误码。


以上案例中的控制在 ioGame 中是简单的。

路由权限的控制是普遍存在的,如果一个攻击者伪造一些请求,而这些请求的路由不在服务器中,那么将是危险的。 通过框架提供的路由权限控制,可以起到很好的防范作用。 比如我们可以记录客户端触发不存在路由的次数,当达到一定次数时,就将该 ip 拉入黑名单一段时间。

如何使用

严格登录,路由访问权限的控制

严格登录指的是,如果玩家没有登录是不能访问任何 action 的。

  • code 1,获取游戏对外服的路由访问权限控制对象。
  • code 2,表示登录才能访问 action,否则不能访问任何 action。
  • code 3,添加不需要登录也能访问的 action。
  • code 4,添加不需要登录也能访问的主路由(范围)
var accessAuthenticationHook = ExternalGlobalConfig.accessAuthenticationHook;
accessAuthenticationHook.setVerifyIdentity(true);
accessAuthenticationHook.addIgnoreAuthCmd(1, 1);
accessAuthenticationHook.addIgnoreAuthCmd(2);

拒绝玩家访问权限的控制

有些 action 只能内部访问,比如增加金币、敏感数值的增加等。 这些 action 是不能由外部直接访问的,这里说的外部指的是连接中的玩家

  • code 2,拒绝主路由为 10 的访问请求
  • code 3,拒绝主路由为 11、子路由为 1 的访问请求
var accessAuthenticationHook = ExternalGlobalConfig.accessAuthenticationHook;
accessAuthenticationHook.addRejectionCmd(10);
accessAuthenticationHook.addRejectionCmd(11, 1);

从上面代码中,我们可以看见访问接口提供了两个方法,一个用于范围路由控制的,一个用于精准路由控制的,这样对应的路由将不能由外部的真实玩家直接访问。

注意事项

注意

路由权限相关的代码需要放到游戏对外服中,因为是在游戏对外服做的权限控制。

扩展阅读,关于路由权限设计的讨论

对于路由权限的疑问会有两点

  1. 为什么不在 ActionMethod 添加一个属性做路由拒绝控制。
  2. 为什么不新增一个注解在 action 方法上标记。

这两点将来也有开发者会问到,这里提前说明一下这么设计的意图。 下面,我们将讨论为什么不在 ActionMethod 做扩展,而使用 AccessAuthenticationHook 来做路由权限设计。

不对 ActionMethod 做属性扩展的原因

不在 ActionMethod 做属性扩展的原因有下面几个方面的考虑

  • 单一职责
  • 配置分散
  • 影响框架稳定性

单一职责

单一职责原则明确规定每个类或方法仅负责一件事情。 然而,在 ActionMethod 中进行属性扩展会引发一系列问题。 这将提升注解使用的复杂度,增加学习成本与维护成本,同时还会导致耦合问题的出现。 比如,未来若有其他类似功能需要扩展,人们很可能首先想到在 ActionMethod 上添加属性来予以支持。 这种通过增加属性数量的扩展方式,会对已经稳定的代码造成影响,显然违背了单一职责原则。

以当前为例,给 ActionMethod 添加上拒绝路由的属性后,就可能会考虑在注解上添加不登录也能访问路由的属性。 倘若未来还有其他类似功能扩展,也极有可能继续在 ActionMethod 上添加属性。 在前期业务量较少的时候,这种以增加属性的方式进行功能扩展或许不会让人察觉有何不妥。 但是,一旦业务积累到一定程度,各种问题便会纷纷显现。 这不仅会致使维护成本增加以及产生耦合问题,还会提高新进开发者的学习成本。 所以,相信你肯定不愿意看到并且也不想去学习一个包含数十个属性的注解。


配置分散

如果在 ActionMethod 中添加属性来做路由拒绝配置,会使得配置分散在各个地方不利于快速查找。 相比之下,AccessAuthenticationHook 可以将配置集中到一个地方,这样就能快速知道大概有哪些路由做了相关配置。

而通过注解方式因为是耦合在注解的属性中,就很难快速知道哪些路由做了相关配置。 当然,这也许可以通过工具的搜索来达到快速查找到相关的配置,但搜索出来的信息也是零散的,分布在各个文件中的。


影响框架稳定性

AccessAuthenticationHook 是支持配置路由拒绝范围的, 如果打算在 ActionMethod 做改动,我们还得改造 ActionController 注解,让其也能支持范围。 因为打算对之前稳定的代码做改动,并且将来还有可能再改动,则有可能造成框架的不稳定性。 此外,也会增加学习与使用成本。

而通过新增一个注解来做拒绝相关功能,则可以避免这种风险,因为这符合单一职责原则。 但是新增注解也有其缺点,在后面会说明。

AccessAuthenticationHook 的优势

相比于注解方式,AccessAuthenticationHook 的优点有

  • 避免注解数量的增加。
  • 配置相对集中。
  • 灵活性与应急。
  • 性能优势。

避免注解数量的增加

AccessAuthenticationHook 不需要增加新注解来实现路由拒绝功能, 而新增注解则会增加框架的注解数量,这也会增加学习成本。 单看这一条注解目前是看不出学习成本的,但积攒的数量多了就会非常明显。


配置相对集中

使用注解来控制权限,会将分散这些配置在多个 action 类或 action 方法中。 这会增加后续维护成本,因为配置分区,所以阅读代码将耗费更多的时间。

而通过 AccessAuthenticationHook,我们可以将配置集中在一起。 不需要到处查找哪个 action 类或哪个 action 方法配置了权限。


灵活性与应急

AccessAuthenticationHook 可以动态地增加或删除路由拒绝配置,而不需要修改代码或重新部署。 这样可以应对一些紧急情况,比如发现某个 action 存在 bug(假设 bug 是无限领取宝箱), 那么可以通过动态配置来控制玩家不能访问该路由,从而避免或减少损失的扩大

而注解方式则做不到这一点,既然注解做不到这一点,就意味着这条注解是可有可无, 既然可有可无那么新增注解的方案也可以不用考虑了。


性能优势

AccessAuthenticationHook 可以让请求在游戏对外服就触发路由拒绝, 不必让请求到达游戏逻辑服,从而节省了网络资源和服务器压力。

小结

综上,不在 ActionMethod 做扩展而使用 AccessAuthenticationHook 的原因和优势。主要有以下几点:

  • 不在 ActionMethod 做扩展是为了遵循单一职责原则,避免配置分散和可能引发框架不稳定性。
  • 使用 AccessAuthenticationHook 是为了减少注解数量,集中管理配置,提高灵活性和性能。

也说明了为什么不对 ActionController 、 ActionMethod 做属性的扩展,为什么不使用新增注解的方式。