保护API #

有许多情况都需要限制或完全阻止客户端访问任何或所有Nakama API,例如对客户端请求执行任何所需的验证或防止客户端试图绕过您的游戏逻辑。

Nakama提供了多种途径来保护您的游戏,防范恶意客户端操作:

  • 在服务器上实现RPC或挂钩式游戏逻辑
  • 对存储对象设置访问控制。通过REST API创建的对象将始终由经过身份验证的用户拥有,您可以设置相应的读取权限来设置其他玩家是否具有对此数据的读取权限。
  • 服务器到服务器调用可通过HTTP密钥保护。
  • 使用before挂钩禁用不想让任何开发的直接访问的API。

使用before挂钩 #

要禁用任何API,在想要禁用的函数调用上注册before挂钩,而不返回请求输入而返回nil。Nakama会将任何此类情况当作禁用API调用自动处理。

在以下示例实现中,所有被注释掉的消息名称和API调用对客户端仍然可用,而其他所有消息名称和调用都被禁用:

Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
let InitModule: nkruntime.InitModule = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, initializer: nkruntime.Initializer) {
  // initializer.registerRtBefore("ChannelJoin", guardFunction);
  // initializer.registerRtBefore("ChannelLeave", guardFunction);
  // initializer.registerRtBefore("ChannelMessageSend", guardFunction);
  initializer.registerRtBefore("ChannelMessageUpdate", guardFunction);
  initializer.registerRtBefore("ChannelMessageRemove", guardFunction);
  initializer.registerRtBefore("MatchCreate", guardFunction);
  // initializer.registerRtBefore("MatchDataSend", guardFunction);
  // initializer.registerRtBefore("MatchJoin", guardFunction);
  // initializer.registerRtBefore("MatchLeave", guardFunction);
  initializer.registerRtBefore("MatchmakerAdd", guardFunction);
  initializer.registerRtBefore("MatchmakerRemove", guardFunction);
  // initializer.registerRtBefore("Ping", guardFunction);
  // initializer.registerRtBefore("Pong", guardFunction);
  initializer.registerRtBefore("StatusFollow", guardFunction);
  initializer.registerRtBefore("StatusUnfollow", guardFunction);
  initializer.registerRtBefore("StatusUpdate", guardFunction);
  // initializer.registerBeforeUpdateAccount(guardFunction);
  // initializer.registerBeforeAuthenticateApple(guardFunction);
  initializer.registerBeforeAuthenticateCustom(guardFunction);
  // initializer.registerBeforeAuthenticateDevice(guardFunction);
  initializer.registerBeforeAuthenticateEmail(guardFunction);
  // initializer.registerBeforeAuthenticateFacebook(guardFunction);
  initializer.registerBeforeAuthenticateFacebookInstantGame(guardFunction);
  // initializer.registerBeforeAuthenticateGameCenter(guardFunction);
  // initializer.registerBeforeAuthenticateGoogle(guardFunction);
  initializer.registerBeforeAuthenticateSteam(guardFunction);
  // initializer.registerBeforeListChannelMessages(guardFunction);
  initializer.registerBeforeListFriends(guardFunction);
  initializer.registerBeforeAddFriends(guardFunction);
  initializer.registerBeforeDeleteFriends(guardFunction);
  initializer.registerBeforeBlockFriends(guardFunction);
  initializer.registerBeforeImportFacebookFriends(guardFunction);
  initializer.registerBeforeCreateGroup(guardFunction);
  initializer.registerBeforeUpdateGroup(guardFunction);
  initializer.registerBeforeDeleteGroup(guardFunction);
  initializer.registerBeforeJoinGroup(guardFunction);
  initializer.registerBeforeLeaveGroup(guardFunction);
  // initializer.registerBeforeAddGroupUsers(guardFunction);
  initializer.registerBeforeBanGroupUsers(guardFunction);
  // initializer.registerBeforeKickGroupUsers(guardFunction);
  // initializer.registerBeforePromoteGroupUsers(guardFunction);
  // initializer.registerBeforeDemoteGroupUsers(guardFunction);
  // initializer.registerBeforeListGroupUsers(guardFunction);
  // initializer.registerBeforeListUserGroups(guardFunction);
  // initializer.registerBeforeListGroups(guardFunction);
  initializer.registerBeforeDeleteLeaderboardRecord(guardFunction);
  initializer.registerBeforeListLeaderboardRecords(guardFunction);
  initializer.registerBeforeWriteLeaderboardRecord(guardFunction);
  initializer.registerBeforeListLeaderboardRecordsAroundOwner(guardFunction);
  // initializer.registerBeforeLinkApple(guardFunction);
  initializer.registerBeforeLinkCustom(guardFunction);
  // initializer.registerBeforeLinkDevice(guardFunction);
  initializer.registerBeforeLinkEmail(guardFunction);
  // initializer.registerBeforeLinkFacebook(guardFunction);
  initializer.registerBeforeLinkFacebookInstantGame(guardFunction);
  // initializer.registerBeforeLinkGameCenter(guardFunction);
  // initializer.registerBeforeLinkGoogle(guardFunction);
  initializer.registerBeforeLinkSteam(guardFunction);
  // initializer.registerBeforeListNotifications(guardFunction);
  // initializer.registerBeforeDeleteNotifications(guardFunction);
  initializer.registerBeforeListStorageObjects(guardFunction);
  initializer.registerBeforeReadStorageObjects(guardFunction);
  initializer.registerBeforeWriteStorageObjects(guardFunction);
  initializer.registerBeforeDeleteStorageObjects(guardFunction);
  initializer.registerBeforeJoinTournament(guardFunction);
  initializer.registerBeforeListTournamentRecords(guardFunction);
  initializer.registerBeforeListTournaments(guardFunction);
  initializer.registerBeforeWriteTournamentRecord(guardFunction);
  initializer.registerBeforeListTournamentRecordsAroundOwner(guardFunction);
  // initializer.registerBeforeUnlinkApple(guardFunction);
  initializer.registerBeforeUnlinkCustom(guardFunction);
  // initializer.registerBeforeUnlinkDevice(guardFunction);
  initializer.registerBeforeUnlinkEmail(guardFunction);
  // initializer.registerBeforeUnlinkFacebook(guardFunction);
  initializer.registerBeforeUnlinkFacebookInstantGame(guardFunction);
  initializer.registerBeforeUnlinkGameCenter(guardFunction);
  initializer.registerBeforeUnlinkSteam(guardFunction);
  initializer.registerBeforeGetUsers(guardFunction);
}

const guardFunction = function() {
  return null;
};

// Reference InitModule to avoid it getting removed on build
!InitModule && InitModule.bind(null);
无法返回null以防止TypeScript服务器运行时中的registerBeforeGetAccount函数。如需防止TypeScript中的此函数,可以抛出错误,例如throw new Error("Function disabled")。注意,这将在Nakama中生成错误记录。