十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这篇文章主要讲解了“Java最新的SQL注入原因以及预防方案”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java最新的SQL注入原因以及预防方案”吧!
成都创新互联专注于南明企业网站建设,成都响应式网站建设公司,成都做商城网站。南明网站建设公司,为南明等地区提供建站服务。全流程定制网站制作,专业设计,全程项目跟踪,成都创新互联专业和态度为您提供的服务
前沿
在现有的框架中sql防注入已经做得很好了,我们需要做的就是尽量不要使用sql拼接调用
java sql注入原因以及预防方案(易理解)
1. SQL注入
1.1 原理
SQL注入是通过客户端的输入把SQL命令注入到一个应用的数据库中,从而执行恶意的SQL语句。
1.2 演示
1.2.1 案例1
有一个登录框,需要 输入用户名和密码 ,然后我们的密码输入 'or '123' = '123 这样的。我们在查询用户名和密码是否正确的时候,本来执行的sql语句是:select * from user where username = '' and password = ''. 这样的sql语句,现在我们输入密码是如上这样的,然后我们会通过参数进行拼接,拼接后的sql语句就是:
select * from user where username = '' and password = ' ' or '123' = '123 ';这样的了,那么会有一个or语句,只要这两个有一个是正确的话,就条件成立,因此 123 = 123 是成立的。因此验证就会被跳过。这只是一个简单的例子,
1.2.2 案例2
密码比如是这样的:'; drop table user;, 这样的话,那么sql命令就变成了:
select * from user where username = '' and password = ''; drop table user;', 那么这个时候我们会把user表直接删除了。
1.3 防范
1.3.1 前端
前端表单进行参数格式控制;
1.3.2 后端
我们可以使用预编译语句(PreparedStatement,这 样的话即使我们使用sql语句伪造成参数,到了服务端的时候,这个伪造sql语句的参数也只是简单的字符,并不能起到攻击的作用。
使用正则表达式过滤传入的参数
注意: 永远也不要把未经检查的用户输入的值直接传给数据库
java中的验证字符串是否包含sql的判断
package cn.javanode.thread; import java.util.regex.Pattern; /** * @author xgt(小光头) * @version 1.0 * @date 2021-1-8 11:48 */ public class CheckSqlDemo { /**正则表达式**/ private static String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|" + "(\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)"; private static Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE); private static boolean isValid(String str) { if (sqlPattern.matcher(str).find()) { System.out.println("未能通过过滤器:str=" + str); return false; } return true; } public static void main(String[] args) { System.out.println(isValid("tongji_user_add")); } }
补充
PreparedStatement是如何防止SQL注入的?
1. 拼接参数(sql注入)
Connection connection = DriverManager.getConnection(DB_URL, USER, PASS); PreparedStatement preparedStatement = connection.prepareStatement(sql); String param = "'test' or 1=1"; String sql = "select file from file where name = " + param; // 拼接SQL参数 ResultSet resultSet = preparedStatement.executeQuery(); System.out.println(resultSet.next());
输出结果为 true ,DB中执行的SQL为
-- 永真条件1=1成为了查询条件的一部分,可以返回所有数据,造成了SQL注入问题 select file from file where name = 'test' or 1=1
2. setString (防注入)
Connection connection = DriverManager.getConnection(DB_URL, USER, PASS); PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,account);//设置参数 preparedStatement.setString(2,password); ResultSet resultSet = preparedStatement.executeQuery();//执行查询sql,获取结果集
输出结果为 false ,DB中执行的SQL为
select file from file where name = '\'test\' or 1=1'
我们可以看到输出的 SQL是把整个参数用引号包起来,并把参数中的引号作为转义字符,从而避免了参数也作为条件的一部分
3. 源码分析
结论
preparedStatement.setString 会判断当前参数的符号是否需要转义,是的话加的转义符
如果不需要,则直接加上引号
//完整代码 public void setString(int parameterIndex, String x) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { // if the passed string is null, then set this column to null if (x == null) { setNull(parameterIndex, Types.CHAR); } else { checkClosed(); int stringLength = x.length(); if (this.connection.isNoBackslashEscapesSet()) { // Scan for any nasty chars // 判断是否需要转义 boolean needsHexEscape = isEscapeNeededForString(x, stringLength); if (!needsHexEscape) { byte[] parameterAsBytes = null; StringBuilder quotedString = new StringBuilder(x.length() + 2); quotedString.append('\''); quotedString.append(x); quotedString.append('\''); if (!this.isLoadDataQuery) { parameterAsBytes = StringUtils.getBytes(quotedString.toString(), this.charConverter, this.charEncoding, this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), getExceptionInterceptor()); } else { // Send with platform character encoding parameterAsBytes = StringUtils.getBytes(quotedString.toString()); } setInternal(parameterIndex, parameterAsBytes); } else { byte[] parameterAsBytes = null; if (!this.isLoadDataQuery) { parameterAsBytes = StringUtils.getBytes(x, this.charConverter, this.charEncoding, this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), getExceptionInterceptor()); } else { // Send with platform character encoding parameterAsBytes = StringUtils.getBytes(x); } setBytes(parameterIndex, parameterAsBytes); } return; }
感谢各位的阅读,以上就是“Java最新的SQL注入原因以及预防方案”的内容了,经过本文的学习后,相信大家对Java最新的SQL注入原因以及预防方案这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!