thingsboard/summary/03-核心模块源码分析/02-设备认证与会话管理.md

353 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ThingsBoard 设备认证与会话管理源码分析
## 1. 概述
ThingsBoard 支持多种设备认证方式和会话管理机制。设备通过传输层MQTT、CoAP、HTTP等连接后需要进行认证才能建立会话。
## 2. 设备认证
### 2.1 认证流程
```
设备连接 -> 传输层接收 -> 验证设备凭证 -> 创建会话 -> 发送到设备 Actor
```
### 2.2 设备认证服务
**位置**: `application/src/main/java/org/thingsboard/server/service/security/device/DefaultDeviceAuthService.java`
**关键方法**:
```java
/**
* 处理设备认证请求
* @param credentialsFilter 设备凭证过滤器
* @return 认证结果
*/
@Override
public DeviceAuthResult process(DeviceCredentialsFilter credentialsFilter) {
log.trace("Lookup device credentials using filter {}", credentialsFilter);
// 1. 根据凭证ID查找设备凭证
DeviceCredentials credentials = deviceCredentialsService
.findDeviceCredentialsByCredentialsId(credentialsFilter.getCredentialsId());
if (credentials != null) {
log.trace("Credentials found {}", credentials);
// 2. 验证凭证类型是否匹配
if (credentials.getCredentialsType() == credentialsFilter.getCredentialsType()) {
switch (credentials.getCredentialsType()) {
case ACCESS_TOKEN:
// Access Token 认证凭证ID直接匹配凭证值
return DeviceAuthResult.of(credentials.getDeviceId());
case X509_CERTIFICATE:
// X509 证书认证
return DeviceAuthResult.of(credentials.getDeviceId());
case LWM2M_CREDENTIALS:
// LWM2M 凭证认证
return DeviceAuthResult.of(credentials.getDeviceId());
default:
return DeviceAuthResult.of("Credentials Type is not supported yet!");
}
} else {
return DeviceAuthResult.of("Credentials Type mismatch!");
}
} else {
log.trace("Credentials not found!");
return DeviceAuthResult.of("Credentials Not Found!");
}
}
```
### 2.3 支持的认证类型
ThingsBoard 支持以下设备认证类型:
1. **ACCESS_TOKEN**: Access Token 认证(最常用)
- 设备使用预配置的 Access Token 进行认证
- 凭证ID 直接匹配 Access Token
2. **X509_CERTIFICATE**: X509 证书认证
- 使用 TLS/SSL 证书进行认证
- 需要配置证书和私钥
3. **LWM2M_CREDENTIALS**: LWM2M 凭证认证
- 用于 LWM2M 协议设备
- 支持多种凭证类型PSK、RPK、X509
4. **MQTT_BASIC**: MQTT Basic 认证(已废弃)
### 2.4 传输层认证集成
不同传输协议集成认证的方式:
#### MQTT 传输
**位置**: `common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java`
MQTT 认证流程:
1. 设备连接时提供客户端ID和用户名/密码
2. 传输层调用认证服务验证凭证
3. 认证成功后建立会话
#### HTTP 传输
**位置**: `common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java`
HTTP 认证流程:
1. 设备在请求头或URL参数中提供 Access Token
2. 传输层验证 Token
3. 认证成功后处理请求
#### CoAP 传输
**位置**: `common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java`
CoAP 认证流程:
1. 设备在 CoAP 请求中提供凭证
2. 传输层验证凭证
3. 认证成功后建立会话
## 3. 会话管理
### 3.1 会话信息
**位置**: `common/proto/src/main/proto/transport.proto`
会话信息通过 `SessionInfoProto` 定义:
```protobuf
message SessionInfoProto {
int64 nodeIdMSB = 1;
int64 nodeIdLSB = 2;
int64 sessionIdMSB = 3;
int64 sessionIdLSB = 4;
int64 deviceIdMSB = 5;
int64 deviceIdLSB = 6;
string deviceName = 7;
string deviceType = 8;
int64 deviceProfileIdMSB = 9;
int64 deviceProfileIdLSB = 10;
int64 tenantIdMSB = 11;
int64 tenantIdLSB = 12;
int64 customerIdMSB = 13;
int64 customerIdLSB = 14;
SessionType sessionType = 15;
// ...
}
```
### 3.2 会话类型
ThingsBoard 支持两种会话类型:
1. **SYNC**: 同步会话
- 设备需要等待响应
- 用于请求-响应模式
2. **ASYNC**: 异步会话
- 设备不需要等待响应
- 用于遥测数据上报等场景
### 3.3 会话生命周期
#### 3.3.1 会话创建
**位置**: `common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java`
```java
/**
* 注册会话
*/
public void registerSession(SessionInfoProto sessionInfo, SessionMsgListener listener) {
// 1. 创建会话上下文
SessionContext sessionCtx = new SessionContext(sessionInfo, listener);
// 2. 注册会话
sessions.put(sessionId, sessionCtx);
// 3. 发送会话打开事件
sendToCore(tenantId, deviceId,
ToCoreMsg.newBuilder()
.setDeviceConnectMsg(DeviceConnectProto.newBuilder()
.setSessionInfo(sessionInfo)
.build())
.build(),
routingKey, null);
}
```
#### 3.3.2 会话管理
**位置**: `application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java`
设备 Actor 管理设备的所有会话:
```java
/**
* 处理传输层消息
* 更新会话信息
*/
public void process(TransportToDeviceActorMsgWrapper wrapper) {
TransportToDeviceActorMsg msg = wrapper.getMsg();
SessionInfoProto sessionInfo = msg.getSessionInfo();
UUID sessionId = new UUID(sessionInfo.getSessionIdMSB(),
sessionInfo.getSessionIdLSB());
// 更新会话活动时间
updateSessionActivity(sessionId, sessionInfo);
// 处理消息
processMessage(msg);
}
```
#### 3.3.3 会话超时
**位置**: `application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java`
```java
/**
* 检查会话超时
*/
public void checkSessionsTimeout() {
long currentTime = System.currentTimeMillis();
List<UUID> expiredSessions = new ArrayList<>();
for (Map.Entry<UUID, SessionInfo> entry : sessions.entrySet()) {
SessionInfo sessionInfo = entry.getValue();
long timeout = sessionInfo.getTimeout();
if (currentTime - sessionInfo.getLastActivityTime() > timeout) {
expiredSessions.add(entry.getKey());
}
}
// 关闭超时会话
for (UUID sessionId : expiredSessions) {
closeSession(sessionId);
}
}
```
#### 3.3.4 会话关闭
```java
/**
* 关闭会话
*/
public void closeSession(UUID sessionId) {
SessionInfo sessionInfo = sessions.remove(sessionId);
if (sessionInfo != null) {
// 发送设备断开消息
sendToCore(tenantId, deviceId,
ToCoreMsg.newBuilder()
.setDeviceDisconnectMsg(DeviceDisconnectProto.newBuilder()
.setSessionInfo(sessionInfo.getSessionInfo())
.build())
.build(),
routingKey, null);
}
}
```
## 4. 设备状态管理
### 4.1 设备连接状态
**位置**: `application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java`
设备状态服务跟踪设备的连接状态:
```java
/**
* 处理设备连接事件
*/
public void onDeviceConnect(TenantId tenantId, DeviceId deviceId,
SessionInfoProto sessionInfo) {
// 更新设备连接状态
save(tenantId, deviceId, "active", true);
save(tenantId, deviceId, "lastConnectTime", System.currentTimeMillis());
}
```
### 4.2 设备活动跟踪
设备活动包括:
- 连接/断开事件
- 遥测数据上报
- 属性更新
- RPC 调用
## 5. 安全机制
### 5.1 凭证存储
设备凭证存储在数据库中,支持加密存储:
**位置**: `dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsDao.java`
### 5.2 访问控制
- 设备只能访问自己的数据
- 租户隔离:不同租户的设备完全隔离
- 权限验证:所有操作都需要验证权限
### 5.3 速率限制
**位置**: `common/transport/src/main/java/org/thingsboard/server/common/transport/limits/TransportRateLimitService.java`
传输层支持速率限制:
- 每个设备的消息速率限制
- 每个租户的消息速率限制
- 防止恶意设备攻击
## 6. 网关设备认证
### 6.1 网关概念
网关设备可以代表多个子设备进行通信。
### 6.2 网关认证流程
1. 网关设备使用自己的凭证认证
2. 认证成功后,网关可以创建子设备会话
3. 子设备使用网关凭证 + 设备名称进行认证
**位置**: `common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java`
```java
/**
* 处理网关设备认证
*/
protected void processGatewayConnect(String deviceName, MqttConnectMessage msg) {
// 1. 验证网关凭证
ValidateDeviceCredentialsResponse response = validateGatewayCredentials(msg);
if (response.hasDeviceInfo()) {
// 2. 获取或创建子设备
GetOrCreateDeviceFromGatewayResponse deviceResponse =
getOrCreateDevice(deviceName, response.getDeviceInfo());
if (deviceResponse.hasDeviceInfo()) {
// 3. 创建子设备会话
establishDeviceSession(deviceResponse.getDeviceInfo());
}
}
}
```
## 7. 总结
ThingsBoard 的设备认证和会话管理系统具有以下特点:
1. **多种认证方式**: 支持 Access Token、X509 证书、LWM2M 凭证等
2. **会话管理**: 完善的会话生命周期管理,支持同步和异步会话
3. **状态跟踪**: 跟踪设备连接状态和活动情况
4. **安全机制**: 凭证加密存储、访问控制、速率限制
5. **网关支持**: 支持网关设备代表子设备进行通信
这套机制确保了设备连接的安全性和可靠性,同时支持大规模的设备连接。