Xiajijian
2025-10-14 dc0b17d8d9b6f2c17165cd394dbd74e304422a5c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package com.ard.work.aspect;
 
import com.ard.common.exception.ControlException;
import com.ard.common.utils.SecurityUtils;
import com.ard.work.aspect.annotation.CheckTakeoffAltitude;
import com.ard.work.aspect.annotation.CheckControlRight;
import com.ard.work.domain.cache.UavTelemetryDataCache;
import com.ard.work.domain.dto.telemetry.TelemetryData;
import com.ard.work.service.control.UavControlService;
import com.ard.work.domain.message.UavControlType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
 
import javax.annotation.Resource;
import java.lang.reflect.Field;
 
/**
 * AOP 切面:拦截 @RequireUavControl,检查用户是否拥有 UAV 控制权限
 *
 * 注意切面顺序:同类方法注解按字母ABCD顺序,不同类注解按order(1)顺序 越小优先级越高
 */
@Aspect
@Component
public class UavControlAspect {
 
    @Resource
    private UavControlService uavControlService;
 
    /**
     * 前置通知:控制权检测
     */
    @Before("@annotation(checkControlRight)")
    public void checkUavControl(JoinPoint joinPoint, CheckControlRight checkControlRight) {
        // 获取当前用户 ID
        Long userId = SecurityUtils.getUserId();
 
        // 获取控制类型
        UavControlType controlType = checkControlRight.value();
 
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
 
        // 遍历参数,使用反射获取每个参数中的 boxSn
        for (Object arg : args) {
            String boxSn = getBoxSn(arg);  // 调用之前实现的 getBoxSn 方法
            if (boxSn != null) {
                // 检查当前用户是否拥有该设备的控制权限
                Long currentController = uavControlService.getCurrentController(boxSn,
                        controlType.name().toLowerCase());
                if (currentController == null || !currentController.equals(userId)) {
                    throw new ControlException("无权执行该操作,需要 " + controlType + " 控制权限");
                }
            }
        }
    }
 
    /**
     * 前置通知:高度检查
     */
    @Before("@annotation(checkTakeoffAltitude)")
    public void takeoffAltitudeCheck(JoinPoint joinPoint, CheckTakeoffAltitude checkTakeoffAltitude) {
        // 获取最小高度
        double minAltitude = checkTakeoffAltitude.minAltitude();
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
 
        // 遍历参数,使用反射获取每个参数中的 boxSn
        for (Object arg : args) {
            String boxSn = getBoxSn(arg);  // 调用之前实现的 getBoxSn 方法
            if (boxSn != null) {
                TelemetryData uavTelemetryData = UavTelemetryDataCache.getUavTelemetryData(boxSn);
                if (uavTelemetryData == null) {
                    throw new ControlException("遥测数据异常,无法执行!");
                }
                // 检查高度
                if (uavTelemetryData.getAltitude() < minAltitude) {
                    throw new ControlException("高度太低,无法执行!最低高度: " + minAltitude);
                }
            }
        }
    }
 
    /**
     * 通过反射获取对象中的 boxSn 字段
     *
     * @param dto 要反射的对象
     * @return boxSn 字段的值,如果没有找到则返回 null
     */
    public static String getBoxSn(Object dto) {
        if (dto == null) {
            return null; // 如果对象为空,直接返回 null
        }
 
        try {
            // 获取类的所有字段
            Field[] fields = dto.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 设置字段可访问
                field.setAccessible(true);
 
                // 判断是否是 boxSn 字段
                if ("boxSn".equals(field.getName())) {
                    // 检查字段类型是否是 String 类型
                    if (field.getType().equals(String.class)) {
                        // 获取并返回 boxSn 字段的值
                        return (String) field.get(dto);
                    } else {
                        // 如果字段类型不是 String,返回 null
                        return null;
                    }
                }
            }
        } catch (IllegalAccessException e) {
            // 捕获异常并打印日志
            System.err.println("反射访问失败: " + e.getMessage());
            e.printStackTrace();
        }
 
        return null; // 如果没有找到 boxSn 字段,返回 null
    }
}