package com.ruoyi.web.integration.dahua; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.system.utils.DoorDeviceCredentialCrypto; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Date; /** * 仅用于实体门禁联调:临时下发测试人员和人脸,并在 finally 中立即撤权。 */ public final class DahuaGrantProbe { private static final String TEST_USER_ID = "CODEX_TEST_20260810"; private static final String TEST_USER_NAME = "门禁联调测试"; private static final long ONE_MINUTE_MILLIS = 60_000L; private static final int DEVICE_FACE_IMAGE_LIMIT = 200 * 1024; private DahuaGrantProbe() { } public static void main(String[] args) throws Exception { if (args.length != 5) { throw new IllegalArgumentException("参数:原生库目录、设备地址、用户名、profile目录、人脸图片地址"); } String passwordCipher = System.getenv("DAHUA_DEVICE_PASSWORD_CIPHER"); if (passwordCipher == null || passwordCipher.trim().isEmpty()) { throw new IllegalArgumentException("缺少 DAHUA_DEVICE_PASSWORD_CIPHER"); } String password = DoorDeviceCredentialCrypto.decrypt(passwordCipher); new RuoYiConfig().setProfile(args[3]); byte[] faceImage = new DahuaFaceImageLoader().load(args[4]); DahuaAccessProperties properties = createProperties(args[0], args[2], password); DahuaAccessControlClient client = new DahuaAccessControlClient(properties); DahuaDeviceCredential device = new DahuaDeviceCredential( args[1], 37777, args[2], password, 0, 255, "GBK"); long now = System.currentTimeMillis(); DahuaAccessControlClient.VisitorCredential visitor = new DahuaAccessControlClient.VisitorCredential( TEST_USER_ID, TEST_USER_NAME, null, new Date(now - ONE_MINUTE_MILLIS), new Date(now + 5 * ONE_MINUTE_MILLIS), faceImage); RuntimeException grantFailure = null; try { client.grant(device, visitor); System.out.println("grantSuccess=true"); } catch (RuntimeException e) { grantFailure = e; throw e; } finally { try { client.revoke(device, TEST_USER_ID); System.out.println("revokeSuccess=true"); } catch (RuntimeException revokeFailure) { if (grantFailure != null) { grantFailure.addSuppressed(revokeFailure); } else { throw revokeFailure; } } finally { client.cleanup(); } } } private static DahuaAccessProperties createProperties(String nativeLibraryPath, String username, String password) { DahuaAccessProperties properties = new DahuaAccessProperties(); properties.setNativeLibraryPath(nativeLibraryPath); properties.setConnectTimeout(5000); properties.setTimeout(10000); return properties; } private static byte[] loadFaceImage(Path path) throws Exception { byte[] image = Files.readAllBytes(path); if (image.length == 0 || image.length > DahuaSdkLayout.MAX_FACE_IMAGE_BYTES) { throw new IllegalArgumentException("人脸图片必须大于0且不超过200KB"); } if (!isJpeg(image) && !isPng(image)) { throw new IllegalArgumentException("人脸图片必须是有效的JPEG或PNG文件"); } if (image.length <= DEVICE_FACE_IMAGE_LIMIT && isJpeg(image)) { return image; } BufferedImage source = ImageIO.read(new ByteArrayInputStream(image)); if (source == null) { throw new IllegalArgumentException("无法解码人脸图片"); } ByteArrayOutputStream output = new ByteArrayOutputStream(); if (!ImageIO.write(source, "jpg", output)) { throw new IllegalArgumentException("无法将人脸图片转换为JPEG"); } byte[] normalized = output.toByteArray(); if (normalized.length > DEVICE_FACE_IMAGE_LIMIT) { throw new IllegalArgumentException("人脸图片转换后仍超过120KB"); } System.out.println("normalizedFaceBytes=" + normalized.length); return normalized; } private static boolean isJpeg(byte[] image) { return image.length >= 3 && (image[0] & 0xFF) == 0xFF && (image[1] & 0xFF) == 0xD8 && (image[2] & 0xFF) == 0xFF; } private static boolean isPng(byte[] image) { return image.length >= 8 && (image[0] & 0xFF) == 0x89 && image[1] == 0x50 && image[2] == 0x4E && image[3] == 0x47 && image[4] == 0x0D && image[5] == 0x0A && image[6] == 0x1A && image[7] == 0x0A; } }