ws token 鉴权、校验
介绍
有时,我们需要在 WebSocket 建立连接前做 Token 相关鉴权、校验的业务。 如果校验没通过,我们就不建立 ws 连接了,在 http 阶段就结束所有流程,可以有效的减少恶意长连接。
框架支持此类业务的扩展,我们可以在对外服部分做相关扩展。
使用场景
WebSocket Token 通常用于身份验证和授权访问 WebSocket 连接。 当客户端尝试建立 WebSocket 连接时,服务器可以要求客户端提供一个有效的令牌作为身份验证凭据。
使用 WebSocket Token 可以实现以下功能
- 身份验证 :通过验证令牌,服务器可以确定客户端的身份,并决定是否允许其建立 WebSocket 连接。
- 授权访问 :令牌可以用于授权访问特定资源或执行特定操作,服务器可以根据令牌的权限级别来限制客户端对 WebSocket 连接的访问权限。
- 安全性 :通过使用令牌进行身份验证和授权,可以提高 WebSocket 连接的安全性。 持有有效令牌的客户端才能与服务器建立连接,并且只有获得授权的客户端才能执行相应的操作。
总而言之,WebSocket Token 是一种用于身份验证和授权访问 WebSocket 连接的机制,可以提供安全性和权限控制。
Example Source Code
see https://github.com/iohao/ionet-examples
path : ionet-cookbook-code
- MyWebSocketVerifyHandler
- WsVerifyApplication
- WsClient
自定义 WebSocketVerifyHandler
现在,我们自定义一个验证类 MyWebSocketVerifyHandler,继承 WebSocketVerifyHandler 并重写 verify 方法。
- code 5,通过 params 获取 key:value 格式的参数
- code 11~18,创建一个请求并发送给逻辑服。
- code 23,返回 true 表示验证通过,返回 false 框架会关闭当前连接。
public final class MyWebSocketVerifyHandler extends WebSocketVerifyHandler {
@Override
protected boolean verify(SocketUserSession userSession, Map<String, String> params) {
// ws://127.0.0.1:10100/websocket?token=abc&name=aaaa
String token = params.get("token");
boolean verifyResult = "abc".equals(token);
log.info("verify name: {}", params.get("name"));
if (verifyResult) {
// Send a login message
var cmdInfo = HallCmd.of(HallCmd.loginVerify);
byte[] data = DataCodecManager.getDataCodec().encode(token);
var message = userSession.ofMessage(cmdInfo);
message.setData(data);
// send message to logicServer
this.convenientCommunication.request(message);
}
// 返回 true 表示验证通过,返回 false 框架会关闭连接。
// Return true means verification passed, return false means the framework will close the connection.
return verifyResult;
}
}
提示
userSession : 是当前连接的 UserSession。
params : 当连接为 ws://127.0.0.1:10100/websocket?token=abc&name=aaaa 时。
连接 “?” 之后的参数会存放在 map params 中,格式为 k-v,如:
- token=abc
- name=aaaa
如何使用
创建对外服,并重写 WebSocketMicroBootstrapFlow.createVerifyHandler 方法。
- code 6,设置自定义的验证类。
ExternalServer createExternalServer() {
var builder = ExternalMapper.builder(ExternalGlobalConfig.externalPort);
// WebSocketVerifyHandler
var microBootstrapFlow = new WebSocketMicroBootstrapFlow();
microBootstrapFlow.verifyHandler = new MyWebSocketVerifyHandler();
builder.setMicroBootstrapFlow(microBootstrapFlow);
return builder.build();
}
在模拟客户端中测试
- code 7,在模拟客户端中设置需要测试的
WebsocketVerify。
public final class WsClient {
static void main() {
String websocketVerify = "?token=abc&name=aaaa";
new ClientRunOne()
...
.setWebsocketVerify(websocketVerify)
.startup();
}
...
}