六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 61|回复: 0

如何防止hql注入

[复制链接]

升级  0%

54

主题

54

主题

54

主题

举人

Rank: 3Rank: 3

积分
200
 楼主| 发表于 2013-1-27 05:01:26 | 显示全部楼层 |阅读模式
在ssh框架下会经常用到hql查询,和jdbc编程一样我们也需防止hql注入。所谓的hql注入,总结起来就是利用表单输入“'”以及“or”等sql语法的保留字或语法符号,来巧妙的避开常用的验证的手段而已。

  通常的解决办法就是进行动态参数设置。具体做法是:
先将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里总要对变量加上单引号。但在参数list里不能加。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)就可以了。。
  
  关键的是防人之心不可无啊。哈。。。
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表