学习笔记如何防止SQL注入,处理并发
一. 什么是SQL注入?自己写一个相关DEMO
①SQL注入是一种注入攻击,可以执行恶意SQL语句,对数据库信息进行非法获取篡改的目的。
相关Demoe实例
MySQL为例,现在项目大部分都用框架实现,比如MyBatis框架,轻量级,功能强大:
在MyBatis中,如果写${变量名},则为直接把传入的值填充到SQL语句中;
如果写#{变量名},则为传入的值只能作为值,放到SQL语句中。
举例:
DELETE FROM student WHERE name=${stu_name}
1)如果这样写,假如用户恶意传入这样一个字符串:abc OR 1=1,
那么整个SQL就变成了
DELETE FROM student WHERE name=abc OR 1=1,
2)结果就是全部数据都删掉了。这就是SQL注入,
如果把${stu_name}换成#{stu_name},那么依然传入上面的字符串,
那么SQL是这样的:
DELETE FROM student WHERE name=
abc OR 1=1
,
会删除名字为abc OR 1=1的学生,没有这个学生则什么都删除不掉,这样就防止了SQL注入。
请说一下你如何防止SQL注入?
二. 如何防止SQL注入防止SQL注入,我们需要注意以下几个要点:
①.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
②.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
③.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
④.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
⑤.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
请说一下你开发中如何防止SQL注入?
三. java如何防止后台的SQL注入
①.采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setString方法传值即可:
String sql= "select * from users where username=? and password=?;
PreparedStatement preState = conn.prepareStatement(sql);
preState.setString(1, userName);
preState.setString(2, password);
ResultSet rs = preState.executeQuery();
②.采用正则表达式将包含有 单引号(’),分号(😉 和 注释符号(–)的语句给替换掉来防止SQL注入
public static String SQL(String str){//替换方法
return str.replaceAll(".*([';]+|(--)+).*", " ");
}
//例子
userName=SQL(userName);
password=SQL(password);
String sql="select * from users where username='"+userName+"' and password='"+password+"' "
Statement sta = conn.createStatement();
ResultSet rs = sta.executeQuery(sql);
四. 以下注解及相关属性的作用,写到笔记上
@Repository(持久层)
---------①这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。
@Service(业务层)
---------①此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图。
@Constroller(控制层)
--------①这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。
@Component(组件):
--------①泛指组件,当对一个组件分不清是那一层的时候,可以用Component来查询对应组件。
@Scope(作用域):
--------①默认为单例模式(Singleton):全局获取Bean仅有一个实例。
--------②多列模式(Prototype):每次获取Bean的时候会有一个新实例。
@Autowired(Spring类型装配):
--------①根据类型自动注入依赖对象。
--------②允许为null值,在@Autowired(required=false)关闭必须存在依赖对象要求。
--------③通过Name注入,@Autowired()@Qualifier(“baseDao”)。
@Resource(J2EE类型装配)
--------①根据Name来自动注入依赖对象。
--------②Name为空,会取字段名来进行注入与查询。
--------③如果注解写了Set/Get注解方法会取属性名进行注入。
注:当找不到Bean时才按照类型进行装配,Name属性一旦指定,只会按照名称进行注入。
@Transactional(注解事务):
--------①注解事务管理机制。
--------②注解标注事物回滚,但是触发的条件是在抛出RuntimeException后才会触发。
五.通过数据库表version字段解决并发问题
--------①在修改信息是加version字段:
update t_book set book_price = #{bookPrice},version=version+1
where book_id=#{bookId} and version=#vsersion#
--------②在方法上加一个判断是否version是否改变:
throw new RuntimeException(“对象已过期(ObjectExpired)或不存在(Object Not Found)”);