添加日志存储与查询功能

登录接口返回用户详细信息
pull/151/head
648540858 2021-08-07 14:05:42 +08:00
parent 94ef0d856f
commit 61f5950b4f
15 changed files with 617 additions and 11 deletions

View File

@ -74,7 +74,19 @@ create table device_alarm
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
(

View File

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

View File

@ -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;
}
}

View File

@ -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 requestIP
*/
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;
}
}

View File

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

View File

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

View File

@ -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();
}

View File

@ -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();
}
}

View File

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

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

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

View File

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

Binary file not shown.