|
@@ -0,0 +1,762 @@
|
|
|
|
+package com.dahua.sdk.client;
|
|
|
|
+
|
|
|
|
+import com.dahua.sdk.client.bean.RSAPrivateBean;
|
|
|
|
+import com.dahua.sdk.client.bean.hls.HLSBeanXo;
|
|
|
|
+import com.dahua.sdk.client.bean.hls.HLSXo;
|
|
|
|
+import com.dahua.sdk.client.bean.request.AuthorizeRequest;
|
|
|
|
+import com.dahua.sdk.client.bean.request.MyRestTemplate;
|
|
|
|
+import com.dahua.sdk.client.bean.response.*;
|
|
|
|
+import com.dahua.sdk.client.bean.xo.AuthorizeXo;
|
|
|
|
+import com.dahua.sdk.client.common.Constants;
|
|
|
|
+import com.dahua.sdk.client.common.DomainOfflineReasonEnum;
|
|
|
|
+import com.dahua.sdk.client.common.SchemeEnum;
|
|
|
|
+import com.dahua.sdk.client.common.ServiceErrorCode;
|
|
|
|
+import com.dahua.sdk.client.convert.JsonToObjectConvert;
|
|
|
|
+import com.dahua.sdk.client.util.*;
|
|
|
|
+import com.google.gson.reflect.TypeToken;
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
+import org.springframework.http.HttpEntity;
|
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
|
+import org.springframework.http.MediaType;
|
|
|
|
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+import org.springframework.web.client.HttpClientErrorException;
|
|
|
|
+import org.springframework.web.client.RestClientException;
|
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
|
+
|
|
|
|
+import javax.net.ssl.*;
|
|
|
|
+import java.net.HttpURLConnection;
|
|
|
|
+import java.net.URL;
|
|
|
|
+import java.security.SecureRandom;
|
|
|
|
+import java.security.cert.CertificateExpiredException;
|
|
|
|
+import java.security.cert.CertificateNotYetValidException;
|
|
|
|
+import java.security.cert.X509Certificate;
|
|
|
|
+import java.security.interfaces.RSAPrivateKey;
|
|
|
|
+import java.security.interfaces.RSAPublicKey;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.concurrent.ExecutorService;
|
|
|
|
+import java.util.concurrent.Executors;
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+public class DahuaDomainService {
|
|
|
|
+// protected static Logger logger = Logger.getLogger(DahuaDomainService.class);
|
|
|
|
+
|
|
|
|
+ protected SchemeEnum scheme;
|
|
|
|
+ protected String serverIp;
|
|
|
|
+
|
|
|
|
+ protected String clientIp;
|
|
|
|
+
|
|
|
|
+ protected int serverPort;
|
|
|
|
+
|
|
|
|
+ protected String username;
|
|
|
|
+
|
|
|
|
+ protected String password;
|
|
|
|
+
|
|
|
|
+ protected String passSalt;
|
|
|
|
+ protected String token;
|
|
|
|
+
|
|
|
|
+ protected String userId;
|
|
|
|
+
|
|
|
|
+ protected int KEEPALIVE_INTERVAL_TIME = 60;//保活间隔时间
|
|
|
|
+
|
|
|
|
+ protected int keepaliveFailedCount = 1;
|
|
|
|
+
|
|
|
|
+ protected Date tokenTime = new Date();
|
|
|
|
+
|
|
|
|
+ protected int tokenRate = 1800 - 300; // 默认token更新频率30分钟,平台提早几分钟去更新
|
|
|
|
+
|
|
|
|
+ protected ExecutorService bossExecutor = null;
|
|
|
|
+
|
|
|
|
+ protected volatile boolean isOnline = false;
|
|
|
|
+
|
|
|
|
+ protected volatile boolean isFinished = false;
|
|
|
|
+
|
|
|
|
+ protected RestTemplate restTemplate;
|
|
|
|
+
|
|
|
|
+ protected HttpHeaders headers;
|
|
|
|
+
|
|
|
|
+ protected volatile boolean started =false;
|
|
|
|
+
|
|
|
|
+ //mq 相关配置信息
|
|
|
|
+ private String mqAddress;
|
|
|
|
+
|
|
|
|
+ private String mqUserName;
|
|
|
|
+
|
|
|
|
+ private String mqPassword;
|
|
|
|
+
|
|
|
|
+ protected JsonToObjectConvert jsonConvert = JsonToObjectConvert.getInstance();
|
|
|
|
+
|
|
|
|
+ public DahuaDomainService(SchemeEnum scheme, String serverIp, int serverPort, String username, String password) {
|
|
|
|
+ this.scheme = scheme;
|
|
|
|
+ this.serverIp = serverIp;
|
|
|
|
+ this.serverPort = serverPort;
|
|
|
|
+ this.username = username;
|
|
|
|
+ this.password = password;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public int init() {
|
|
|
|
+
|
|
|
|
+ //TODO 参数检查
|
|
|
|
+
|
|
|
|
+ //设置请求头
|
|
|
|
+ headers = new HttpHeaders();
|
|
|
|
+ headers.setContentType(MediaType.parseMediaType("application/json;charset=utf-8"));
|
|
|
|
+
|
|
|
|
+ //初始化 restTemplate
|
|
|
|
+ SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
|
|
|
|
+ requestFactory.setConnectTimeout(1 * 1000);
|
|
|
|
+ requestFactory.setReadTimeout(30 * 1000);
|
|
|
|
+ requestFactory.setOutputStreaming(false);
|
|
|
|
+ this.restTemplate = new MyRestTemplate(requestFactory);
|
|
|
|
+
|
|
|
|
+ //openHttps
|
|
|
|
+ try {
|
|
|
|
+ openHttps();
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+ return ServiceErrorCode.SUCCESS;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 解决java.security.cert.CertificateException: No subject alternative names present
|
|
|
|
+ * 系统刚起来打开一次即可,放在init中为了利用domain的ip和port
|
|
|
|
+ * @throws Exception
|
|
|
|
+ * @since 7.02
|
|
|
|
+ */
|
|
|
|
+ public void openHttps() throws Exception {
|
|
|
|
+ final String[] VERIFY_HOST_NAME_ARRAY = new String[] {};
|
|
|
|
+
|
|
|
|
+ HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
|
|
|
|
+ @Override
|
|
|
|
+ public boolean verify(String hostname, SSLSession arg1) {
|
|
|
|
+ if (StringUtils.isEmpty(hostname)) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ return !Arrays.asList(VERIFY_HOST_NAME_ARRAY).contains(hostname);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
|
|
|
|
+ sslContext.init(null, trusTCerts, new SecureRandom());
|
|
|
|
+ HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
|
|
|
|
+ // 以下可以不需要
|
|
|
|
+ URL url = new URL(buildUrl("admin"));
|
|
|
|
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
|
|
+ connection.setRequestMethod("GET");
|
|
|
|
+ connection.setConnectTimeout(150);
|
|
|
|
+ connection.setReadTimeout(50);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 启动登录和心跳
|
|
|
|
+ * @return
|
|
|
|
+ * @since 7.02
|
|
|
|
+ */
|
|
|
|
+ public int start() {
|
|
|
|
+ if (started) {
|
|
|
|
+// logger.info("domain service already started"+commonLogInfo());
|
|
|
|
+ System.out.println("domain service already started"+commonLogInfo());
|
|
|
|
+ return ServiceErrorCode.SUCCESS;
|
|
|
|
+ }
|
|
|
|
+ // 初始化主线程,主要用于登录、重连和心跳
|
|
|
|
+ bossExecutor = Executors.newSingleThreadExecutor();
|
|
|
|
+ bossExecutor.submit(new Runnable() {
|
|
|
|
+ @Override
|
|
|
|
+ public void run() {
|
|
|
|
+ while (!Thread.interrupted()) {
|
|
|
|
+ if (!isOnline) {
|
|
|
|
+ int ret = ServiceErrorCode.SUCCESS;
|
|
|
|
+ try {
|
|
|
|
+ ret = authorize();
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.out.println("authorize error: "+e.getMessage());
|
|
|
|
+ ret = ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ TimeUnit.SECONDS.sleep(ret == ServiceErrorCode.SUCCESS ? KEEPALIVE_INTERVAL_TIME : 10);
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ System.out.println("sleep interrupted");
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ int ret;
|
|
|
|
+ try {
|
|
|
|
+ ret = keepalive();
|
|
|
|
+ updateToken();
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.out.println("keeplive error: "+e.getMessage());
|
|
|
|
+ ret = ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ret != ServiceErrorCode.SUCCESS) {
|
|
|
|
+ try {
|
|
|
|
+ TimeUnit.SECONDS.sleep(10);
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ System.out.println("sleep interrupted");
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ try {
|
|
|
|
+ TimeUnit.SECONDS.sleep(KEEPALIVE_INTERVAL_TIME);
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
+ System.out.println("sleep interrupted");
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ started = true;
|
|
|
|
+ return ServiceErrorCode.SUCCESS;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 登录
|
|
|
|
+ * @return 0-成功
|
|
|
|
+ * @since 7.02
|
|
|
|
+ */
|
|
|
|
+ public int authorize() {
|
|
|
|
+ AuthorizeRequest request = new AuthorizeRequest();
|
|
|
|
+ request.setUserName(username);
|
|
|
|
+ request.setClientType("WINPC_V1");
|
|
|
|
+ request.setIpAddress(serverIp);
|
|
|
|
+ AuthorizeFirstResponse firstResponse = null;
|
|
|
|
+ try {
|
|
|
|
+ restTemplate.postForObject(buildUrl("/admin/API/accounts/authorize"), request, String.class);
|
|
|
|
+ } catch(RestClientException e) {
|
|
|
|
+ // 防止登录一个失败的请求导致等待的过程中(连接超时设置10秒)新的域已经登录成功,超时候会将成功的域改成离线
|
|
|
|
+ if (!started) {
|
|
|
|
+ System.out.println(String.format("destroy when authorize%s", commonLogInfo()));
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+ if (e instanceof HttpClientErrorException) {
|
|
|
|
+ HttpClientErrorException response = (HttpClientErrorException) e;
|
|
|
|
+ if (401 == response.getStatusCode().value()) {
|
|
|
|
+ String body = response.getResponseBodyAsString();
|
|
|
|
+ firstResponse = (AuthorizeFirstResponse) jsonConvert.convert(body, AuthorizeFirstResponse.class);
|
|
|
|
+ } else {
|
|
|
|
+ System.out.println("login domain failed, error: "+e.getMessage());
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ System.out.println("login domain failed, error: "+e.getMessage());
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.out.println("login domain failed, error: "+e.getMessage());
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (null == firstResponse) {
|
|
|
|
+ System.out.println("login to domain failed, response is null");
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String pass_temp = "";
|
|
|
|
+ try {
|
|
|
|
+ pass_temp = EncryptionUtils.encryptWithMD5(EncryptionUtils.encryptWithMD5(username + EncryptionUtils.encryptWithMD5(password)));
|
|
|
|
+ }catch (Exception e){
|
|
|
|
+ System.out.println(e);
|
|
|
|
+ }
|
|
|
|
+ String encrypted_passwd = EncryptionUtils.encryptWithMD5(String.format("%s:%s:%s", username, firstResponse.getRealm(), pass_temp));
|
|
|
|
+ String signature = EncryptionUtils.encryptWithMD5(String.format("%s:%s", encrypted_passwd, firstResponse.getRandomKey()));
|
|
|
|
+ passSalt = firstResponse.getRealm();
|
|
|
|
+ if (null == signature) {
|
|
|
|
+ System.out.println("encrypt password failed, password is null");
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ request.setEncryptType(firstResponse.getEncryptType());
|
|
|
|
+ request.setRandomKey(firstResponse.getRandomKey());
|
|
|
|
+ request.setSignature(signature);
|
|
|
|
+ RSAPublicKey rsaPublicKey = null;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ rsaPublicKey = RsaUtil.generateRandomKey();
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.out.println("generate rsa public key error" + e);
|
|
|
|
+ }
|
|
|
|
+ RSAPrivateKey rsaPrivateKey = ((RSAPrivateBean) RsaUtil.getKeyPairMap().get(Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()))).getRsaPrivateKey();
|
|
|
|
+ request.setPublicKey(Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()));
|
|
|
|
+
|
|
|
|
+ AuthorizeResponse authResponse;
|
|
|
|
+ try {
|
|
|
|
+ authResponse = restTemplate.postForObject(buildUrl("/admin/API/accounts/authorize"), request, AuthorizeResponse.class);
|
|
|
|
+ } catch(RestClientException e) {
|
|
|
|
+ System.out.println("login domain failed, error: "+e.getMessage());
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ } catch(Exception e) {
|
|
|
|
+ System.out.println("login domain failed, error: "+e.getMessage());
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+ if (null == authResponse) {
|
|
|
|
+ System.out.println("login to domain failed, response is null");
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+ if (null != authResponse.getCode() && !"1000".equals(authResponse.getCode())) {
|
|
|
|
+ System.out.println(String.format("login to domain failed, code=%s, desc=%s%s", authResponse.getCode(), authResponse.getDesc()));
|
|
|
|
+ handleOffline(authResponse.getCode());
|
|
|
|
+ offlineHandle();
|
|
|
|
+ // 如果是用户名密码错误则无需再登录
|
|
|
|
+ if ("2001".equals(authResponse.getCode())) {
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+ token = authResponse.getToken();
|
|
|
|
+ tokenTime = new Date();
|
|
|
|
+ userId = authResponse.getUserId();
|
|
|
|
+ String duration = authResponse.getDuration();
|
|
|
|
+ if (!StringUtil.isEmpty(duration) && StringUtil.isInteger(duration)) {
|
|
|
|
+ KEEPALIVE_INTERVAL_TIME = (int) Math.rint(Integer.parseInt(duration) * 3/4);
|
|
|
|
+ }
|
|
|
|
+ headers.remove("X-Subject-Token");
|
|
|
|
+ headers.add("X-Subject-Token", token);
|
|
|
|
+ keepaliveFailedCount = 1;
|
|
|
|
+ System.out.println("login to domain successfully");
|
|
|
|
+
|
|
|
|
+ // 登录成功之后立即做的事情
|
|
|
|
+ loginAfterSyncHandle();
|
|
|
|
+
|
|
|
|
+ String secretKey = authResponse.getSecretKey();
|
|
|
|
+ String secretVector = authResponse.getSecretVector();
|
|
|
|
+ try {
|
|
|
|
+ byte[] secretKeyBytes = Base64.getDecoder().decode(secretKey);
|
|
|
|
+ byte[] bytes = Base64.getDecoder().decode(secretVector);
|
|
|
|
+ secretKey = new String(RsaUtil.decryptByPrivateKey(secretKeyBytes, HexUtil.bytesToHexString(rsaPrivateKey.getEncoded())), Constants.ENCODING);
|
|
|
|
+ secretVector = new String(RsaUtil.decryptByPrivateKey(bytes, HexUtil.bytesToHexString(rsaPrivateKey.getEncoded())), Constants.ENCODING);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.out.println("get address failed, RSA decrypt error" + e);
|
|
|
|
+ }
|
|
|
|
+ authResponse.setSecretKey(secretKey);
|
|
|
|
+ authResponse.setSecretVector(secretVector);
|
|
|
|
+
|
|
|
|
+ isOnline = true;
|
|
|
|
+ // 置为在线
|
|
|
|
+
|
|
|
|
+ return ServiceErrorCode.SUCCESS;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 更新 token
|
|
|
|
+ */
|
|
|
|
+ protected void updateToken() {
|
|
|
|
+ long millis = System.currentTimeMillis() - tokenTime.getTime();
|
|
|
|
+ if (millis < (long)tokenRate * 1000) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Map<String, String> params = new HashMap<String, String>();
|
|
|
|
+
|
|
|
|
+ String encryptPass = EncryptionUtils.encryptWithMD5(username +":" + passSalt + ":" +
|
|
|
|
+ EncryptionUtils.encryptWithMD5( EncryptionUtils.encryptWithMD5(username + EncryptionUtils.encryptWithMD5(password))));
|
|
|
|
+
|
|
|
|
+ params.put("signature", EncryptionUtils.encryptWithMD5(String.format("%s:%s", encryptPass, token)));
|
|
|
|
+ HttpEntity<Map<String, String>> request = new HttpEntity<Map<String, String>>(params, headers);
|
|
|
|
+ APIResponseInfo updateTokenResponse;
|
|
|
|
+ boolean updateTokenSuccess = false;
|
|
|
|
+ String newToken = null;
|
|
|
|
+ for (int i = 0; i < 3; i++) {
|
|
|
|
+ try {
|
|
|
|
+ updateTokenResponse = restTemplate.postForObject(buildUrl("/admin/API/accounts/updateToken"), request, APIResponseInfo.class);
|
|
|
|
+ updateTokenSuccess = true;
|
|
|
|
+ newToken = JsonParserUtils.getPrimitiveField(updateTokenResponse.getData().toString(), "token", String.class);
|
|
|
|
+ break;
|
|
|
|
+ } catch(Exception e) {
|
|
|
|
+ System.out.println("update token failed:" + e.getMessage());
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ TimeUnit.SECONDS.sleep(10);
|
|
|
|
+ } catch (InterruptedException e1) {
|
|
|
|
+ System.out.println("sleep interrupted");
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!updateTokenSuccess) {
|
|
|
|
+ offlineHandle();
|
|
|
|
+ System.out.println("updateToken failed");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //logger.info("newtoken:" + newToken);
|
|
|
|
+ if (null != newToken) {
|
|
|
|
+ token = newToken;
|
|
|
|
+ tokenTime = new Date();
|
|
|
|
+ headers.remove("X-Subject-Token");
|
|
|
|
+ headers.add("X-Subject-Token", token);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 心跳
|
|
|
|
+ * @return
|
|
|
|
+ * @since 7.02
|
|
|
|
+ */
|
|
|
|
+ protected int keepalive() {
|
|
|
|
+ Map<String, String> params = new HashMap<String, String>();
|
|
|
|
+ params.put("signature", "domain");
|
|
|
|
+ HttpEntity<Map<String, String>> request = new HttpEntity<Map<String, String>>(params, headers);
|
|
|
|
+ try {
|
|
|
|
+ //restTemplate.postForObject(buildUrl("/admin/API/accounts/keepalive"), request, String.class);
|
|
|
|
+ restTemplate.put(buildUrl("/admin/API/accounts/keepalive"), request, String.class);
|
|
|
|
+ } catch(RestClientException e) {
|
|
|
|
+ if (keepaliveFailedCount > 3) {
|
|
|
|
+ offlineHandle();
|
|
|
|
+ System.out.println("keepalive failed"+commonLogInfo()+", error: "+e.getMessage());
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+ keepaliveFailedCount++;
|
|
|
|
+ return ServiceErrorCode.SUCCESS;
|
|
|
|
+ } catch(Exception e) {
|
|
|
|
+ if (keepaliveFailedCount > 3) {
|
|
|
|
+ offlineHandle();
|
|
|
|
+ System.out.println("keepalive failed"+commonLogInfo()+", error: "+e.getMessage());
|
|
|
|
+ // 置为离线
|
|
|
|
+ return ServiceErrorCode.FAIL;
|
|
|
|
+ }
|
|
|
|
+ keepaliveFailedCount++;
|
|
|
|
+ return ServiceErrorCode.SUCCESS;
|
|
|
|
+ }
|
|
|
|
+ keepaliveFailedCount = 1;
|
|
|
|
+ System.out.println("keepalive"+commonLogInfo());
|
|
|
|
+ return ServiceErrorCode.SUCCESS;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 登录成功之后同步处理的方法
|
|
|
|
+ *
|
|
|
|
+ * @since 7.02
|
|
|
|
+ */
|
|
|
|
+ public void loginAfterSyncHandle() {
|
|
|
|
+ //获取 mq 连接配置信息
|
|
|
|
+ getMqAddrInfo();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取MQ地址
|
|
|
|
+ *
|
|
|
|
+ * @since 7.02
|
|
|
|
+ */
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ public void getMqAddrInfo() {
|
|
|
|
+ Map<String, Object> params = new HashMap<String, Object>();
|
|
|
|
+// params.put("data", null);
|
|
|
|
+ params.put("clientType", "WINPC_V1");
|
|
|
|
+ params.put("clientMac", "");
|
|
|
|
+ params.put("project", "PSDK");
|
|
|
|
+ params.put("method", "BRM.Config.GetMqConfig");
|
|
|
|
+ DhDomainResponseInfo<MqAddressResponseInfo> responseInfo = null;
|
|
|
|
+ DhDomainResponseInfo<SuccessResponse> aesResponseInfo = null;
|
|
|
|
+ RSAPublicKey rsaPublicKey = null;
|
|
|
|
+ try {
|
|
|
|
+ rsaPublicKey = RsaUtil.generateRandomKey();
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.out.println("generate rsa public key error" + e);
|
|
|
|
+ }
|
|
|
|
+ if(StringUtil.isBlank(rsaPublicKey)){
|
|
|
|
+ System.out.println("generate rsa public key error");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ System.out.println("rsaPublicKey: "+ rsaPublicKey);
|
|
|
|
+ RSAPrivateKey rsaPrivateKey = ((RSAPrivateBean) RsaUtil.getKeyPairMap().get(Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()))).getRsaPrivateKey();
|
|
|
|
+ System.out.println("rsaPrivateKey: "+ rsaPrivateKey);
|
|
|
|
+ try {
|
|
|
|
+ String responseStr = restTemplate.postForObject(buildUrl(String.format("/admin/API/BRM/Config/GetMqConfig?token=%s", token)), params, String.class);
|
|
|
|
+ responseInfo = (DhDomainResponseInfo<MqAddressResponseInfo>) jsonConvert.convert(responseStr, new TypeToken<DhDomainResponseInfo<MqAddressResponseInfo>>(){}.getType());
|
|
|
|
+ AuthorizeXo authorizeXo = new AuthorizeXo();
|
|
|
|
+ authorizeXo.setPublicKey(Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()));
|
|
|
|
+ String aesResponseStr = restTemplate.postForObject(buildUrl(String.format("/admin/API/config/encrypt/key/generate?token=%s",token)),authorizeXo, String.class);
|
|
|
|
+ aesResponseInfo = (DhDomainResponseInfo<SuccessResponse>) jsonConvert.convert(aesResponseStr, new TypeToken<DhDomainResponseInfo<SuccessResponse>>(){}.getType());
|
|
|
|
+
|
|
|
|
+ } catch(RestClientException e) {
|
|
|
|
+ System.out.println("get mq address failed"+commonLogInfo()+", error: "+e.getMessage());
|
|
|
|
+ return;
|
|
|
|
+ } catch(Exception e) {
|
|
|
|
+ System.out.println("get mq address failed"+commonLogInfo()+", error: "+e.getMessage());
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (1000 != responseInfo.getCode()) {
|
|
|
|
+ System.out.println(String.format("get mq address failed, code=%s, desc=%s%s", responseInfo.getCode(), responseInfo.getDesc(), commonLogInfo()));
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ MqAddressResponseInfo mqAddressResponse = responseInfo.getData();
|
|
|
|
+ SuccessResponse aesResponse= aesResponseInfo.getData();
|
|
|
|
+ if (null == mqAddressResponse) {
|
|
|
|
+ System.out.println("get mq address failed, mqAddressResponse is null"+commonLogInfo());
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ mqAddress = mqAddressResponse.getAddr();
|
|
|
|
+ mqUserName = mqAddressResponse.getUserName();
|
|
|
|
+
|
|
|
|
+ System.out.println("address: "+ mqAddress+ ";mqUserName: "+ mqUserName);
|
|
|
|
+ //获取aes秘钥和向量
|
|
|
|
+ String secretKey = aesResponse.getSecretKey();
|
|
|
|
+ String secretVector = aesResponse.getSecretVector();
|
|
|
|
+ System.out.println("secretKey:"+ secretKey+ ";secretVector: "+ secretVector);
|
|
|
|
+
|
|
|
|
+ System.out.println("$$$$ mqAddressResponse.getPassword() " + mqAddressResponse.getPassword());
|
|
|
|
+ try {
|
|
|
|
+ byte[] secretKeyBytes = Base64.getDecoder().decode(secretKey);
|
|
|
|
+ byte[] bytes = Base64.getDecoder().decode(secretVector);
|
|
|
|
+ secretKey = new String(RsaUtil.decryptByPrivateKey(secretKeyBytes,HexUtil.bytesToHexString(rsaPrivateKey.getEncoded())), Constants.ENCODING);
|
|
|
|
+ secretVector = new String(RsaUtil.decryptByPrivateKey(bytes, HexUtil.bytesToHexString(rsaPrivateKey.getEncoded())), Constants.ENCODING);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ System.out.println("get mq address failed, RSA decrypt error" + e);
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+// logger.error("get mq address failed, RSA decrypt error" + e);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// mqPassword = EncryptionUtils.decryptByAesCbc(mqAddressResponse.getPassword(), secretKey, secretVector);
|
|
|
|
+ mqPassword = EncryptionUtils.decryptByAesCbc(mqAddressResponse.getPassword(), secretKey, secretVector);
|
|
|
|
+ System.out.println(String.format("get mq address: %s", mqAddress));
|
|
|
|
+
|
|
|
|
+ System.out.println("$$$$ mq: " + mqAddress + " == " + mqUserName + " == " + mqPassword);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void test1(){
|
|
|
|
+// List<String> aesKeys = null;
|
|
|
|
+// try {
|
|
|
|
+// aesKeys = EncryptionUtils.getAesKey();
|
|
|
|
+// String decryptPassWord = "";
|
|
|
|
+// for (String aesKey : aesKeys) {
|
|
|
|
+// decryptPassWord = EncryptionUtils.decryptByAesCbcGDPR(password, aesKey);
|
|
|
|
+// if (StringUtils.isNotEmpty(decryptPassWord)) {
|
|
|
|
+// break;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// if (StringUtils.isNotEmpty(decryptPassWord)) {
|
|
|
|
+// password = decryptPassWord;
|
|
|
|
+// }
|
|
|
|
+// logger.debug("mq用户名,gdpr解密成功:" + decryptPassWord);
|
|
|
|
+// } catch (Exception e) {
|
|
|
|
+// logger.error(e);
|
|
|
|
+// }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void handleOffline(String code) {
|
|
|
|
+ // 置为离线
|
|
|
|
+ int status;
|
|
|
|
+ if ("2001".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.USER_PASS_ERROR.getCode();
|
|
|
|
+ } else if ("2002".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.USER_LOCKED.getCode();
|
|
|
|
+ } else if ("2003".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.USER_DISABLED.getCode();
|
|
|
|
+ } else if ("2004".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.USER_LOGGED_IN.getCode();
|
|
|
|
+ } else if ("2005".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.USER_DATE_OVER.getCode();
|
|
|
|
+ } else if ("2006".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.USER_TIME_OVER.getCode();
|
|
|
|
+ } else if ("2155".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.USER_MAC_ERROR.getCode();
|
|
|
|
+ } else if ("2156".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.AD_LOGIN_CLOSE.getCode();
|
|
|
|
+ } else if ("2218".equals(code)) {
|
|
|
|
+ status = DomainOfflineReasonEnum.USER_LOCKED_SYS_UPGRADE.getCode();
|
|
|
|
+ } else {
|
|
|
|
+ status = DomainOfflineReasonEnum.CONNECT_EXCEPTION.getCode();
|
|
|
|
+ }
|
|
|
|
+ System.out.println("offline reason code: " + status);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 离线之后要做的事情
|
|
|
|
+ *
|
|
|
|
+ * @since 7.02
|
|
|
|
+ */
|
|
|
|
+ public void offlineHandle(){
|
|
|
|
+ isOnline = false;
|
|
|
|
+ isFinished = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ protected String buildUrl(String url) {
|
|
|
|
+ StringBuilder str = new StringBuilder();
|
|
|
|
+ str.append(scheme.getScheme());
|
|
|
|
+ str.append(serverIp);
|
|
|
|
+ str.append(":");
|
|
|
|
+ str.append(serverPort);
|
|
|
|
+ str.append("/");
|
|
|
|
+ str.append(url);
|
|
|
|
+ return str.toString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String buildUrlWithToken(String url) {
|
|
|
|
+ StringBuilder str = new StringBuilder();
|
|
|
|
+ str.append(scheme.getScheme());
|
|
|
|
+ str.append(serverIp);
|
|
|
|
+ str.append(":");
|
|
|
|
+ str.append(serverPort);
|
|
|
|
+ str.append("/");
|
|
|
|
+ str.append(url);
|
|
|
|
+ str.append("?token=" + token);
|
|
|
|
+ return str.toString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 公共日志信息
|
|
|
|
+ * @return
|
|
|
|
+ * @since 7.02
|
|
|
|
+ */
|
|
|
|
+ protected String commonLogInfo() {
|
|
|
|
+ StringBuilder str = new StringBuilder();
|
|
|
|
+ str.append(", ip=");
|
|
|
|
+ str.append(serverIp);
|
|
|
|
+ str.append(":");
|
|
|
|
+ str.append(serverPort);
|
|
|
|
+ return str.toString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public ResponseInfo getHls(){
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * {
|
|
|
|
+ *
|
|
|
|
+ * "hlsBeanXoList": [
|
|
|
|
+ * {
|
|
|
|
+ * "devicecode": "1000002",
|
|
|
|
+ * "unitSeq": "1",
|
|
|
|
+ * "chnSeq": "0",
|
|
|
|
+ * "recordSource": "2",
|
|
|
|
+ * "recordType": "1",
|
|
|
|
+ * "streamType": "1",
|
|
|
|
+ * "beginTime": "2020-06-19 00:00:00",
|
|
|
|
+ * "endTime": "2020-06-19 23:59:59"
|
|
|
|
+ * }
|
|
|
|
+ * ]
|
|
|
|
+ *
|
|
|
|
+ * }
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ Map<String, Object> params = new HashMap<>();
|
|
|
|
+ HLSXo hlsXo = new HLSXo();
|
|
|
|
+
|
|
|
|
+ HLSBeanXo hlsBeanXo = new HLSBeanXo();
|
|
|
|
+ hlsBeanXo.setDevicecode("1000000");
|
|
|
|
+ hlsBeanXo.setUnitSeq("1");
|
|
|
|
+ hlsBeanXo.setChnSeq("0");
|
|
|
|
+ hlsBeanXo.setRecordSource("2");
|
|
|
|
+ hlsBeanXo.setRecordType("1");
|
|
|
|
+ hlsBeanXo.setStreamType("1");
|
|
|
|
+ hlsBeanXo.setBeginTime("2020-07-01 00:00:00");
|
|
|
|
+ hlsBeanXo.setEndTime("2020-07-01 23:59:59");
|
|
|
|
+
|
|
|
|
+ List<HLSBeanXo> hlsBeanXoList = new ArrayList<>();
|
|
|
|
+ hlsBeanXoList.add(hlsBeanXo);
|
|
|
|
+
|
|
|
|
+ hlsXo.setHlsBeanXoList(hlsBeanXoList);
|
|
|
|
+
|
|
|
|
+ params.put("data", hlsXo);
|
|
|
|
+ HttpEntity<Map<String, Object>> request = new HttpEntity<>(params, headers);
|
|
|
|
+
|
|
|
|
+ ResponseInfo responseInfo = restTemplate.postForObject(buildUrlWithToken("/admin/API/hls/getLiveUrl"), request,
|
|
|
|
+ ResponseInfo.class);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ return responseInfo;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * HttpEntity 封装参数
|
|
|
|
+ * @param params
|
|
|
|
+ * @param <T>
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public <T> HttpEntity<T> getHttpEntity(T params){
|
|
|
|
+ HttpEntity<T> request = new HttpEntity<>(params, headers);
|
|
|
|
+ return request;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ *
|
|
|
|
+ * @param uri /admin/API/tree/devices
|
|
|
|
+ * @param request
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public String postForObject(String uri, HttpEntity request){
|
|
|
|
+ String responseStr = restTemplate.postForObject(buildUrl(uri), // attach token
|
|
|
|
+ request,
|
|
|
|
+ String.class); //表示返回值类型
|
|
|
|
+ return responseStr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public <T> String postForObject(String uri, Map<String, T> request){
|
|
|
|
+ String responseStr = restTemplate
|
|
|
|
+ .postForObject(buildUrlWithToken(uri), request, String.class);
|
|
|
|
+
|
|
|
|
+ return responseStr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public JsonToObjectConvert getJsonConvert() {
|
|
|
|
+ return jsonConvert;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public String getMqUserName() {
|
|
|
|
+ return mqUserName;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public String getMqPassword() {
|
|
|
|
+ return mqPassword;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public String getMqAddress() {
|
|
|
|
+ return mqAddress;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 信任证书
|
|
|
|
+ */
|
|
|
|
+ static TrustManager[] trusTCerts = new TrustManager[] {
|
|
|
|
+ new X509TrustManager() {
|
|
|
|
+ @Override
|
|
|
|
+ public X509Certificate[] getAcceptedIssuers() {
|
|
|
|
+ return new X509Certificate[]{};
|
|
|
|
+ }
|
|
|
|
+ @Override
|
|
|
|
+ public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
|
|
|
+ for (X509Certificate certificate : chain) {
|
|
|
|
+ try {
|
|
|
|
+ certificate.checkValidity();
|
|
|
|
+ } catch (CertificateExpiredException e) {
|
|
|
|
+ System.out.println("CertificateExpiredException " + e);
|
|
|
|
+ } catch (CertificateNotYetValidException e) {
|
|
|
|
+ System.out.println("CertificateNotYetValidException " + e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ @Override
|
|
|
|
+ public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
|
|
|
+ for (X509Certificate certificate : chain) {
|
|
|
|
+ try {
|
|
|
|
+ certificate.checkValidity();
|
|
|
|
+ } catch (CertificateExpiredException e) {
|
|
|
|
+ System.out.println("CertificateExpiredException " + e);
|
|
|
|
+ } catch (CertificateNotYetValidException e) {
|
|
|
|
+ System.out.println("CertificateNotYetValidException " + e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+}
|