SQL注入

0、什么是SQL注入

SQL注入发生在应用程序与数据库进行交互的时候的安全漏洞。就是在输入字符串的时候注入SQL指令,在编程时不注意忽略了字符检查,俺么这些注入进去的恶意指令会被数据库服务器误认为正常的SQL指令运行,因此遭受破坏或者入侵。

举个例子

# 正常的sql语句
select * from table_name where user_name = "arvin";
​
# 如果上述的输入框输入没有拦截,语句就变成了如下形式,多了额外的"or 1=1" 到查询的语句中就是sql注入了。由于1=1永远都是成立的,即where字句总是为真。
select * from table_name where name="arvin" or 1=1;
# 实际执行效果
select * from table_name

 

1、可能出现的数据库

SQL注入可能出现在大部分数据库中,主要支持处理SQL指令的数据库服务器,都有可能受到其手段的攻击。

2、如何防止SQL注入

1、在前端表单进行参数格式控制

2、后台进行参数格式化,过滤是由涉及sql的非法字符

//参考:https://freeman983.iteye.com/blog/1153989
//过滤 '
//ORACLE 注解 --  /**/
//关键字过滤 update,delete
 
static String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
            + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
 
static Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);//表示忽略大小写
 
/***************************************************************************
 * 参数校验
 * 
 * @param str ep: "or 1=1"
 */
public static boolean isSqlValid(String str) {
    Matcher matcher = sqlPattern.matcher(str);
    if (matcher.find()) {
        System.out.println("参数存在非法字符,请确认:"+matcher.group());//获取非法字符:or
        return false;
    }
    return true;
}

 

3、持久层使用参数化的持久层

String sql= "select * from user where name=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, name);
ResultSet rs = ps.executeQuery();

3、框架中防止SQL注入

1、spring中的jdbcTemplate防止SQL注入

1、使用参数化SQL代替字符串拼接(少参)

  字符串拼接(不安全): jdbcTemplate.update("update user set age = "+age+" where uuid = "+uuid);
  
  参数化sql(安全):   jdbcTemplate.update("update user set age = ? where uuid = ?",new Object[]{age,uuid});

2、参数化,将参数进行数组打包注入(多参)

  List<Object> obj = new ArrayList<Object>();
  obj.add(name);
  obj.add(age);
  String sql = "update user set name=?,age = ? where uuid = 4";
  jdbcTemplate.update(sql,obj.toArray());

3、参数化,将参数进行map集合打包,指定参数注入(多参)

  Map<String,Object> map = new HashMap<String,Object>();
  String sql = "update user set name=:name,age =:age where uuid = 4";
  map.put("name",name);
  map.put("age",age);
  jdbcTemplate.update(sql,map);

4、参数化,使用编译语句(少参,参数为单体对象)

   String sql = "insert into user(name,age) values (?,?)";  
   jdbcTemplate.update(sql, new PreparedStatementSetter() {
      @Override
      public void setValues(PreparedStatement ps) throws SQLException {  
          ps.setString(1, "sixmonth");  
          ps.setInt(2, 18);  
   }});

5、参数化,使用预编译语句,进行批处理更新(多参,参数为对象集合)

   String sql = "insert into user(name,age) values (?,?)";  
   List<User> userList = new ArrayList<User>();//此处为测试,使用空集合
   jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
        public void setValues(PreparedStatement ps, int i) throws SQLException {
            ps.setString(1, userList.get(i).getName());
            ps.setInt(2, userList.get(i).getAge());
        }
        @Override
        public int getBatchSize() {
            return userList.size();
        }
    });

2、mybatis防止SQL注入

mybatis是一款优秀的持久层框架,在防止sql注入方面,mybatis启用了预编译功能,在所有的SQL执行前, 都会先将SQL发送给数据库进行编译,执行时,直接替换占位符"?"即可;

mybatis在处理传参的时候,有两种处理方式,一种是#,另一种是$;

1、#{XXX},将传入参数都当成一个字符串,会自动加双引号,已经经过预编译,安全性高,能很大程度上防止sql注入; 2、${XXX},该方式则会直接将参数嵌入sql语句,未经过预编译,安全性低,无法防止sql注入;一般用于传入数据库对象,例如传入表名。

结论:在编写MyBatis的映射语句时尽量采用#{xxx}这样的格式。若不得不使用${xxx}这样的参数,要手动做好过滤工作,来防止SQL注入。

MyBatis3.0中使用link进行模糊查询,防止sql注入攻击。正确写法如下:

Mysql: select * from t_user where name like concat('%', #{name}, '%') 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曼走丶999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值