如何防止hql注入

在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)就可以了。。

关键的是防人之心不可无啊。哈。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值