hql注入を防止する方法
sshフレームワークではhqlクエリが頻繁に使用され、jdbcプログラミングと同様にhql注入を防止する必要があります.hql注入とは、フォームに「'」や「or」などのsql構文の保留字や文法記号を入力し、よく使われる検証を巧みに避ける手段にすぎない.
通常の解決策は、ダイナミックパラメータの設定です.具体的な方法は次のとおりです.
まずhqlを組み立てます.「?」で変数値の代わりに.次にhibernateにパラメータ値を動的に注入します.表現が難しい.やはりコードを貼りましょう.
上のコードの考え方は、まずhql列を組み立てる時間をすべて「?」代替変数.変数値をlistに同時に読み込みます.本来は配列が要求される(後述dao層の実現)が,配列長が動的に増大しないためlistで最後に変換する.
ここで注意しなければならないのは、一般的にhqlに直接スペルするには、変数に単一引用符を付ける必要があります.ただしパラメータリストには追加できません.hibernateは私たちのために自動的に追加します.これがhql注入を防ぐための鍵かもしれないと思います.
以下を理解しやすいように,最後のコア実装コードを貼り付ける.
もちろん、ページを分けなければ、そのマルチコードを書く必要はありません.getHibernateTemplate()を直接使います.find(String queryString,Object[]values)でいいです.
肝心なのは人の心を防ぐことだ.はあ...
通常の解決策は、ダイナミックパラメータの設定です.具体的な方法は次のとおりです.
まずhqlを組み立てます.「?」で変数値の代わりに.次にhibernateにパラメータ値を動的に注入します.表現が難しい.やはりコードを貼りましょう.
/**
* hql
* @param form
* @param pageNo
* @param pageSize
*/
public Page pageByHql(TeamForm form, int pageNo, int pageSize){
String teamCode = form.getTeamCode();
String teamName = form.getTeamName();
String principal = form.getTeamPrincipal();
String eventCode = form.getSecondType();
if(StringUtils.isEmpty(eventCode))
eventCode = form.getFirstType(); // ,
//
StringBuffer hql = new StringBuffer("select distinct c from Team c ");
List params = new ArrayList();
if(eventCode!=null && !eventCode.equals(""))
hql.append(",PreEventTypeRes p ");
hql.append(" where 1=1 ");
if(teamCode!=null && !teamCode.equals("")){
hql.append(" and c.teamCode like ?");
params.add("%"+teamCode+"%");
}
if(teamName!=null && !teamName.equals("")){
hql.append(" and c.teamName like ?");
params.add("%"+teamName+"%");
}
if(principal!=null && !principal.equals("")){
hql.append(" and c.teamPrincipal like ?");
params.add("%"+principal+"%");
}
if(eventCode!=null && !eventCode.equals("")){
hql.append(" and c.teamId=p.resId and p.eventTypeCode like ?");
params.add("%"+eventCode+"%");
}
hql.append(" and c.delSign!='1' ");
hql.append(" order by c.teamCode asc");
return teamDao.findPageByHQL(hql.toString(), pageNo, pageSize,params.toArray());
}
上のコードの考え方は、まずhql列を組み立てる時間をすべて「?」代替変数.変数値をlistに同時に読み込みます.本来は配列が要求される(後述dao層の実現)が,配列長が動的に増大しないためlistで最後に変換する.
ここで注意しなければならないのは、一般的にhqlに直接スペルするには、変数に単一引用符を付ける必要があります.ただしパラメータリストには追加できません.hibernateは私たちのために自動的に追加します.これがhql注入を防ぐための鍵かもしれないと思います.
以下を理解しやすいように,最後のコア実装コードを貼り付ける.
/**
* <ol>
* <li> 。 。
* </ol>
*
* @param queryString
* final String -
* @param currentPage
* final int -
* @param rows
* final int -
* @return -
*/
protected List findPageListByHQL(final String queryString, final int currentPage, final int rows, final Object[] params) throws DAOException {
try {
return getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException {
Query q = session.createQuery(queryString);
//
if (params != null){
for (int i = 0; i < params.length; i++) {
q.setParameter(i, params[i]);
}
}
if (currentPage > -1) {
q.setFirstResult((currentPage - 1) * rows);
}
if (rows > -1) {
q.setMaxResults(rows);
}
List list = q.list();
if (list == null) {
list = Collections.EMPTY_LIST;
}
return list;
}
});
} catch (DataAccessException e) {
logger.error(e.getMessage(), e);
throw new DAOException(e);
}
}
もちろん、ページを分けなければ、そのマルチコードを書く必要はありません.getHibernateTemplate()を直接使います.find(String queryString,Object[]values)でいいです.
肝心なのは人の心を防ぐことだ.はあ...