跳到主要内容

ws token 鉴权、校验

介绍

有时,我们需要在 WebSocket 建立连接前做 Token 相关鉴权、校验的业务。 框架支持此类业务的扩展,我们可以在游戏对外服部分做相关扩展。

简单的说,如果校验没通过,我们就不建立 ws 连接了,在 http 阶段就结束所有流程,可以有效的减少恶意长连接。

使用场景

WebSocket Token 通常用于身份验证和授权访问 WebSocket 连接。 当客户端尝试建立 WebSocket 连接时,服务器可以要求客户端提供一个有效的令牌作为身份验证凭据。

使用 WebSocket Token 可以实现以下功能

  • 身份验证 :通过验证令牌,服务器可以确定客户端的身份,并决定是否允许其建立 WebSocket 连接。
  • 授权访问 :令牌可以用于授权访问特定资源或执行特定操作,服务器可以根据令牌的权限级别来限制客户端对 WebSocket 连接的访问权限。
  • 安全性 :通过使用令牌进行身份验证和授权,可以提高 WebSocket 连接的安全性。 持有有效令牌的客户端才能与服务器建立连接,并且只有获得授权的客户端才能执行相应的操作。

总而言之,WebSocket Token 是一种用于身份验证和授权访问 WebSocket 连接的机制,可以提供安全性和权限控制。

如何使用

创建游戏对外服,并重写 WebSocketMicroBootstrapFlow.createVerifyHandler 方法。

  • code 5,设置 MicroBootstrapFlow 类,并重写 createVerifyHandler 方法。
  • code 8,自定义 MyWebSocketVerifyHandler 验证 Handler。
ExternalServer createExternalServer() {
DefaultExternalServerBuilder builder = ...

DefaultExternalCoreSetting setting = builder.setting();
setting.setMicroBootstrapFlow(new WebSocketMicroBootstrapFlow() {
@Override
protected WebSocketVerifyHandler createVerifyHandler() {
return new MyWebSocketVerifyHandler();
}
});

return builder.build();
}

自定义 WebSocketVerifyHandler

现在,我们自定义一个验证类 MyWebSocketVerifyHandler,继承自 WebSocketVerifyHandler 并重写 verify 方法。

  • code 4,通过 params 获取 key:value 格式的参数
  • code 9,为了简单演示,这里只将 token 放到元信息中。 在实际中,开发者可以自定义一个元信息类,来存放更复杂的数据。
  • code 11,返回 true 表示验证通过,返回 false 框架会关闭当前连接
public class MyWebSocketVerifyHandler extends WebSocketVerifyHandler {
@Override
public boolean verify(SocketUserSession userSession, Map<String, String> params) {
String token = params.get("token");
boolean verifyResult = "abc".equals(token);

var tokenValue = StringValue.of(token);
byte[] encode = DataCodecKit.encode(tokenValue);
userSession.option(UserSessionOption.attachment, encode);

return verifyResult;
}
}
提示

userSession : 是当前连接的 UserSession。

params : 当连接为 ws://127.0.0.1:10100/websocket?token=abc&name=aaaa 时。 连接 “?” 之后的参数会存放在 map params 中,格式为 k-v,如:

  • token=abc
  • name=aaaa
注意

如果不是特殊情况,不建议在这个环节做除了元信息之外的任何设置。 换句话说就是只把关键信息放到元信息中,之后统一在游戏逻辑服的 action 中做处理。

因为 WebSocket Token 相关验证只在 WS 连接方式下存在,而 TCP 、UDP 这些连接方式是不需要这些概念的。 如果把太多业务放到 verify 中,之后如果想将 WS 连接方式切换到 TCP 时,你的系统并不能得到很好的兼容。

总之,这里的建议是,在 verify 中,只保存一些关键的元信息。 即使是在 verify 中得到了 userId 也不要着急设置到 userSession 中, 而是放到元信息对象上,之后在游戏逻辑服的 action 统一做处理。

在模拟客户端中测试

  • code 6,在模拟客户端中设置需要测试的 WebsocketVerify
public class WsClient {
public static void main(String[] args) throws InterruptedException {
String websocketVerify = "?token=abc&name=aaaa";

new ClientRunOne()
.setWebsocketVerify(websocketVerify)
...
.startup();
}

...
}

Example Source Code

see https://github.com/iohao/ioGameExamples

path : SimpleExample/example/example-ws-token

  • WsVerifyApplication
  • WsClient