服务端安全认证
本章主要介绍服务端通过 Soket.IO 和 WebSyncTable 接口与爱智通信时如何进行安全认证。
概述
为保证通信安全,爱智提供了基于 Token 和随机数 Srand 的双重保障,两项认证均通过才能完成通信。随机数以分钟级进行刷新,过期随机数无法通过安全验证。
获取 Token 和 Srand
具体请参见 获取 Token 和 Srand。
集成 Token 与 Srand
不同通讯协议的集成方法如下:
Socket.IO 集成 Token 和 Srand
- 在开发环境执行以下命令,安装 socket.io-client 和 vue-socket.io-extended 包。
npm install socket.io-client vue-socket.io-extended
- 参考以下示例,在 src 目录下创建 socket.ts 文件,引入安装包, 编写 socket.io 的相关代码。
//示例代码: 示例代码实现了 socket.io 在异常情况下的重试机制
import Vue from "vue";
import VueSocketIOExt from "vue-socket.io-extended";
import SocketIO from "socket.io-client";
import { tokenRef } from "./service/api";
export let socket!: SocketIOClient.Socket;
const addListener = (
client: SocketIOClient.Socket,
evt: string,
fn: () => void
) => {
if (!client.hasListeners(evt)) {
client.on(evt, fn);
}
};
export const initSocket = (data: TokenResponse) => {
// 创建 socketio 连接
socket = SocketIO({
query: { "edger-token": data.token, "edger-srand": data.srand },
transports: ["websocket"],
});
const errorHandler = () => {
// 如果 token 或 srand 不存在, 则终止 socketio 连接
if (!tokenRef.token || !tokenRef.srand) {
return;
}
socket.io.opts.query = {
...socket.io.opts.query,
"edger-token": tokenRef.token,
"edger-srand": tokenRef.srand,
} as Record<string, any>;
};
// 异常断联后, 重新尝试 socket 连接
addListener(socket, "error", errorHandler);
addListener(socket, "connect_error", errorHandler);
addListener(socket, "connect_timeout", errorHandler);
addListener(socket, "reconnect_error", errorHandler);
addListener(socket, "reconnect_failed", errorHandler);
addListener(socket, "disconnect", errorHandler);
Vue.use(VueSocketIOExt, socket);
};
- 参考以下示例,在 main.ts 文件中引入 socket.ts 文件,并初始化 socket.io 连接。
//main.ts 示例代码
...
import { initSocket } from './socket'
const updateToken = (data: TokenResponse) => {
if (data) {
initSocket(data)
}
}
...
WebSyncTable 集成 Token 和 Srand
- 在开发环境执行以下命令,安装 @edgeros/synctable 包。
npm install @edgeros/web-synctable
- 参考以下示例,在需要使用 SyncTable 的文件中集成 Token 和 Srand。
//示例代码
<template>
...
</template>
<script lang='ts'>
import { Component, Vue } from 'vue-property-decorator';
import { tokenRef } from '@/service/api';
import { SyncTable } from '@edgeros/web-synctable';
@Component({
components: {}
})
export default class TestApp extends Vue {
private table: any
// 实例创建完成之后创建 SyncTable 连接
created () {
if (!this.table) {
this.connectSyncTable()
}
}
// 实例销毁后断开 SyncTable 连接
destroyed () {
this.disconnectSyncTable()
}
private connectSyncTable () {
const signboard = 'xxx.xxx' // SyncTable 表名
// 创建的 SyncTable 是一个类似 Map 的对象, 后续操作可以通过后台约定的 key 值获取对应数据
const table = new window.SyncTable(`wss://${window.location.host}`, signboard, {token: tokenRef.token, srand: tokenRef.srand});
this.table = table
table.addEventListener('update', (key: string, value: number[]) => {
// 在监听到更新后,对数据进行一些处理
})
}
private disconnectSyncTable () {
if (this.table) {
this.table.close()
this.table = undefined
}
}
}
</script>