ホームページ > データベース > mysql チュートリアル > Hibernate を使用して SQL インジェクションを防ぐ方法

Hibernate を使用して SQL インジェクションを防ぐ方法

巴扎黑
リリース: 2017-07-23 11:42:48
オリジナル
3148 人が閲覧しました

コードを記述する前に、整理された String 型の Hql または SQL ステートメントを実行のためにバックグラウンドに渡します。

これは実際には非常に愚かなアプローチです。 ! ! !

例をあげてください~~

ユーザーのログイン シナリオを真似してみましょう:

一般的なアプローチは、フロント デスクによって文字列として取得されたユーザー名とパスワードをクエリ ステートメントに動的に結合し、データベースを呼び出すことです。 query ~クエリの結果が 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 where t.username=123456 and t.password=123 ;

これは通常の SQL ステートメントです。データベースにクエリを実行して、このユーザー データが存在するかどうかを確認できます。

でも!

ユーザーがパスワード入力ボックスに 123 または 1=1 を入力すると、文字列としてバックグラウンドに渡されます

SQL ステートメントは次のように結合されます: from User t where t.username= 123456 と t.password =123 または 1=1;

or 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 はプリコンパイルされません。

パラメータをバインドするには 2 つの方法があります: 位置パラメータ (クエリ文字列で使用されますか?) または 名前付きパラメータ (クエリ文字列:) で使用します

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注入基本上已经不存在了~~~~

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

以上がHibernate を使用して SQL インジェクションを防ぐ方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート