Browse Source

添加日志存储与查询功能

登录接口返回用户详细信息
pull/151/head
648540858 3 years ago
parent
commit
61f5950b4f
  1. 14
      sql/mysql.sql
  2. 2
      src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
  3. 172
      src/main/java/com/genersoft/iot/vmp/common/ApiSaveConstant.java
  4. 114
      src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java
  5. 10
      src/main/java/com/genersoft/iot/vmp/conf/UserSetup.java
  6. 2
      src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java
  7. 34
      src/main/java/com/genersoft/iot/vmp/service/ILogService.java
  8. 36
      src/main/java/com/genersoft/iot/vmp/service/impl/LogServiceImpl.java
  9. 6
      src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
  10. 39
      src/main/java/com/genersoft/iot/vmp/storager/dao/LogMapper.java
  11. 86
      src/main/java/com/genersoft/iot/vmp/storager/dao/dto/LogDto.java
  12. 93
      src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java
  13. 18
      src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
  14. 2
      src/main/resources/all-application.yml
  15. BIN
      src/main/resources/wvp.sqlite

14
sql/mysql.sql

@ -74,7 +74,19 @@ create table device_alarm
alarmType varchar(50) alarmType varchar(50)
); );
create table log
(
id int auto_increment
primary key,
name varchar(50) not null,
type varchar(50) not null,
uri varchar(200) not null,
address varchar(50) not null,
result varchar(50) not null,
timing bigint not null,
username varchar(50) not null,
createTime varchar(50) not null
);
create table device_mobile_position create table device_mobile_position
( (

2
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java

@ -4,6 +4,7 @@ import java.util.logging.LogManager;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import springfox.documentation.oas.annotations.EnableOpenApi; import springfox.documentation.oas.annotations.EnableOpenApi;
@ -11,6 +12,7 @@ import springfox.documentation.oas.annotations.EnableOpenApi;
/** /**
* *
*/ */
@ServletComponentScan("com.genersoft.iot.vmp.conf")
@SpringBootApplication @SpringBootApplication
@EnableScheduling @EnableScheduling
@EnableOpenApi @EnableOpenApi

172
src/main/java/com/genersoft/iot/vmp/common/ApiSaveConstant.java

@ -0,0 +1,172 @@
package com.genersoft.iot.vmp.common;
public class ApiSaveConstant {
public static String getVal(String key) {
String[] keyItemArray = key.split("/");
if (keyItemArray.length <= 1 || !"api".equals(keyItemArray[1])) {
return null;
}
if (keyItemArray.length >= 4) {
switch (keyItemArray[2]) {
case "alarm":
if ("delete".equals(keyItemArray[3])) {
return "删除报警";
}
break;
case "device":
switch (keyItemArray[3]) {
case "config":
if (keyItemArray.length >= 5 && "basicParam".equals(keyItemArray[4])) {
return "[设备配置] 基本配置设置命令";
}
break;
case "control":
switch (keyItemArray[4]) {
case "teleboot":
return "[设备控制] 远程启动";
case "record":
return "[设备控制] 录像控制";
case "guard":
return "[设备控制] 布防/撤防命令";
case "reset_alarm":
return "[设备控制] 报警复位";
case "i_frame":
return "[设备控制] 强制关键帧";
case "home_position":
return "[设备控制] 看守位控制";
}
break;
case "query":
if (keyItemArray.length <= 5) return null;
switch (keyItemArray[4]) {
case "devices":
if (keyItemArray.length < 7) return null;
switch (keyItemArray[6]) {
case "sync":
return "[设备查询] 同步设备通道";
case "delete":
return "[设备查询] 移除设备";
}
break;
case "channel":
return "[设备查询] 更新通道信息";
case "transport":
return "[设备查询] 修改数据流传输模式";
}
break;
}
case "gbStream":
switch (keyItemArray[3]) {
case "del":
return "移除通道与国标的关联";
case "add":
return "添加通道与国标的关联";
}
break;
case "media":
break;
case "position":
if ("subscribe".equals(keyItemArray[3])) {
return "订阅位置信息";
}
break;
case "platform":
switch (keyItemArray[3]) {
case "save":
return "添加上级平台";
case "delete":
return "移除上级平台";
case "update_channel_for_gb":
return "向上级平台添加国标通道";
case "del_channel_for_gb":
return "从上级平台移除国标通道";
}
break;
case "platform_gb_stream":
break;
case "play":
switch (keyItemArray[3]) {
case "start":
return "开始点播";
case "stop":
return "停止点播";
case "convert":
return "转码";
case "convertStop":
return "结束转码";
case "broadcast":
return "语音广播";
}
break;
case "download":
switch (keyItemArray[3]) {
case "start":
return "开始历史媒体下载";
case "stop":
return "停止历史媒体下载";
}
break;
case "playback":
switch (keyItemArray[3]) {
case "start":
return "开始视频回放";
case "stop":
return "停止视频回放";
}
break;
case "ptz":
switch (keyItemArray[3]) {
case "control":
return "云台控制";
case "front_end_command":
return "通用前端控制命令";
}
break;
case "gb_record":
break;
case "onvif":
break;
case "server":
if ("restart".equals(keyItemArray[3])) {
return "重启流媒体服务";
}
break;
case "proxy":
switch (keyItemArray[3]) {
case "save":
return "保存代理";
case "del":
return "移除代理";
case "start":
return "启用代理";
case "stop":
return "停用代理";
}
break;
case "push":
switch (keyItemArray[3]) {
case "save_to_gb":
return "将推流添加到国标";
case "remove_form_gb":
return "将推流移出到国标";
}
break;
case "user":
switch (keyItemArray[3]) {
case "login":
return "登录";
case "changePassword":
return "修改密码";
case "add":
return "添加用户";
case "delete":
return "删除用户";
}
break;
}
}
return null;
}
}

114
src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java

@ -0,0 +1,114 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.common.ApiSaveConstant;
import com.genersoft.iot.vmp.conf.security.SecurityUtils;
import com.genersoft.iot.vmp.service.ILogService;
import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
@WebFilter(filterName = "ApiAccessFilter", urlPatterns = "/api/*", asyncSupported=true)
public class ApiAccessFilter extends OncePerRequestFilter {
private final static Logger logger = LoggerFactory.getLogger(ApiAccessFilter.class);
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Autowired
private UserSetup userSetup;
@Autowired
private ILogService logService;
@Override
protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
String username = null;
if (SecurityUtils.getUserInfo() == null) {
username = servletRequest.getParameter("username");
}else {
username = SecurityUtils.getUserInfo().getUsername();
}
long start = System.currentTimeMillis(); // 请求进入时间
String uriName = ApiSaveConstant.getVal(servletRequest.getRequestURI());
filterChain.doFilter(servletRequest, servletResponse);
if (uriName != null && userSetup.getLogInDatebase()) {
LogDto logDto = new LogDto();
logDto.setName(uriName);
logDto.setUsername(username);
logDto.setAddress(servletRequest.getRemoteAddr());
logDto.setResult(HttpStatus.valueOf(servletResponse.getStatus()).toString());
logDto.setTiming(System.currentTimeMillis() - start);
logDto.setType(servletRequest.getMethod());
logDto.setUri(servletRequest.getRequestURI());
logDto.setCreateTime(format.format(System.currentTimeMillis()));
logService.add(logDto);
// logger.warn("[Api Access] [{}] [{}] [{}] [{}] [{}] {}ms",
// uriName, servletRequest.getMethod(), servletRequest.getRequestURI(), servletRequest.getRemoteAddr(), HttpStatus.valueOf(servletResponse.getStatus()),
// System.currentTimeMillis() - start);
}
}
/**
* 获取IP地址
*
* @param request 请求
* @return request发起客户端的IP地址
*/
private String getIP(HttpServletRequest request) {
if (request == null) {
return "0.0.0.0";
}
String Xip = request.getHeader("X-Real-IP");
String XFor = request.getHeader("X-Forwarded-For");
String UNKNOWN_IP = "unknown";
if (StringUtils.isNotEmpty(XFor) && !UNKNOWN_IP.equalsIgnoreCase(XFor)) {
//多次反向代理后会有多个ip值,第一个ip才是真实ip
int index = XFor.indexOf(",");
if (index != -1) {
return XFor.substring(0, index);
} else {
return XFor;
}
}
XFor = Xip;
if (StringUtils.isNotEmpty(XFor) && !UNKNOWN_IP.equalsIgnoreCase(XFor)) {
return XFor;
}
if (StringUtils.isBlank(XFor) || UNKNOWN_IP.equalsIgnoreCase(XFor)) {
XFor = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || UNKNOWN_IP.equalsIgnoreCase(XFor)) {
XFor = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isBlank(XFor) || UNKNOWN_IP.equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isBlank(XFor) || UNKNOWN_IP.equalsIgnoreCase(XFor)) {
XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isBlank(XFor) || UNKNOWN_IP.equalsIgnoreCase(XFor)) {
XFor = request.getRemoteAddr();
}
return XFor;
}
}

10
src/main/java/com/genersoft/iot/vmp/conf/UserSetup.java

@ -25,6 +25,8 @@ public class UserSetup {
private Boolean recordPushLive = Boolean.FALSE; private Boolean recordPushLive = Boolean.FALSE;
private Boolean logInDatebase = Boolean.TRUE;
private List<String> interfaceAuthenticationExcludes = new ArrayList<>(); private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
public Boolean getSavePositionHistory() { public Boolean getSavePositionHistory() {
@ -94,4 +96,12 @@ public class UserSetup {
public void setInterfaceAuthenticationExcludes(List<String> interfaceAuthenticationExcludes) { public void setInterfaceAuthenticationExcludes(List<String> interfaceAuthenticationExcludes) {
this.interfaceAuthenticationExcludes = interfaceAuthenticationExcludes; this.interfaceAuthenticationExcludes = interfaceAuthenticationExcludes;
} }
public Boolean getLogInDatebase() {
return logInDatebase;
}
public void setLogInDatebase(Boolean logInDatebase) {
this.logInDatebase = logInDatebase;
}
} }

2
src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java

@ -48,7 +48,7 @@ public class SecurityUtils {
Authentication authentication = getAuthentication(); Authentication authentication = getAuthentication();
if(authentication!=null){ if(authentication!=null){
Object principal = authentication.getPrincipal(); Object principal = authentication.getPrincipal();
if(principal!=null){ if(principal!=null && !"anonymousUser".equals(principal)){
LoginUser user = (LoginUser) authentication.getPrincipal(); LoginUser user = (LoginUser) authentication.getPrincipal();
return user; return user;
} }

34
src/main/java/com/genersoft/iot/vmp/service/ILogService.java

@ -0,0 +1,34 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
import com.github.pagehelper.PageInfo;
/**
* 系统日志
*/
public interface ILogService {
/**
* 查询日志
* @param page 当前页
* @param count 每页数量
* @param query 搜索内容
* @param type 类型
* @param startTime 开始时间
* @param endTime 结束时间
* @return 日志列表
*/
PageInfo<LogDto> getAll(int page, int count, String query, String type, String startTime, String endTime);
/**
* 添加日志
* @param logDto 日志
*/
void add(LogDto logDto);
/**
* 清空
*/
int clear();
}

36
src/main/java/com/genersoft/iot/vmp/service/impl/LogServiceImpl.java

@ -0,0 +1,36 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.service.ILogService;
import com.genersoft.iot.vmp.storager.dao.LogMapper;
import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class LogServiceImpl implements ILogService {
@Autowired
private LogMapper logMapper;
@Override
public PageInfo<LogDto> getAll(int page, int count, String query, String type, String startTime, String endTime) {
PageHelper.startPage(page, count);
List<LogDto> all = logMapper.query(query, type, startTime, endTime);
return new PageInfo<>(all);
}
@Override
public void add(LogDto logDto) {
logMapper.add(logDto);
}
@Override
public int clear() {
return logMapper.clear();
}
}

6
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java

@ -342,12 +342,14 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) { if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
logger.info("获取负载最低的节点时无在线节点"); logger.info("获取负载最低的节点时无在线节点");
return null;
} }
// 获取分数最低的,及并发最低的 // 获取分数最低的,及并发最低的
Set<Object> objects = redisUtil.ZRange(key, 0, -1); Set<Object> objects = redisUtil.ZRange(key, 0, -1);
ArrayList<Object> MediaServerObjectS = new ArrayList<>(objects); ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects);
String mediaServerId = (String)MediaServerObjectS.get(0);
String mediaServerId = (String)mediaServerObjectS.get(0);
return getOne(mediaServerId); return getOne(mediaServerId);
} }

39
src/main/java/com/genersoft/iot/vmp/storager/dao/LogMapper.java

@ -0,0 +1,39 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 用于存储设服务的日志
*/
@Mapper
@Repository
public interface LogMapper {
@Insert("insert into log ( name, type, uri, address, result, timing, username, createTime) " +
"values ('${name}', '${type}', '${uri}', '${address}', '${result}', ${timing}, '${username}', '${createTime}')")
int add(LogDto logDto);
@Select(value = {"<script>" +
" SELECT * FROM log " +
" WHERE 1=1 " +
" <if test=\"query != null\"> AND (name LIKE '%${query}%')</if> " +
" <if test=\"type != null\" > AND type = '${type}'</if>" +
" <if test=\"startTime != null\" > AND createTime &gt;= '${startTime}' </if>" +
" <if test=\"endTime != null\" > AND createTime &lt;= '${endTime}' </if>" +
" ORDER BY createTime DESC " +
" </script>"})
List<LogDto> query(String query, String type, String startTime, String endTime);
@Delete("DELETE FROM log")
int clear();
}

86
src/main/java/com/genersoft/iot/vmp/storager/dao/dto/LogDto.java

@ -0,0 +1,86 @@
package com.genersoft.iot.vmp.storager.dao.dto;
public class LogDto {
private int id;
private String name;
private String type;
private String uri;
private String address;
private String result;
private long timing;
private String username;
private String createTime;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public long getTiming() {
return timing;
}
public void setTiming(long timing) {
this.timing = timing;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
}

93
src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java

@ -0,0 +1,93 @@
package com.genersoft.iot.vmp.vmanager.log;
import com.genersoft.iot.vmp.service.ILogService;
import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@Api(tags = "日志管理")
@CrossOrigin
@RestController
@RequestMapping("/api/log")
public class LogController {
@Autowired
private ILogService logService;
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 分页查询日志
*
* @param query 查询内容
* @param page 当前页
* @param count 每页查询数量
* @param type 类型
* @param startTime 开始时间
* @param endTime 结束时间
* @return
*/
@ApiOperation("分页查询报警")
@GetMapping("/all")
@ApiImplicitParams({
@ApiImplicitParam(name="query", value = "查询内容", dataTypeClass = String.class),
@ApiImplicitParam(name="page", value = "当前页", required = true ,dataTypeClass = Integer.class),
@ApiImplicitParam(name="count", value = "每页查询数量", required = true ,dataTypeClass = Integer.class),
@ApiImplicitParam(name="type", value = "类型" ,dataTypeClass = String.class),
@ApiImplicitParam(name="startTime", value = "查询内容" ,dataTypeClass = String.class),
@ApiImplicitParam(name="endTime", value = "查询内容" ,dataTypeClass = String.class),
})
public ResponseEntity<PageInfo<LogDto>> getAll(
@RequestParam int page,
@RequestParam int count,
@RequestParam(required = false) String query,
@RequestParam(required = false) String type,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime
) {
if (StringUtils.isEmpty(query)) query = null;
if (StringUtils.isEmpty(startTime)) startTime = null;
if (StringUtils.isEmpty(endTime)) endTime = null;
try {
if (startTime != null) format.parse(startTime);
if (endTime != null) format.parse(endTime);
} catch (ParseException e) {
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
PageInfo<LogDto> allLog = logService.getAll(page, count, query, type, startTime, endTime);
return new ResponseEntity<>(allLog, HttpStatus.OK);
}
/**
* 清空日志
*
*/
@ApiOperation("清空日志")
@DeleteMapping("/clear")
@ApiImplicitParams({})
public ResponseEntity<WVPResult<String>> clear() {
int count = logService.clear();
WVPResult wvpResult = new WVPResult();
wvpResult.setCode(0);
wvpResult.setMsg("success");
wvpResult.setData(count);
return new ResponseEntity<WVPResult<String>>(wvpResult, HttpStatus.OK);
}
}

18
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java

@ -17,9 +17,7 @@ import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.security.sasl.AuthenticationException; import javax.security.sasl.AuthenticationException;
import javax.xml.crypto.Data;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import java.util.List;
@Api(tags = "用户管理") @Api(tags = "用户管理")
@ -42,19 +40,25 @@ public class UserController {
@ApiImplicitParam(name = "password", required = true, value = "密码(32位md5加密)", dataTypeClass = String.class), @ApiImplicitParam(name = "password", required = true, value = "密码(32位md5加密)", dataTypeClass = String.class),
}) })
@GetMapping("/login") @GetMapping("/login")
public String login(@RequestParam String username, @RequestParam String password){ public WVPResult<LoginUser> login(@RequestParam String username, @RequestParam String password){
LoginUser user; LoginUser user = null;
WVPResult<LoginUser> result = new WVPResult<>();
try { try {
user = SecurityUtils.login(username, password, authenticationManager); user = SecurityUtils.login(username, password, authenticationManager);
} catch (AuthenticationException e) { } catch (AuthenticationException e) {
e.printStackTrace(); e.printStackTrace();
return "fail"; result.setCode(-1);
result.setMsg("fail");
} }
if (user != null) { if (user != null) {
return "success"; result.setCode(0);
result.setMsg("success");
result.setData(user);
}else { }else {
return "fail"; result.setCode(-1);
result.setMsg("fail");
} }
return result;
} }
@ApiOperation("修改密码") @ApiOperation("修改密码")

2
src/main/resources/all-application.yml

@ -150,6 +150,8 @@ user-settings:
- /api/v1/** - /api/v1/**
# 推流直播是否录制 # 推流直播是否录制
record-push-live: true record-push-live: true
# 是否将日志存储进数据库
logInDatebase: true
# 在线文档: swagger-ui(生产环境建议关闭) # 在线文档: swagger-ui(生产环境建议关闭)
swagger-ui: swagger-ui:

BIN
src/main/resources/wvp.sqlite

Binary file not shown.
Loading…
Cancel
Save