支持彻底关闭文档页面 + 修复云端录像偶现callId错误问题
parent
d70bfb53dd
commit
2daa59d78c
|
@ -7,6 +7,7 @@ import io.swagger.v3.oas.models.info.Contact;
|
||||||
import io.swagger.v3.oas.models.info.Info;
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
import io.swagger.v3.oas.models.info.License;
|
import io.swagger.v3.oas.models.info.License;
|
||||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springdoc.core.GroupedOpenApi;
|
import org.springdoc.core.GroupedOpenApi;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
@ -18,6 +19,7 @@ import org.springframework.context.annotation.Configuration;
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@Order(1)
|
@Order(1)
|
||||||
|
@ConditionalOnProperty(value = "user-settings.doc-enable", havingValue = "true", matchIfMissing = true)
|
||||||
public class SpringDocConfig {
|
public class SpringDocConfig {
|
||||||
|
|
||||||
@Value("${doc.enabled: true}")
|
@Value("${doc.enabled: true}")
|
||||||
|
|
|
@ -54,6 +54,8 @@ public class UserSetting {
|
||||||
private Boolean deviceStatusNotify = Boolean.TRUE;
|
private Boolean deviceStatusNotify = Boolean.TRUE;
|
||||||
private Boolean useCustomSsrcForParentInvite = Boolean.TRUE;
|
private Boolean useCustomSsrcForParentInvite = Boolean.TRUE;
|
||||||
|
|
||||||
|
private Boolean docEnable = Boolean.TRUE;
|
||||||
|
|
||||||
private String serverId = "000000";
|
private String serverId = "000000";
|
||||||
|
|
||||||
private String thirdPartyGBIdReg = "[\\s\\S]*";
|
private String thirdPartyGBIdReg = "[\\s\\S]*";
|
||||||
|
@ -315,4 +317,12 @@ public class UserSetting {
|
||||||
public void setRegisterKeepIntDialog(boolean registerKeepIntDialog) {
|
public void setRegisterKeepIntDialog(boolean registerKeepIntDialog) {
|
||||||
this.registerKeepIntDialog = registerKeepIntDialog;
|
this.registerKeepIntDialog = registerKeepIntDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getDocEnable() {
|
||||||
|
return docEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDocEnable(Boolean docEnable) {
|
||||||
|
this.docEnable = docEnable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,16 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
// 忽略登录请求的token验证
|
// 忽略登录请求的token验证
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
|
System.out.println(requestURI);
|
||||||
|
if ((requestURI.startsWith("/doc.html") || requestURI.startsWith("/swagger-ui") ) && !userSetting.getDocEnable()) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (requestURI.equalsIgnoreCase("/api/user/login")) {
|
if (requestURI.equalsIgnoreCase("/api/user/login")) {
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!userSetting.isInterfaceAuthentication()) {
|
if (!userSetting.isInterfaceAuthentication()) {
|
||||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
|
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
|
||||||
SecurityContextHolder.getContext().setAuthentication(token);
|
SecurityContextHolder.getContext().setAuthentication(token);
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
|
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
|
||||||
.antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
|
.antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
|
||||||
.antMatchers("/api/user/login", "/index/hook/**", "/swagger-ui/**", "/doc.html").permitAll()
|
.antMatchers("/api/user/login", "/index/hook/**", "/swagger-ui/**", "/doc.html#/**").permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
// 异常处理器
|
// 异常处理器
|
||||||
.and()
|
.and()
|
||||||
|
|
|
@ -29,6 +29,7 @@ import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||||
|
import com.genersoft.iot.vmp.utils.MediaServerUtils;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo;
|
import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo;
|
import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo;
|
||||||
|
@ -47,7 +48,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.sip.InvalidArgumentException;
|
import javax.sip.InvalidArgumentException;
|
||||||
import javax.sip.SipException;
|
import javax.sip.SipException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -179,7 +179,7 @@ public class ZLMHttpHookListener {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!"rtp".equals(param.getApp())) {
|
if (!"rtp".equals(param.getApp())) {
|
||||||
Map<String, String> paramMap = urlParamToMap(param.getParams());
|
Map<String, String> paramMap = MediaServerUtils.urlParamToMap(param.getParams());
|
||||||
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
|
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
|
||||||
if (streamAuthorityInfo != null && streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId"))) {
|
if (streamAuthorityInfo != null && streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId"))) {
|
||||||
return new HookResult(401, "Unauthorized");
|
return new HookResult(401, "Unauthorized");
|
||||||
|
@ -220,7 +220,7 @@ public class ZLMHttpHookListener {
|
||||||
logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)");
|
logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)");
|
||||||
return new HookResultForOnPublish(401, "Unauthorized");
|
return new HookResultForOnPublish(401, "Unauthorized");
|
||||||
}
|
}
|
||||||
Map<String, String> paramMap = urlParamToMap(param.getParams());
|
Map<String, String> paramMap = MediaServerUtils.urlParamToMap(param.getParams());
|
||||||
String sign = paramMap.get("sign");
|
String sign = paramMap.get("sign");
|
||||||
if (sign == null) {
|
if (sign == null) {
|
||||||
logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)");
|
logger.info("推流鉴权失败: 缺少必要参数:sign=md5(user表的pushKey)");
|
||||||
|
@ -899,22 +899,4 @@ public class ZLMHttpHookListener {
|
||||||
|
|
||||||
return HookResult.SUCCESS();
|
return HookResult.SUCCESS();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> urlParamToMap(String params) {
|
|
||||||
HashMap<String, String> map = new HashMap<>();
|
|
||||||
if (ObjectUtils.isEmpty(params)) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
String[] paramsArray = params.split("&");
|
|
||||||
if (paramsArray.length == 0) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
for (String param : paramsArray) {
|
|
||||||
String[] paramArray = param.split("=");
|
|
||||||
if (paramArray.length == 2) {
|
|
||||||
map.put(paramArray[0], paramArray[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ public class OnRecordMp4HookParam extends HookParam{
|
||||||
private String vhost;
|
private String vhost;
|
||||||
private long start_time;
|
private long start_time;
|
||||||
private double time_len;
|
private double time_len;
|
||||||
|
private String params;
|
||||||
|
|
||||||
public String getApp() {
|
public String getApp() {
|
||||||
return app;
|
return app;
|
||||||
|
@ -96,6 +97,14 @@ public class OnRecordMp4HookParam extends HookParam{
|
||||||
this.time_len = time_len;
|
this.time_len = time_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getParams() {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(String params) {
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "OnRecordMp4HookParam{" +
|
return "OnRecordMp4HookParam{" +
|
||||||
|
@ -109,6 +118,7 @@ public class OnRecordMp4HookParam extends HookParam{
|
||||||
", vhost='" + vhost + '\'' +
|
", vhost='" + vhost + '\'' +
|
||||||
", start_time=" + start_time +
|
", start_time=" + start_time +
|
||||||
", time_len=" + time_len +
|
", time_len=" + time_len +
|
||||||
|
", params=" + params +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package com.genersoft.iot.vmp.service.bean;
|
package com.genersoft.iot.vmp.service.bean;
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||||
|
import com.genersoft.iot.vmp.utils.MediaServerUtils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 云端录像数据
|
* 云端录像数据
|
||||||
|
@ -88,6 +91,10 @@ public class CloudRecordItem {
|
||||||
cloudRecordItem.setMediaServerId(param.getMediaServerId());
|
cloudRecordItem.setMediaServerId(param.getMediaServerId());
|
||||||
cloudRecordItem.setTimeLen((long) param.getTime_len() * 1000);
|
cloudRecordItem.setTimeLen((long) param.getTime_len() * 1000);
|
||||||
cloudRecordItem.setEndTime((param.getStart_time() + (long)param.getTime_len()) * 1000);
|
cloudRecordItem.setEndTime((param.getStart_time() + (long)param.getTime_len()) * 1000);
|
||||||
|
Map<String, String> paramsMap = MediaServerUtils.urlParamToMap(param.getParams());
|
||||||
|
if (paramsMap.get("callId") != null) {
|
||||||
|
cloudRecordItem.setCallId(paramsMap.get("callId"));
|
||||||
|
}
|
||||||
return cloudRecordItem;
|
return cloudRecordItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
|
|
||||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||||
import com.genersoft.iot.vmp.service.ICloudRecordService;
|
import com.genersoft.iot.vmp.service.ICloudRecordService;
|
||||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||||
|
@ -26,8 +25,12 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.*;
|
import java.time.LocalDate;
|
||||||
import java.util.*;
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@DS("share")
|
@DS("share")
|
||||||
|
@ -102,11 +105,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
|
||||||
@Override
|
@Override
|
||||||
public void addRecord(OnRecordMp4HookParam param) {
|
public void addRecord(OnRecordMp4HookParam param) {
|
||||||
CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(param);
|
CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(param);
|
||||||
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
|
logger.info("[添加录像记录] {}/{}, callId: {}, 文件大小:{}, 时长: {}秒", param.getApp(), param.getStream(),cloudRecordItem.getCallId(), param.getFile_size(),param.getTime_len());
|
||||||
if (streamAuthorityInfo != null) {
|
|
||||||
cloudRecordItem.setCallId(streamAuthorityInfo.getCallId());
|
|
||||||
}
|
|
||||||
logger.info("[添加录像记录] {}/{} 文件大小:{}, 时长: {}秒", param.getApp(), param.getStream(), param.getFile_size(),param.getTime_len());
|
|
||||||
cloudRecordServiceMapper.add(cloudRecordItem);
|
cloudRecordServiceMapper.add(cloudRecordItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.genersoft.iot.vmp.utils;
|
||||||
|
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MediaServerUtils {
|
||||||
|
public static Map<String, String> urlParamToMap(String params) {
|
||||||
|
HashMap<String, String> map = new HashMap<>();
|
||||||
|
if (ObjectUtils.isEmpty(params)) {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
String[] paramsArray = params.split("&");
|
||||||
|
if (paramsArray.length == 0) {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
for (String param : paramsArray) {
|
||||||
|
String[] paramArray = param.split("=");
|
||||||
|
if (paramArray.length == 2) {
|
||||||
|
map.put(paramArray[0], paramArray[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -241,6 +241,8 @@ user-settings:
|
||||||
register-again-after-time: 60
|
register-again-after-time: 60
|
||||||
# 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
|
# 国标续订方式,true为续订,每次注册在同一个会话里,false为重新注册,每次使用新的会话
|
||||||
register-keep-int-dialog: false
|
register-keep-int-dialog: false
|
||||||
|
# 开启接口文档页面。 默认开启,生产环境建议关闭,遇到swagger相关的漏洞时也可以关闭
|
||||||
|
doc-enable: true
|
||||||
# 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
|
# 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
|
||||||
allowed-origins:
|
allowed-origins:
|
||||||
- http://localhost:8008
|
- http://localhost:8008
|
||||||
|
|
|
@ -110,7 +110,4 @@ user-settings:
|
||||||
auto-apply-play: true
|
auto-apply-play: true
|
||||||
# 设备/通道状态变化时发送消息
|
# 设备/通道状态变化时发送消息
|
||||||
device-status-notify: true
|
device-status-notify: true
|
||||||
# [可选] 日志配置, 一般不需要改
|
|
||||||
logging:
|
|
||||||
config: classpath:logback-spring.xml
|
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,7 @@ create table wvp_media_server (
|
||||||
hook_alive_interval integer,
|
hook_alive_interval integer,
|
||||||
record_path character varying(255),
|
record_path character varying(255),
|
||||||
record_day integer default 7,
|
record_day integer default 7,
|
||||||
|
transcode_suffix character varying(255),
|
||||||
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
|
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,7 @@ create table wvp_media_server (
|
||||||
hook_alive_interval integer,
|
hook_alive_interval integer,
|
||||||
record_path character varying(255),
|
record_path character varying(255),
|
||||||
record_day integer default 7,
|
record_day integer default 7,
|
||||||
|
transcode_suffix character varying(255),
|
||||||
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
|
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue