SRS 4.0 HTTP回调实战:SpringBoot 5个接口实现推拉流鉴权与日志记录
SRS 4.0 HTTP回调实战:SpringBoot 5个接口实现推拉流鉴权与日志记录
流媒体服务在现代互联网应用中扮演着越来越重要的角色,而SRS(Simple Realtime Server)作为一款高性能的开源流媒体服务器,凭借其轻量级、高并发的特性,已经成为众多开发者的首选。本文将深入探讨如何利用SRS 4.0的HTTP回调机制,结合SpringBoot后端实现一个完整的流媒体业务系统,涵盖推流/拉流鉴权、用户行为日志记录等核心功能。
1. SRS HTTP回调机制解析
HTTP回调是SRS提供的一种灵活的事件通知机制,它允许开发者在特定事件发生时(如客户端连接、推流、拉流等),通过HTTP请求将相关数据发送到开发者自定义的服务端接口。这种机制为业务逻辑的扩展提供了极大的便利。
SRS 4.0支持的主要回调事件包括:
- on_connect :客户端连接到指定vhost和app时触发
- on_publish :客户端开始推流时触发
- on_play :客户端开始拉流播放时触发
- on_stop :客户端停止播放时触发
- on_close :客户端断开连接时触发
每个回调事件都会携带丰富的上下文信息,例如:
{
"action": "on_publish",
"client_id": "1985",
"ip": "192.168.1.10",
"vhost": "video.test.com",
"app": "live",
"stream": "livestream",
"param": "?token=xxx&salt=yyy"
}
2. SpringBoot项目架构设计
为了实现一个完整的流媒体业务系统,我们需要设计合理的项目结构。以下是推荐的SpringBoot项目模块划分:
src/main/java
├── com.example.live
│ ├── config # 配置类
│ ├── constant # 常量定义
│ ├── controller # 控制器
│ ├── callbackbean # 回调数据结构
│ ├── service # 业务服务
│ └── utils # 工具类
src/main/resources
├── static # 静态资源
└── templates # 模板文件
2.1 核心依赖配置
在pom.xml中需要添加以下关键依赖:
<dependencies>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JWT支持 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>
<!-- 日志记录 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependencies>
3. JWT鉴权方案实现
在流媒体系统中,安全认证是必不可少的环节。我们采用JWT(JSON Web Token)作为鉴权方案,它具有无状态、易扩展的特点,非常适合分布式系统。
3.1 Token工具类实现
public class TokenUtils {
private static final long EXPIRE_TIME = 60 * 60 * 1000; // 1小时有效
private static final String SECRET = "your-secret-key"; // 加密密钥
/**
* 生成签名
*/
public static String sign(String username) {
Date expireDate = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(SECRET);
return JWT.create()
.withIssuer("srs-auth") // 签发者
.withClaim("username", username) // 自定义声明
.withExpiresAt(expireDate) // 过期时间
.sign(algorithm);
}
/**
* 验证Token
*/
public static boolean verify(String token, String username) {
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.build();
verifier.verify(token);
return true;
} catch (Exception e) {
return false;
}
}
}
3.2 推流URL生成
推流URL需要包含Token参数,供后续鉴权使用:
@Service
public class StreamServiceImpl implements StreamService {
@Override
public String generateURL(String username) {
String token = TokenUtils.sign(username);
String stream = UUID.randomUUID().toString();
return "rtmp://your-srs-server/live/" + stream + "?token=" + token;
}
}
4. 核心回调接口实现
4.1 连接回调(on_connect)
@PostMapping("/connect")
public int onConnect(@RequestBody CallBackDataOnConnect data) {
// 验证app名称是否正确
if(!"live".equals(data.getApp())) {
log.warn("Invalid app name: {}", data.getApp());
return 1; // 拒绝连接
}
log.info("Client connected - IP: {}, Vhost: {}, App: {}",
data.getIp(), data.getVhost(), data.getApp());
return 0; // 允许连接
}
4.2 推流回调(on_publish)
@PostMapping("/publish")
public int onPublish(@RequestBody CallBackDataOnPublish data) {
// 1. 验证app名称
if(!"live".equals(data.getApp())) {
log.warn("Publish rejected - invalid app: {}", data.getApp());
return 1;
}
// 2. 提取并验证Token
String token = extractToken(data.getParam());
if(token == null || !TokenUtils.verify(token, "expected-username")) {
log.warn("Publish rejected - invalid token");
return 1;
}
log.info("Stream published - Stream: {}, Client: {}",
data.getStream(), data.getIp());
return 0;
}
private String extractToken(String param) {
if(param == null || !param.startsWith("?token=")) {
return null;
}
return param.substring(7); // 截取?token=后面的部分
}
4.3 播放回调(on_play)
@PostMapping("/play")
public int onPlay(@RequestBody CallBackDataOnPlay data) {
// 1. 基础验证
if(!"live".equals(data.getApp())) {
log.warn("Play rejected - invalid app: {}", data.getApp());
return 1;
}
// 2. Token验证
String token = extractToken(data.getParam());
if(token == null || !TokenUtils.verify(token, "expected-username")) {
log.warn("Play rejected - invalid token");
return 1;
}
// 3. 记录播放行为
log.info("Stream playing - Stream: {}, Client: {}, Page: {}",
data.getStream(), data.getIp(), data.getPageUrl());
return 0;
}
4.4 停止播放回调(on_stop)
@PostMapping("/stop")
public int onStop(@RequestBody String rawData) {
// 解析JSON数据
CallBackDataOnStop data = parseStopData(rawData);
log.info("Play stopped - Stream: {}, Duration: {}",
data.getStream(), data.getDuration());
return 0;
}
4.5 断开连接回调(on_close)
@PostMapping("/close")
public int onClose(@RequestBody CallBackDataOnClose data) {
log.info("Client disconnected - IP: {}, Bytes sent: {}, Bytes received: {}",
data.getIp(), data.getSendBytes(), data.getRecvBytes());
return 0;
}
5. SRS服务配置
要让SRS能够正确调用我们的SpringBoot接口,需要在SRS配置文件中进行相应设置:
vhost __defaultVhost__ {
http_hooks {
enabled on;
on_connect http://your-springboot-server:8080/connect;
on_close http://your-springboot-server:8080/close;
on_publish http://your-springboot-server:8080/publish;
on_unpublish http://your-springboot-server:8080/unpublish;
on_play http://your-springboot-server:8080/play;
on_stop http://your-springboot-server:8080/stop;
}
}
6. 日志记录与监控
完善的日志系统对于流媒体服务至关重要。我们采用Log4j2进行日志记录,并设计了以下日志规范:
- 访问日志 :记录所有客户端连接、断开事件
- 推流日志 :记录推流开始、结束事件及推流质量
- 播放日志 :记录播放开始、结束事件及播放质量
- 异常日志 :记录所有鉴权失败、异常情况
日志配置示例(log4j2.xml):
<Configuration>
<Appenders>
<RollingFile name="FileAppender" fileName="logs/app.log"
filePattern="logs/app-%d{yyyy-MM-dd}.log.gz">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="com.example.live.controller" level="info" additivity="false">
<AppenderRef ref="FileAppender"/>
</Logger>
<Root level="error">
<AppenderRef ref="FileAppender"/>
</Root>
</Loggers>
</Configuration>
7. 性能优化与安全建议
在实际部署时,还需要考虑以下优化和安全措施:
-
接口性能优化 :
- 使用缓存减少数据库查询
- 异步处理非关键日志记录
- 合理设置HTTP超时时间
-
安全加固 :
- 启用HTTPS加密通信
- 实现IP白名单机制
- 定期轮换JWT密钥
-
高可用设计 :
- 部署多个SRS边缘节点
- 实现回调服务的负载均衡
- 建立完善的监控告警系统
通过以上实现,我们构建了一个完整的流媒体业务系统,具备完善的鉴权机制和操作日志记录功能。这套方案已经在多个实际项目中得到验证,能够稳定支持高并发的流媒体服务需求。
更多推荐

所有评论(0)