视频监控设备列表/详情/云台等接口按当前账号站点权限过滤,防止越权访问
1个文件已修改
122 ■■■■■ 已修改文件
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/VideoMonitorController.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/VideoMonitorController.java
@@ -2,21 +2,33 @@
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.other.api.domain.TDevice;
import com.ruoyi.other.api.feignClient.RoleSiteClient;
import com.ruoyi.other.api.feignClient.UserSiteClient;
import com.ruoyi.other.query.VideoMonitorControlRequest;
import com.ruoyi.other.query.VideoMonitorPageQuery;
import com.ruoyi.other.service.TDeviceService;
import com.ruoyi.other.util.EzvizOpenApiUtils;
import com.ruoyi.other.vo.VideoMonitorDeviceVO;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.feignClient.SysUserClient;
import com.ruoyi.system.api.feignClient.SysUserRoleClient;
import com.ruoyi.system.api.model.SysUserRoleVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -36,15 +48,34 @@
    @Resource
    private EzvizOpenApiUtils ezvizOpenApiUtils;
    @Resource
    private SysUserClient sysUserClient;
    @Resource
    private SysUserRoleClient sysUserRoleClient;
    @Resource
    private UserSiteClient userSiteClient;
    @Resource
    private RoleSiteClient roleSiteClient;
    @ResponseBody
    @GetMapping("/pageList")
    @ApiOperation(value = "获取视频监控列表", tags = {"管理后台-视频监控"})
    public AjaxResult<PageInfo<VideoMonitorDeviceVO>> pageList(VideoMonitorPageQuery query) {
        DeviceAuthScope scope = resolveAuthScope();
        if (scope.siteIds != null && scope.siteIds.isEmpty()) {
            // 非管理员且无任何授权站点:直接返回空列表,避免全量查询
            return AjaxResult.success(new PageInfo<>(query.getPageCurr(), query.getPageSize()));
        }
        Page<TDevice> page = deviceService.lambdaQuery()
                .like(StringUtils.hasText(query.getDeviceName()), TDevice::getDeviceName, query.getDeviceName())
                .eq(query.getPartnerType() != null, TDevice::getPartnerType, query.getPartnerType())
                .eq(query.getPartnerId() != null, TDevice::getPartnerId, query.getPartnerId())
                .eq(query.getSiteId() != null && query.getSiteId() != 0, TDevice::getSiteId, query.getSiteId())
                .eq(scope.partnerId != null, TDevice::getPartnerId, scope.partnerId)
                .in(scope.siteIds != null, TDevice::getSiteId, scope.siteIds)
                .orderByDesc(TDevice::getCreateTime)
                .page(Page.of(query.getPageCurr(), query.getPageSize()));
@@ -72,6 +103,9 @@
        if (device == null) {
            return AjaxResult.error("设备不存在");
        }
        if (!canAccessDevice(device)) {
            return AjaxResult.error("无权访问该设备");
        }
        VideoMonitorDeviceVO vo = toMonitorVO(device);
        fillOnlineStatus(vo);
@@ -86,6 +120,9 @@
        TDevice device = getDevice(request.getId());
        if (device == null) {
            return AjaxResult.error("设备不存在");
        }
        if (!canAccessDevice(device)) {
            return AjaxResult.error("无权访问该设备");
        }
        JSONObject result = ezvizOpenApiUtils.ptzControl(
@@ -106,6 +143,9 @@
        if (device == null) {
            return AjaxResult.error("设备不存在");
        }
        if (!canAccessDevice(device)) {
            return AjaxResult.error("无权访问该设备");
        }
        JSONObject result = ezvizOpenApiUtils.setSceneSwitch(
                device.getDeviceSerial(),
@@ -122,6 +162,9 @@
        TDevice device = getDevice(request.getId());
        if (device == null) {
            return AjaxResult.error("设备不存在");
        }
        if (!canAccessDevice(device)) {
            return AjaxResult.error("无权访问该设备");
        }
        JSONObject result = ezvizOpenApiUtils.ptzControl(
@@ -151,6 +194,9 @@
        if (device == null) {
            return AjaxResult.error("设备不存在");
        }
        if (!canAccessDevice(device)) {
            return AjaxResult.error("无权访问该设备");
        }
        JSONObject result;
        if (Integer.valueOf(2).equals(request.getType())) {
@@ -179,6 +225,82 @@
        return AjaxResult.success(vo);
    }
    /**
     * 设备数据访问范围
     * siteIds 为 null 表示不限站点;partnerId 非空表示仅限该合作商名下设备
     */
    private static class DeviceAuthScope {
        private final Set<Integer> siteIds;
        private final Integer partnerId;
        DeviceAuthScope(Set<Integer> siteIds, Integer partnerId) {
            this.siteIds = siteIds;
            this.partnerId = partnerId;
        }
    }
    /**
     * 解析当前登录用户可访问的设备范围(与站点管理 getSiteList 口径一致):
     * 合作商(roleType=2)仅可见自己名下设备;roleId=1 管理员不限;其他用户按 用户站点 ∪ 角色站点 过滤
     */
    private DeviceAuthScope resolveAuthScope() {
        Long userId = SecurityUtils.getUserId();
        SysUser user = sysUserClient.getSysUser(userId).getData();
        if (user == null) {
            return new DeviceAuthScope(Collections.emptySet(), null);
        }
        Integer roleType = user.getRoleType();
        Integer objectId = user.getObjectId();
        // 合作商:仅可见自己名下的设备
        if (Objects.equals(roleType, 2)) {
            return new DeviceAuthScope(null, objectId);
        }
        // 与站点管理一致:roleId != 1 视为非管理员
        R<Integer> admin = sysUserClient.isAdmin(userId);
        if (admin != null && admin.getData() != null && admin.getData() == 1) {
            return new DeviceAuthScope(null, null);
        }
        return new DeviceAuthScope(getAssignedSiteIds(user.getUserId()), null);
    }
    private Set<Integer> getAssignedSiteIds(Long userId) {
        Set<Integer> siteIds = new HashSet<>();
        if (userId == null) {
            return siteIds;
        }
        R<List<Integer>> userSiteResult = userSiteClient.getSiteIds(userId);
        if (userSiteResult != null && userSiteResult.getData() != null) {
            siteIds.addAll(userSiteResult.getData());
        }
        R<List<SysUserRoleVo>> roleResult = sysUserRoleClient.getRoleByUserId(userId);
        if (roleResult != null && roleResult.getData() != null) {
            for (SysUserRoleVo role : roleResult.getData()) {
                if (role == null || role.getRoleId() == null) {
                    continue;
                }
                R<List<Integer>> roleSiteResult = roleSiteClient.getSiteIds(role.getRoleId());
                if (roleSiteResult != null && roleSiteResult.getData() != null) {
                    siteIds.addAll(roleSiteResult.getData());
                }
            }
        }
        return siteIds;
    }
    private boolean canAccessDevice(TDevice device) {
        if (device == null) {
            return false;
        }
        DeviceAuthScope scope = resolveAuthScope();
        if (scope.partnerId != null) {
            return Objects.equals(device.getPartnerId(), scope.partnerId);
        }
        if (scope.siteIds == null) {
            return true; // 管理员
        }
        return device.getSiteId() != null && scope.siteIds.contains(device.getSiteId());
    }
    private TDevice getDevice(Integer id) {
        if (id == null) {
            return null;