Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/88.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用JPA和Hibernate防止SQL注入?_Java_Sql_Hibernate_Jpa_Sql Injection - Fatal编程技术网

Java 如何使用JPA和Hibernate防止SQL注入?

Java 如何使用JPA和Hibernate防止SQL注入?,java,sql,hibernate,jpa,sql-injection,Java,Sql,Hibernate,Jpa,Sql Injection,我正在使用hibernate开发一个应用程序。当我尝试创建登录页面时,就会出现Sql注入的问题。 我有以下代码: @Component @Transactional(propagation = Propagation.SUPPORTS) public class LoginInfoDAOImpl implements LoginInfoDAO{ @Autowired private SessionFactory sessionFactory; @Override public Lo

我正在使用hibernate开发一个应用程序。当我尝试创建登录页面时,就会出现Sql注入的问题。 我有以下代码:

@Component
@Transactional(propagation = Propagation.SUPPORTS)
public class LoginInfoDAOImpl implements LoginInfoDAO{

@Autowired
private SessionFactory sessionFactory;      
@Override
public LoginInfo getLoginInfo(String userName,String password){
    List<LoginInfo> loginList = sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName='"+userName+"' and password='"+password+"'").list();
    if(loginList!=null )
        return loginList.get(0);
    else return null;   
          }
      }
Query q=sessionFactory.getCurrentSession().createQuery(“来自LoginInfo,其中userName=:name”);
q、 setParameter(“名称”,用户名);
List loginList=q.List();

您还有其他选择,请参见mkyong的这篇文章。

我们应该始终尝试使用存储过程来防止SQLInjection。。如果无法执行存储过程;我们应该尝试准备语句。

您需要使用命名参数来避免sql注入。另外(与sql注入无关,但通常与安全性有关)不返回第一个结果,而是使用getSingleResult,因此如果出于某种原因存在多个结果,查询将失败,并出现UnuniqueresultException,登录将不成功

 Query query= sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName=:userName  and password= :password");
 query.setParameter("username", userName);
 query.setParameter("password", password);
 LoginInfo loginList = (LoginInfo)query.getSingleResult();
什么是SQL注入? 当恶意攻击者可以操纵查询时,就会发生SQL注入 构建过程,以便他可以执行不同于 应用程序开发人员最初的意图

如何防止SQL注入攻击 解决方案非常简单和直接。您只需确保始终使用绑定参数:

public PostComment getPostCommentByReview(String review) {
    return doInJPA(entityManager -> {
        return entityManager.createQuery(
            "select p " +
            "from PostComment p " +
            "where p.review = :review", PostComment.class)
        .setParameter("review", review)
        .getSingleResult();
    });
}
现在,如果有人试图破解这个查询:

getPostCommentByReview("1 AND 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) )");
将防止SQL注入攻击:

Time:1, Query:["select postcommen0_.id as id1_1_, postcommen0_.post_id as post_id3_1_, postcommen0_.review as review2_1_ from post_comment postcommen0_ where postcommen0_.review=?"], Params:[(1 AND 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) ))]
JPQL注入 使用JPQL或HQL查询时也可能发生SQL注入,如下例所示:

public List<Post> getPostsByTitle(String title) {
    return doInJPA(entityManager -> {
        return entityManager.createQuery(
            "select p " +
            "from Post p " +
            "where" +
            "   p.title = '" + title + "'", Post.class)
        .getResultList();
    });
}
动态查询 应避免使用字符串连接动态生成查询的查询:

String hql = " select e.id as id,function('getActiveUser') as name from " + domainClass.getName() + " e ";
Query query=session.createQuery(hql);
return query.list();
如果要使用动态查询,则需要改用Criteria API:

Class<Post> entityClass = Post.class;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<?> root = query.from(entityClass);
query.select(
    cb.tuple(
        root.get("id"),
        cb.function("now", Date.class)
    )
);


return entityManager.createQuery(query).getResultList();
Class entityClass=Post.Class;
CriteriaBuilder cb=entityManager.getCriteriaBuilder();
CriteriaQuery=cb.createTupleQuery();
Root=query.from(entityClass);
query.select(
元组(
root.get(“id”),
函数(“现在”,Date.class)
)
);
返回entityManager.createQuery(query.getResultList();

我想在这里添加一个特殊的SQL注入,它可以通过在搜索中使用like查询来实现

假设我们有一个查询字符串,如下所示:

create table login_info
  (user_name varchar(16) not null primary key,
  pass_word varchar(16) not null); 
queryString = queryString + " and c.name like :name";
在设置name参数时,大多数人通常会使用此参数

query.setParameter("name", "%" + name + "%");
现在,如上所述,由于TypedQuery的原因,无法注入诸如“1=1”之类的传统参数,默认情况下Hibernate将处理它

但是这里可能有特殊的SQL注入,这是因为类似的查询结构使用了下划线

下划线通配符用于恰好匹配中的一个字符 MySQL的意思是,例如,从用户喜欢的 "abc_de",;这将产生以abc开头、结束的用户输出 与de和之间正好有一个字符

现在,如果在我们的场景中,如果我们

  • name=“\u”产生名称至少为1个字母的客户
  • name=“_uu”产生名称至少为2个字母的客户
  • name=“\uuuuuuu”产生名称至少为3个字母的客户
等等

理想的解决方案:

为了缓解这种情况,我们需要用前缀转义所有下划线

___将变为\ \ \ \ \ \ \ \(相当于3个原始下划线)


同样,versa查询也会导致需要转义%的注入。

请参考此链接[1]:此外,如果您今天在2020年访问此链接,请使用spring security进行此类操作。谢谢,我们如何在查询中包含密码???@Petr Mensik,就像我包含用户名一样我同意,技术上更好,因为速度。然而,据我所知,任何语言中都没有ORM框架生成存储过程。如果他们这样做了,那就太好了。但是,由于它们不是这样,而且ORM框架提供的生产力是必不可少的,所以准备好的语句将占主导地位。在ORM中,对所有内容使用存储过程并不是那么明智。准备好的陈述应该是好的!
Class<Post> entityClass = Post.class;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<?> root = query.from(entityClass);
query.select(
    cb.tuple(
        root.get("id"),
        cb.function("now", Date.class)
    )
);


return entityManager.createQuery(query).getResultList();
queryString = queryString + " and c.name like :name";
query.setParameter("name", "%" + name + "%");