mybatiss를 사용할 경우 ${param}, #{param}과 같이 # 또는 $으로 parameter를 받을 수 있는데, 보통 아래와 같이 #을 사용해서 받는 것을 권장합니다. 그 이유는, #{}이 SQL Injection 공격에 안전하기 때문인데요
SELECT *
FROM TB_USER
WHERE USER_ID = #{userId}
#이 SQL Injection에 안전한 이유는, #이 내부적으로 PreparedStatement를 사용하기 때문입니다. PreparedStatement는 값을 binding 하는 시점에 전달된 값에 대한 특수 문자, 쿼리 등을 필터링하여 SQL Injection을 막습니다.
하지만 ${}를 부득이하게 사용해야 할 경우가 있습니다. 제가 다니는 회사를 예로 들면, 고객사가 스키마명을 변경해 달라고 하는 경우가 있는데 이 경우 모든 쿼리를 수정할 수 없기 때문에 어쩔 수 없이 $를 사용합니다.
문제는, $을 사용하면 mybatis에서 SQL Injection을 막아 줄 수 없다는 것인데요.
이런 경우 java에서 SQL Injection 방어 코딩을 해야 하는데, 너무 번거로워 라이브러리를 찾아봤습니다.
바로 github.com/rkpunjal/sql-injection-safe/ 라이브러리입니다.
이 라이브러리는 VO의 필드에 Annotaion을 사용하여 SQL Injection을 방어하는 방법입니다.
사용방법은 간단합니다.
먼저, pom.xml에 아래와 같이 dependency를 추가합니다.
<dependency>
<groupId>com.github.rkpunjal.sqlsafe</groupId>
<artifactId>sql-injection-safe</artifactId>
<version>1.0.2</version>
</dependency>
이 다음에 아래와 같이 VO의 컬럼에 @SQLInjectionSafe를 추가합니다.
public class UserVo {
private @SQLInjectionSafe String userId;
private @SQLInjectionSafe String userName;
// getter, setter 생략
}
그리고, 아래와 같이 스프링 컨트롤러에 전달되는 parameter에 @Valid를 추가하여 SQL Injection을 방어할 수 있습니다.
@RequestMapping(value = "/insertUser")
public @ResponseBody String insertUser(@Valid UserVo userVo) {
// todo
}
여기까지 진행했다면, SQL Injection의 위험이 되는 문자가 있는 경우 BindException이 발생합니다.
'웹 개발' 카테고리의 다른 글
[netty] too many open files (0) | 2020.11.22 |
---|---|
spring boot jar 외부에서 properties 파일을 읽는 방법 (0) | 2020.11.22 |
NPE(Null Pointer Exception)으로부터 안전한 프로그래밍 하기 (1) | 2020.11.08 |
Spring lazy Initialization (0) | 2020.10.13 |
javascript ajax 크로스 도메인 요청하기(CORS) (0) | 2020.09.30 |