package com.inspect.nvr.service;
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.github.benmanes.caffeine.cache.Cache;
|
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
|
import com.github.benmanes.caffeine.cache.RemovalCause;
|
|
import com.inspect.nvr.daHuaCarme.jna.NetSDKLib;
|
|
import com.inspect.nvr.daHuaCarme.jna.NetSDKLib.LLong;
|
|
import com.inspect.nvr.domain.Infrared.NvrInfo;
|
|
import com.inspect.nvr.utils.redis.RedisService;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import javax.annotation.Resource;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
/**
|
|
* 大华登录服务
|
|
*/
|
|
@Slf4j
|
|
@Service
|
|
public class DahuaLoginService {
|
|
private static final String ERROR_LOGOUT_KEY = "dahua:error";
|
|
|
|
@Autowired
|
|
private NetSDKLib dhNetSDK;
|
|
@Resource
|
|
private RedisService redisService;
|
|
|
|
// 使用 Caffeine 缓存,10分钟未访问自动移除并登出
|
|
private final Cache<String, LLong> sessionCache = Caffeine.newBuilder()
|
|
// 10分钟未被get()就过期
|
|
.expireAfterAccess(10, TimeUnit.MINUTES)
|
|
.removalListener((String ip, LLong loginID, RemovalCause cause) -> {
|
|
if (loginID != null && (cause == RemovalCause.EXPIRED || cause == RemovalCause.SIZE)) {
|
|
log.info("[大华]会话超时自动登出,ip: {},loginID: {}", ip, loginID);
|
|
doLogout(ip, loginID);
|
|
}
|
|
}).build();
|
|
|
|
public synchronized LLong login(NvrInfo nvrInfo) {
|
|
String ip = nvrInfo.getNvrIp();
|
|
LLong existLoginID = sessionCache.getIfPresent(ip);
|
|
if (existLoginID != null) {
|
|
log.info("[大华]登录命中缓存,ip: {},loginID: {}", ip, existLoginID);
|
|
return existLoginID;
|
|
}
|
|
// 执行登录
|
|
NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY pstInParam = new NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY();
|
|
pstInParam.szIP = nvrInfo.getNvrIp().getBytes();
|
|
pstInParam.nPort = nvrInfo.getServerPort();
|
|
pstInParam.szUserName = nvrInfo.getAccount().getBytes();
|
|
pstInParam.szPassword = nvrInfo.getPassword().getBytes();
|
|
NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY pstOutParam = new NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY();
|
|
LLong loginID = dhNetSDK.CLIENT_LoginWithHighLevelSecurity(pstInParam, pstOutParam);
|
|
if (loginID.intValue() == 0) {
|
|
int errorCode = dhNetSDK.CLIENT_GetLastError();
|
|
throw new RuntimeException("登录失败,错误码:" + errorCode);
|
|
}
|
|
// 放入缓存,自动开始计时10分钟
|
|
sessionCache.put(nvrInfo.getNvrIp(), loginID);
|
|
log.info("[大华]登录成功,ip:{},loginID:{}", ip, loginID);
|
|
return loginID;
|
|
}
|
|
|
|
/**
|
|
* 记录注销失败信息到 Redis
|
|
*/
|
|
private void recordLogoutError(String ip, LLong loginID, int errorCode) {
|
|
JSONObject json = new JSONObject();
|
|
json.put("ip", ip);
|
|
json.put("userId", loginID);
|
|
json.put("errorCode", errorCode);
|
|
json.put("time", System.currentTimeMillis());
|
|
redisService.redisTemplate.opsForZSet().add(ERROR_LOGOUT_KEY, json.toJSONString(), System.currentTimeMillis());
|
|
}
|
|
|
|
/**
|
|
* 登出具体实现
|
|
*/
|
|
public void doLogout(String ip, LLong loginID) {
|
|
if (loginID != null) {
|
|
// 执行登出操作
|
|
boolean isLogout = dhNetSDK.CLIENT_Logout(loginID);
|
|
if (isLogout) {
|
|
log.info("[大华]自动注销成功,ip: {},loginID: {}", ip, loginID.longValue());
|
|
} else {
|
|
int errorCode = dhNetSDK.CLIENT_GetLastError();
|
|
log.error("[大华]自动注销失败,ip: {},loginID: {},错误码: {}", ip, loginID.longValue(), errorCode);
|
|
// 记录失败日志到 Redis
|
|
recordLogoutError(ip, loginID, errorCode);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 登出
|
|
*/
|
|
public synchronized void logout(String ip) {
|
|
LLong loginID = sessionCache.getIfPresent(ip);
|
|
if (loginID != null) {
|
|
sessionCache.invalidate(ip);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 登出所有用户
|
|
*/
|
|
public void logoutAll() {
|
|
// 获取所有缓存的IP和userID
|
|
sessionCache.asMap().forEach((ip, loginID) -> {
|
|
doLogout(ip, loginID);
|
|
});
|
|
// 清空整个缓存
|
|
sessionCache.invalidateAll();
|
|
log.info("[大华]所有用户已登出");
|
|
}
|
|
|
|
/**
|
|
* 检查是否已登录(同时刷新过期时间)
|
|
*/
|
|
public boolean isLoggedIn(String ip) {
|
|
return sessionCache.getIfPresent(ip) != null;
|
|
}
|
|
}
|