> 데이터 베이스 > MySQL 튜토리얼 > SQL 주입을 방지하기 위해 Hibernate를 사용하는 방법

SQL 주입을 방지하기 위해 Hibernate를 사용하는 방법

巴扎黑
풀어 주다: 2017-07-23 11:42:48
원래의
3141명이 탐색했습니다.

코드를 작성하기 전에 정리된 String 유형의 Hql 또는 Sql 문을 백그라운드로 전달하여 실행하세요.

이것은 실제로 매우 어리석은 접근 방식입니다! ! ! !

예를 들어보세요~~

사용자 로그인 시나리오를 모방해 보겠습니다.

일반적인 접근 방식은 프런트 데스크에서 얻은 사용자 이름과 비밀번호를 문자열로 쿼리 문에 동적으로 연결한 다음 데이터베이스를 호출하는 것입니다. 쿼리 ~ 쿼리 결과가 null이 아니면 사용자가 존재하고 로그인에 성공한 것이며, 그렇지 않으면 로그인이 실패한다는 의미입니다!

일반적으로 사용자는 계좌번호 123456과 비밀번호 123을 입력합니다. (비밀번호가 틀리거나 사용자가 전혀 존재하지 않는다고 가정)

usernameString//前台输入的用户名passwordString//前台输入的密码//hql语句String queryString = "from User t where t.username= " + usernameString + " and  t.password="+ passwordString;//执行查询List result = session.createQuery(queryString).list();
로그인 후 복사

사용자가 정상적으로 입력하면 sql 명령문은 다음과 같이 연결됩니다: from User t 여기서 t.username=123456 및 t.password=123 ;

이것은 일반적인 SQL 문입니다. 데이터베이스를 쿼리하여 이 사용자 데이터가 존재하는지 확인할 수 있습니다.

하지만!

사용자가 비밀번호 입력 상자에 123 또는 1=1을 입력하면 문자열로 백그라운드로 전달됩니다.

sql 문은 다음과 같이 연결됩니다. from User t where t.username= 123456 및 t.password =123 또는 1=1;

한 번 또는 1=1이 추가되면 이 SQL은 항상 설정됩니다! ! ! 더 심각한 경우에는 데이터베이스의 테이블 삭제, 정보 변조 등이 있는데, 이는 매우 심각합니다! ! !

SQL 인젝션을 받는 이유를 설명해볼까요?

SQL 인젝션을 하는 이유는 표면적으로는 문자열을 이어붙여 SQL 문을 만드는데, SQL 문은 미리 컴파일되거나 바인딩된 변수를 사용하지 않기 때문입니다.

하지만 더 깊은 이유는 사용자가 입력한 문자열이 "sql 문"으로 실행되기 때문입니다.

예를 들어, 위의 String queryString = "from User t where t.username= " + usernameString + " and t.password="+passwordString;

우리는 사용자 이름과 비밀번호 값을 원합니다 ​​​​사용자가 입력한 문자열 리터럴과 마찬가지로 실행을 위해 데이터베이스에 전달됩니다.

그러나 다음을 입력하면 123 또는 1=1 또는 1=1은 where id=의 리터럴 값으로 사용되지 않고 SQL 문으로 실행됩니다. 따라서 그 본질은 사용자의 입력 데이터를 명령으로 실행하는 것입니다.

SQL 방어

기본적으로 모두가 SQL 문을 사용하여 변수를 미리 컴파일하고 바인딩하는 것이 SQL 주입을 방어하는 가장 좋은 방법이라는 것을 알고 있습니다. SQL 주입을 방지하려면 SQL 문을 함께 연결하지 마세요! ! !

실제 프로젝트에서는 일반적으로 ibatis, hibernate, mybatis 등 다양한 프레임워크를 사용합니다. 일반적으로 기본적으로 미리 컴파일된 SQL을 사용합니다. ibatis/mybatis의 경우 #{name} 형식을 사용하면 sql이 미리 컴파일된 것입니다. ${name}을 사용하면 sql이 미리 컴파일되지 않습니다.

매개변수를 바인딩하는 방법에는 위치 매개변수(쿼리 문자열에 사용됨) 또는 이름이 지정된 매개변수(쿼리 문자열에 사용됨:)를 사용하는 두 가지 방법이 있습니다.

hibernate는 명명된 매개변수(쿼리 문자열에 사용됨:)를 사용하는 것과 동일한 효과를 갖는 JDBC 스타일 위치 매개변수(쿼리 문자열에 사용됨)를 지원합니다.

이름이 지정된 매개변수 사용

usernameString//前台输入的用户名passwordString//前台输入的密码//hql语句String queryString = "from User t where t.username:usernameString and t.password: passwordString";//执行查询List result = session.createQuery(queryString)
                      .setString("usernameString ", usernameString )
                      .setString("passwordString", passwordString)
                      .list();
로그인 후 복사

위치 매개변수 사용

usernameString//前台输入的用户名passwordString//前台输入的密码//hql语句String queryString = "from User t where t.username=? and t.password=?";//执行查询List result = session.createQuery(queryString)
                      .setString(0, usernameString )
                      .setString(1, passwordString)
                      .list();
로그인 후 복사

两者比较:positional parameter可读性强不如named parameter的强,而且可维护性差,如果我们的查询稍微改变一点,将第一个参数和第二个参数改变一下位置,

这样我们的代码中涉及到位置的地方都要修改,所以我们强烈建议使用named parameter方式进行参数绑定。

最后,在named parameter中可能有一个参数出现多次的情况,应该怎么处理呢?

在举个栗子~~

我们模仿一下用户登录的场景:这次业务变换,有的网站,手机号可以作为用户名来登录,也能作为手机号本身登录。

常见的做法是将前台获取到的用户名or手机号和密码,作为字符串动态拼接到查询语句中,然后去调用数据库查询~查询的结果不为null就代表用户存在,则登陆成功,否则登录失败!

正常情况下用户输入账号是13812345678和密码123

这里usernameString作为手机号又作为用户名出现了两次,怎么办呢?

大家请看下面代码:

usernameString//前台输入的用户名passwordString//前台输入的密码//hql语句String queryString = "from User t where t.username:usernameString and
t.phone:usernameString and t.password: passwordString";//执行查询List result = session.createQuery(queryString)
                      .setString("usernameString ", usernameString )
                      .setString("passwordString", passwordString)
                      .list();
로그인 후 복사

在Hibernate+spring中getHibernateTemplate()返回的对象可以调用find(String queryString, Object value...Object value)来实现named parameter。比如:

usernameString//前台输入的用户名passwordString//前台输入的密码//hql语句String queryString = "from User t where t.username:usernameString and t.password: passwordString";//执行查询return getHibernateTemplate().find(queryString, usernameString, passwordString);
로그인 후 복사

 PS:其实说这么多都是扯淡,因为现在真是商业项目中,没有把密码以明文的方式存入数据库的,基本上都是经过加密以后进行比对。所以不管用户输入什么都会解密成一个字符串。所以,这种SQL注入基本上已经不存在了~~~~

所以还是建议大家在开发中,多规范一下自己的代码,让代码更加健壮!

위 내용은 SQL 주입을 방지하기 위해 Hibernate를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿