fix: Override vulnerability #1050

This commit is contained in:
tjq 2025-01-21 23:52:35 +08:00
parent c32b2abe0d
commit a406602b09
3 changed files with 72 additions and 26 deletions

View File

@ -0,0 +1,20 @@
package tech.powerjob.server.auth.common.utils;
import javax.servlet.http.HttpServletRequest;
/**
* 获取常用的请求头
*
* @author tjq
* @since 2025/1/21
*/
public class HttpHeaderUtils {
public static String fetchAppId(HttpServletRequest request) {
return HttpServletUtils.fetchFromHeader("AppId", request);
}
public static String fetchNamespaceId(HttpServletRequest request) {
return HttpServletUtils.fetchFromHeader("NamespaceId", request);
}
}

View File

@ -7,15 +7,15 @@ import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.common.exception.ImpossibleException;
import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.server.auth.LoginUserHolder;
import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.PowerJobUser;
import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.server.auth.common.PowerJobAuthException;
import tech.powerjob.server.auth.common.utils.HttpServletUtils;
import tech.powerjob.server.auth.common.utils.HttpHeaderUtils;
import tech.powerjob.server.auth.service.login.PowerJobLoginService;
import tech.powerjob.server.auth.service.permission.PowerJobPermissionService;
import tech.powerjob.server.common.Loggers;
@ -74,14 +74,14 @@ public class PowerJobAuthInterceptor implements HandlerInterceptor {
if (RoleScope.NAMESPACE.equals(roleScope)) {
final String namespaceIdStr = HttpServletUtils.fetchFromHeader("NamespaceId", request);
final String namespaceIdStr = HttpHeaderUtils.fetchNamespaceId(request);
if (StringUtils.isNotEmpty(namespaceIdStr)) {
targetId = Long.valueOf(namespaceIdStr);
}
}
if (RoleScope.APP.equals(roleScope)) {
final String appIdStr = HttpServletUtils.fetchFromHeader("AppId", request);
final String appIdStr = HttpHeaderUtils.fetchAppId(request);
if (StringUtils.isNotEmpty(appIdStr)) {
targetId = Long.valueOf(appIdStr);
}

View File

@ -1,26 +1,30 @@
package tech.powerjob.server.web.controller;
import org.apache.commons.lang3.StringUtils;
import tech.powerjob.common.request.http.SaveJobInfoRequest;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.common.enums.SwitchableStatus;
import tech.powerjob.server.persistence.PageResult;
import tech.powerjob.server.persistence.remote.model.JobInfoDO;
import tech.powerjob.server.persistence.remote.repository.JobInfoRepository;
import tech.powerjob.server.core.service.JobService;
import tech.powerjob.server.web.request.QueryJobInfoRequest;
import tech.powerjob.server.web.response.JobInfoVO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;
import tech.powerjob.common.enums.ErrorCodes;
import tech.powerjob.common.enums.SwitchableStatus;
import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.request.http.SaveJobInfoRequest;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.server.auth.Permission;
import tech.powerjob.server.auth.RoleScope;
import tech.powerjob.server.auth.common.utils.HttpHeaderUtils;
import tech.powerjob.server.auth.interceptor.ApiPermission;
import tech.powerjob.server.core.service.JobService;
import tech.powerjob.server.persistence.PageResult;
import tech.powerjob.server.persistence.remote.model.JobInfoDO;
import tech.powerjob.server.persistence.remote.repository.JobInfoRepository;
import tech.powerjob.server.web.request.QueryJobInfoRequest;
import tech.powerjob.server.web.response.JobInfoVO;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@ -43,46 +47,55 @@ public class JobController {
@PostMapping("/save")
@ApiPermission(name = "Job-Save", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> saveJobInfo(@RequestBody SaveJobInfoRequest request) {
public ResultDTO<Void> saveJobInfo(@RequestBody SaveJobInfoRequest request, HttpServletRequest hsr) {
request.setAppId(Long.valueOf(HttpHeaderUtils.fetchAppId(hsr)));
jobService.saveJob(request);
return ResultDTO.success(null);
}
@PostMapping("/copy")
@ApiPermission(name = "Job-Copy", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<JobInfoVO> copyJob(String jobId) {
public ResultDTO<JobInfoVO> copyJob(String jobId, HttpServletRequest hsr) {
preCheck(jobId, hsr);
return ResultDTO.success(JobInfoVO.from(jobService.copyJob(Long.valueOf(jobId))));
}
@GetMapping("/export")
@ApiPermission(name = "Job-Export", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<SaveJobInfoRequest> exportJob(String jobId) {
public ResultDTO<SaveJobInfoRequest> exportJob(String jobId, HttpServletRequest hsr) {
preCheck(jobId, hsr);
return ResultDTO.success(jobService.exportJob(Long.valueOf(jobId)));
}
@GetMapping("/disable")
@ApiPermission(name = "Job-Disable", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> disableJob(String jobId) {
public ResultDTO<Void> disableJob(String jobId, HttpServletRequest hsr) {
preCheck(jobId, hsr);
jobService.disableJob(Long.valueOf(jobId));
return ResultDTO.success(null);
}
@GetMapping("/delete")
@ApiPermission(name = "Job-Delete", roleScope = RoleScope.APP, requiredPermission = Permission.WRITE)
public ResultDTO<Void> deleteJob(String jobId) {
public ResultDTO<Void> deleteJob(String jobId, HttpServletRequest hsr) {
preCheck(jobId, hsr);
jobService.deleteJob(Long.valueOf(jobId));
return ResultDTO.success(null);
}
@GetMapping("/run")
@ApiPermission(name = "Job-Copy", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Long> runImmediately(String appId, String jobId, @RequestParam(required = false) String instanceParams) {
@ApiPermission(name = "Job-Run", roleScope = RoleScope.APP, requiredPermission = Permission.OPS)
public ResultDTO<Long> runImmediately(String appId, String jobId, @RequestParam(required = false) String instanceParams, HttpServletRequest hsr) {
preCheck(jobId, hsr);
return ResultDTO.success(jobService.runJob(Long.valueOf(appId), Long.valueOf(jobId), instanceParams, 0L));
}
@PostMapping("/list")
@ApiPermission(name = "Job-Copy", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<PageResult<JobInfoVO>> listJobs(@RequestBody QueryJobInfoRequest request) {
@ApiPermission(name = "Job-List", roleScope = RoleScope.APP, requiredPermission = Permission.READ)
public ResultDTO<PageResult<JobInfoVO>> listJobs(@RequestBody QueryJobInfoRequest request, HttpServletRequest hsr) {
String targetAppId = HttpHeaderUtils.fetchAppId(hsr);
request.setAppId(Long.valueOf(targetAppId));
Sort sort = Sort.by(Sort.Direction.ASC, "id");
PageRequest pageRequest = PageRequest.of(request.getIndex(), request.getPageSize(), sort);
@ -128,6 +141,19 @@ public class JobController {
return ResultDTO.success(convertPage(jobInfoPage));
}
private void preCheck(String jobId, HttpServletRequest hsr) {
Long appId = Long.valueOf(HttpHeaderUtils.fetchAppId(hsr));
Optional<JobInfoDO> jobInfoOpt = jobInfoRepository.findById(Long.valueOf(jobId));
if (!jobInfoOpt.isPresent()) {
throw new PowerJobException(ErrorCodes.ILLEGAL_ARGS_ERROR, "JobNotExist");
}
JobInfoDO jobInfoDO = jobInfoOpt.get();
if (!jobInfoDO.getAppId().equals(appId)) {
throw new PowerJobException(ErrorCodes.INVALID_REQUEST, String.format("AppIdNotMatch(%d!=%d)", jobInfoDO.getAppId(), appId));
}
}
private static PageResult<JobInfoVO> convertPage(Page<JobInfoDO> jobInfoPage) {
List<JobInfoVO> jobInfoVOList = jobInfoPage.getContent().stream().map(JobInfoVO::from).collect(Collectors.toList());