안녕하세요. 이번 시간에는 sqlalchemy에서 like 연산자를 쓰는 방법을 알아보겠습니다. 하나 조심해야 할 것은, 당연하게도 유저의 입력값을 믿으면 안 된다인데요. 이게 무슨 소리일까 싶습니다. like의 경우 %와 _ 등으로 인해 의도치 않은 결과가 나올 수 있습니다. 입력값 필터링을 하지 않거나 escaping을 하지 않은 경우 문제가 발생할 수도 있다는 의미입니다.
먼저 실습에 사용할 데이터입니다. 테이블 A에는 title이 aa, ba, _a, %a인 것이 있습니다.
그리고 models.py에 정의된 모델 A에 대한 클래스입니다.
저는 like 연산자를 썼습니다. Query parameter로 들어오는 keyword에 대해, 접두어가 keyword인 title을 찾습니다. 무엇이 문제일까요? 정확히 말하면 f"{keyword}%"가 문제입니다. 입력값 필터링을 하지 않고 사용자의 입력을 믿어버리면 절대로 안 됩니다. keyword가 특정한 문자가 들어오지 않는다면 의도대로 동작이 할 겁니다. 예를 들어, keyword에 a를 넣어보겠습니다.
a로 시작하는 "aa"만 나옵니다.
문제는 _a인데요. 저 경우 where title like '_a%'로 rendering이 되어 버립니다. like에서 _는 어떠한 character와도 매칭됩니다. 따라서, "aa", "ba", "_a", "%a" 이렇게 4개가 매치되게 됩니다. 당연하게도 %a를 넣어도 의도치 못한 결과가 나오게 됩니다. 왜 그럴까요? 2가지 이유가 있습니다. 유저 입력을 그대로 믿어버린 것. 그리고 특정한 문자가 escaping이 되지 않은 것입니다.
어떻게 해야 할까요? 접두 검색의 경우, startswith를 쓰면 됩니다. 그리고 autoescape를 True로 설정하면 됩니다.
이 프로그램을 보겠습니다. A.title.startswith(keyword, autoescape=True)라고 되어 있네요.
그러면 _a로 시작하는 결과만 나옵니다. 이는 _가 어떠한 하나의 캐릭터와 매치되는 특수 문자가 아니라, 다른 것으로 랜더링 되어 버렸기 때문입니다. 그리고 %와 _가 나오는 곳에 앞에 /가 붙습니다. 즉, %와 _가 escaping 됩니다. 이는 문서에도 언급되어 있는 부분입니다.
쿼리를 출력해 보겠습니다. 그러면 Like :title_1 || '%' escape '/'가 나오네요. 사실 title에 그대로 %가 남아 있었으면 _a만 출력되지않았을 겁니다. 이 말은, 문서에서 언급한 대로 특정한 문자들이 LIKE 쿼리 안에서 escape가 된 상태로 render가 된다는 의미입니다. 접미 검사는 어떻게 하면 될까요?
비슷한 원리로, endswith를 쓰면 됩니다. autoescape를 True로 startswith와 마찬가지로, LIKE 안에 들어가는 param 부분에 포함되어 있는 %와 _를 escaping 하게 됩니다.
어떠한 string이 포함되었는지 검사하기 위해서는 contains를 쓰면 됩니다.
'웹 > FASTAPI' 카테고리의 다른 글
fastapi celery로 간단하게 특정 시간마다 task가 실행되는 schedular를 만들어 봅시다. (0) | 2023.06.17 |
---|---|
fastapi sub application에 대해 알아보고 app마다 다른 middleware를 적용해 봅시다. (0) | 2023.06.13 |
fastapi pydantic 필드 단위로 동작하는 validator를 간단하게 알아봅시다 (0) | 2023.06.09 |
fastapi pydantic root validator를 알아봅시다. (1) | 2023.06.06 |
fastapi alembic revision 명령어를 쓸 때 마이그레이션 버전을 커스텀하게 생성해 봅시다. (0) | 2023.05.31 |
최근댓글