You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Data JPA @Query注解的Checkmarx不当资源访问授权漏洞排查

Fixing "Improper Resource Access Authorization" in Spring Data JPA Repository

Let's tackle this Checkmarx issue step by step. The problem here is that your current approach only handles parameter validation or coarse-grained role checks, but Checkmarx is flagging a lack of resource-specific authorization—meaning you need to verify that the logged-in user actually has permission to access the data tied to the employeeId they're passing in.

Here's why your previous attempts didn't work:

  • @Valid and @Pattern only validate the format of the input (e.g., ensuring employeeId matches a regex), not whether the user is allowed to access that specific employee's data.
  • @Secured("ROLE_TEST") checks if the user has a general role, but doesn't restrict access to individual resources (any user with ROLE_TEST could query any employeeId, which is the risk Checkmarx is catching).

Solution Directions

1. Move Authorization Logic to the Service Layer (Recommended)

Repository layers should only handle data access, not business/authorization logic. Add a service layer method that first validates the user's right to access the requested employeeId, then calls the repository:

@Service
public class EmployeeAddressService {
    private final EmployeeAddressRepository addressRepo;

    public EmployeeAddressService(EmployeeAddressRepository addressRepo) {
        this.addressRepo = addressRepo;
    }

    public List<EmployeeAddress> getEmployeeAddresses(String employeeId, LocalDate date) {
        // Get the currently authenticated user
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        YourUserPrincipal userPrincipal = (YourUserPrincipal) auth.getPrincipal();

        // Validate authorization: either the user is accessing their own data, or is an admin
        if (!userPrincipal.getEmployeeId().equals(employeeId) && !auth.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"))) {
            throw new AccessDeniedException("You are not authorized to access this employee's data");
        }

        // Proceed with the repository call only if authorized
        return addressRepo.findEmployeeAddressByEmployeeId(employeeId, date);
    }
}

2. Use Spring Security's @PreAuthorize for Fine-Grained Checks

Instead of manual validation, use Spring Security's method-level security with SpEL expressions to enforce resource-specific access directly in the service layer:

@Service
public class EmployeeAddressService {
    private final EmployeeAddressRepository addressRepo;

    public EmployeeAddressService(EmployeeAddressRepository addressRepo) {
        this.addressRepo = addressRepo;
    }

    // Allow access only if the employeeId matches the logged-in user's ID, or user is an admin
    @PreAuthorize("#employeeId == authentication.principal.employeeId or hasRole('ADMIN')")
    public List<EmployeeAddress> getEmployeeAddresses(String employeeId, LocalDate date) {
        return addressRepo.findEmployeeAddressByEmployeeId(employeeId, date);
    }
}

Make sure you have @EnableGlobalMethodSecurity(prePostEnabled = true) in your Spring Security configuration to enable @PreAuthorize.

3. Eliminate External employeeId Input (Most Secure)

If users should only ever access their own address data, remove the employeeId parameter entirely and fetch it directly from the authenticated user in the repository query:

@Repository
public interface EmployeeAddressRepository extends JpaRepository<EmployeeAddress, Integer> {
    @Query("select empAdd from EmployeeAddress empAdd " +
           "where empAdd.Employee.employeeId = ?#{authentication.principal.employeeId} " +
           "and endDate > ?1 " + // Fixed your original query's syntax issue here
           "ORDER BY empAdd.lastUpdateTimeStamp DESC")
    List<EmployeeAddress> findOwnEmployeeAddress(LocalDate date) throws PersistenceException;
}

This way, there's no way for a user to pass someone else's employeeId—the query automatically uses the logged-in user's ID, eliminating the authorization risk entirely.

4. Ensure Checkmarx Recognizes Your Authorization Logic

Checkmarx relies on detecting explicit authorization checks before data access. Make sure your validation logic is:

  • Explicit (no hidden checks in utility classes that Checkmarx can't trace)
  • Tied directly to the resource being accessed (the employeeId in this case)
  • Throws a clear access denied exception if validation fails

内容的提问来源于stack exchange,提问作者Gautam

火山引擎 最新活动