자바 개발 노트 (149) 도입 예비 보고서 의 장점

앞에서 각종 SQL 문장의 호출 과정 을 소개 했다. 예 코드 는 모든 SQL 문자열 을 죽 였 지만 조회 조건 을 방법 매개 변수 로 전달 할 수 있다.예 를 들 어 현재 특정한 과정의 교사 기록 을 삭제 하려 면 삭제 방법 을 작성 할 때 과정 이름 을 이 방법의 입력 매개 변수 로 합 니 다.이에 따라 작 성 된 방법 코드 예 시 는 다음 과 같다.
	//     
	private static void deleteRecord(Statement stmt, String course) throws SQLException {
		String sql = String.format("delete from teacher where course='%s'", course);
		int count = stmt.executeUpdate(sql); //       
		System.out.println("    SQL  :"+sql);
		System.out.println("            "+count);
	}

 
이 어 외부 에 서 는 위의 deleteRecord 방법 을 호출 하려 고 합 니 다. 두 번 째 과정 매개 변 수 는 '화학' 을 작성 하여 모든 화학 선생님 의 기록 을 삭제 하 기 를 원 합 니 다. 호출 코드 는 다음 과 같 습 니 다.
			deleteRecord(stmt, "  "); //     

 
상기 코드 를 포함 하 는 테스트 프로그램 을 실행 하고 아래 의 출력 로 그 를 관찰 합 니 다.
    SQL  :delete from teacher where course='  '
            1

로그 정 보 를 보면 화학 선생님 의 기록 만 삭제 하 는 것 이 모든 것 이 정상 인 것 처럼 보인다.그러나 과정 매개 변 수 는 외부 에서 들 어 오 는데 과정 문자열 이 무엇 인지 누가 알 겠 는가?만약 누군가가 한가 해서 당황 하면 키보드 에서 마음대로 몇 글 자 를 잃 었 다. 'or' 1 '=' 1 '과 같은 문자열 을 수업 이름 으로 삼 았 다.그래서 삭제 방법의 호출 코드 는 다음 과 같 습 니 다.
			deleteRecord(stmt, "' or '1'='1"); //     

 
테스트 프로그램 을 다시 실행 하 니 출력 로그 가 잘못 되 었 습 니 다:
    SQL  :delete from teacher where course='' or '1'='1'
            4

 
함부로 진 몇 글자 가 SQL 문 구 를 실행 시 킬 줄 은 몰 랐 고 teacher 표 의 나머지 기록 을 깨끗이 지 웠 다.이 건 큰일 이 야. 원래 문장의 형식 은 분명히 특정 과정의 기록 만 삭제 하려 고 하 는데 왜 집행 결과 가 크게 다 르 지?이 유 는 실 행 될 SQL 문 구 를 딱딱 하 게 과정 문자열 을 그대로 채 워 서 'or' 1 '=' 1 '이라는 극단 적 인 조건 이 생 겼 기 때 문 입 니 다. 자 연 스 럽 게 MySQL 은 teacher 표를 충 실 히 삭 제 했 습 니 다.이와 같은 SQL 결함 은 SQL 에 구멍 을 주입 한다 고 하 는데 해커 들 이 원 하 는 대로 이용 되 어 큰 손실 을 초래한다.상기 실험 결 과 는 보고 체제 의 안전 문 제 를 드 러 냈 고 조건 파라미터 가 악의 적 으로 변경 되면 예상 치 못 한 심각 한 상황 이 발생 할 수 있다.이 를 위해 JDBC 는 또 다른 예비 보고 체 제 를 설계 했다. 예비 보고 서 는 새로운 종류의 Prepared Statement 을 정의 했다. 원 보고서 Statement 과 달리 예비 보고 대상 을 만 들 때 SQL 문 구 를 설정 하고 SQL 안의 동적 인 파 라 메 터 는 물음표 로 대체 해 야 한다.그리고 executeUpdate 나 executeQuery 를 호출 하기 전에 미리 보고 대상 의 setString 방법 을 호출 하여 해당 번호 의 매개 변수 값 을 설정 합 니 다.다음은 예비 보고 서 를 도입 한 데이터베이스 작업 코드 예 입 니 다.
	//         
	private static void testPreparedStatement() {
		String sql = "delete from teacher where course=?";
		//          ,         
		try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
				PreparedStatement stmt = conn.prepareStatement(sql)) {
			//stmt.setString(1, "  "); //           
			stmt.setString(1, "'' or 1=1"); //           
			int count = stmt.executeUpdate(); //       
			System.out.println("     SQL  :"+stmt.toString());
			System.out.println("            "+count);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

 
여전히 이전의 악성 문자열 을 예 로 들 면, 위의 코드 는 setString 방법 을 호출 할 때 'or' 1 '=' 1 '을 입력 하여 계속 흐 린 물 속 에서 물고 기 를 만 지 려 고 한다.test Prepared Statement 방법 을 포함 하 는 테스트 프로그램 을 실행 합 니 다. 관찰 한 로그 정 보 는 다음 과 같 습 니 다.
     SQL  :com.mysql.cj.jdbc.ClientPreparedStatement: delete from teacher where course='\'\' or 1=1'
            0

 
로그 결과 에 따 르 면 이번 교란 행 위 는 이 루어 지지 않 았 고 기록 하나 도 삭제 되 지 않 았 다.이 때 조건 문 구 를 'course =' \ '\' or 1 = 1 '로 바 꾸 는 것 을 주의 하 십시오. 문자열 에 있 는 작은 따옴표 가 전의 되 어 전의 후의 조건 문 형식 이 정확 하지 않 고 SQL 을 성공 적 으로 수행 하지 못 한 것 이 분명 합 니 다.이 를 통 해 예비 보고 Prepared Statement 은 데이터 베이스 작업 의 안전성 을 향상 시 켰 음 을 증명 한다. 동적 으로 매개 변 수 를 입력 해 야 하 는 SQL 문 구 는 예비 보고 체 제 를 통 해 처리 하 는 것 이 가장 좋다.
더 많은 자바 기술 문장 은 《 자바 개발 노트 (순서) 장절 디 렉 터 리 》 를 참조한다.

좋은 웹페이지 즐겨찾기