api의 접근 제한

YJS·2023년 10월 12일
0

Spring Boot 탐구

목록 보기
5/11

😖문제 상황

프론트에서 next.js를 활용해서 example.com/object/{objectType}/{objectId} 구조로 url을 만들었는데 objectType과 objectId가 일치하지 않아도 접근이 가능하다는 이슈가 생겼다. 따라서 objectType에 아무 글자나 입력 후에 objectId만 맞게 입력하면 api에서 정보를 내려주고 있었다.

문제 코드 )

// controller
@GetMapping("/{objectType}/{objectId}")
public ObjectResponse loadObject(@PathVariable(name = "objectId")long objectId) {
        return objectService.loadObject(objectId);
    }
    
//service
public ObjectResponse loadObject(long id){
        Object object = objectRepository.findByIdAndObjectType(id,type).orElseThrow(() -> new NoSuchElementException("존재하지 않는 오브젝트입니다."));

       ...
            }
        }
        return ObjectResponse;
    }

🧐문제의 원인 파악

문제의 원인은 오브젝트의 타입을 검사하는 로직이 아예 없다는 것이었다. 프론트에서 api를 호출할때 오브젝트의 타입을 넘겨주고 넘겨받은 타입을 백엔드에서도 확인해서 해당 오브젝트의 id와 타입이 일치하는지를 확인해서 에러처리를 해주어야하는데 id만 확인하고 있었기 때문에 타입의 존재 여부와는 관계없이 id만 맞으면 정보를 내려주고 있었다.

🤓문제 해결 과정

step1. 프론트에서 api를 호출할때 objectType을 넘겨준다. 컨트롤러에서 pathVariable로 objectType을 받는다.

@GetMapping("/{objectType}/{objectId}")
public ObjectResponse loadObject(@PathVariable(name = "objectId")long objectId, @PathVariable(name = "objectType") String objectType) {
        return objectService.loadObject(objectId, objectType);
    }

step2. 서비스에서 objectType을 받는다. 이때 url의 objectType은 소문자이지만 백엔드에서는 enum으로 되어 있기 때문에 소문자로된 objectType을 대문자로 바꿔준다.

public ObjectResponse loadObject(long id, String objectType){
            type =ObjectType.valueOf(objectType.toUpperCase()) ;
}
       

step3. objectType과 id의 매칭을 확인하고 없다면 예외처리를 해준다.

public ObjectResponse loadObject(long id, String objectType){
 ObjectType type = null;
        try {
            type =ObjectType.valueOf(objectType.toUpperCase()) ;
        } catch (IllegalArgumentException e) {
            throw new NoSuchElementException("존재하지 않는 타입입니다.");
        }
        Object object = objectRepository.findByIdAndObjectType(id,type).orElseThrow(() -> new NoSuchElementException("존재하지 않는 오브젝트입니다."));

해결 코드)

// controller
@GetMapping("/{objectType}/{objectId}")
public ObjectResponse loadObject(@PathVariable(name = "objectId")long objectId, @PathVariable(name = "objectType") String objectType) {
        return objectService.loadObject(objectId, objectType);
    }
    
//service
public ObjectResponse loadObject(long id, String objectType){
        ObjectType type = null;
        try {
            type =ObjectType.valueOf(objectType.toUpperCase()) ;
        } catch (IllegalArgumentException e) {
            throw new NoSuchElementException("존재하지 않는 타입입니다.");
        }
        Object object = objectRepository.findByIdAndObjectType(id,type).orElseThrow(() -> new NoSuchElementException("존재하지 않는 오브젝트입니다."));

       ...
            }
        }
        return ObjectResponse;
    }



profile
우당탕탕 개발 일기

0개의 댓글