MyBatis进阶:告别SQL注入!MyBatis分页与特殊字符的正确使用方式

简介: MyBatis进阶:告别SQL注入!MyBatis分页与特殊字符的正确使用方式

e9d0030de9d0452388f8a72ac522ea0e.jpg

引言

SQL注入是一种常见的数据库攻击手段,它利用了程序员在编写代码时疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库。举个例子,如果一个网站没有对用户输入的字符串进行过滤、转义、限制或处理不严谨,那么攻击者就可以通过输入精心构造的字符串去非法获取到数据库中的数据  。

SQL注入的坏处包括但不限于:窃取敏感信息、破坏数据、影响系统稳定性等  。

SQL注入案例:

当用户输入的数据直接拼接到SQL语句中时,如果用户输入恶意数据,例如 ' OR '1'='1,那么整个SQL语句会变成:

SELECT * FROM users WHERE name = '' OR '1'='1';

由于1=1 永远为真,所以这个SQL语句会返回所有用户记录。这就是一个典型的SQL注入攻击。如果使用MyBatis的动态SQL功能,用户可以在查询语句中直接输入变量名,而MyBatis会将这些变量替换为对应的值。如果用户输入的值包含恶意代码,那么就会导致SQL注入问题。

下面来看看我们怎么解决的吧!!👇👇

一、使用正确的方式实现分页

1.1.什么是分页

分页是一种操作系统里存储器管理的一种技术,可以使电脑的主存可以使用存储在辅助存储器中的数据。操作系统会将辅助存储器(通常是磁盘)中的数据分区成固定大小的区块,称为“页”。当不需要时,将当前访问的页从内存中换出,放入磁盘中,以便下次访问时再将其读入内存。这样,每次只需要读取所需的那一页数据,就可以避免一次性读取大量数据导致内存不足的问题。

举个例子,如果我们需要在一个网站上查看文章列表,但是每篇文章都有很多内容,如果我们一次性将所有文章全部加载到浏览器中,那么可能会导致浏览器崩溃。而如果我们使用分页技术,每次只加载一篇文章的内容,这样就可以避免这个问题。

MyBatis分页插件提供了多种分页方式,可以满足不同场景下的需求。例如,可以使用物理分页和逻辑分页两种方式来实现分页查询。物理分页是指将数据分成固定大小的块进行查询,而逻辑分页则是根据用户需求进行查询。使用MyBatis分页插件可以方便地实现这些功能,并且可以避免SQL注入等安全问题。

1.2.MyBatis中的分页实现方式

MyBatis中有多种分页实现方式,其中比较常用的有以下几种:

      1.物理分页:将数据分成固定大小的块进行查询。这种方式的优点是速度快,但是缺点是占用内存大,不适用于数据量大的情况。

<select id="selectUsersByPage" parameterType="map" resultType="User">
    SELECT * FROM user
    LIMIT #{start}, #{size}
</select>

       2.逻辑分页:根据用户需求进行查询。这种方式的优点是可以根据用户需求进行查询,灵活性高,但是缺点是需要手动编写SQL语句,维护成本高。

public List<User> selectUsersByPage(int pageNum, int pageSize) {
    int start = (pageNum - 1) * pageSize;
    int end = start + pageSize;
    List<User> users = userMapper.selectAllUsers();
    if (start < users.size()) {
        users = users.subList(start, end);
    }
    return users;
}

       3.MyBatis分页插件:提供了多种分页方式,可以满足不同场景下的需求。例如,可以使用物理分页和逻辑分页两种方式来实现分页查询。使用MyBatis分页插件可以方便地实现这些功能,并且可以避免SQL注入等安全问题。

我接下来要介绍的是第三种方式MyBatis分页插件,利用插件完成分页共有以下四步:

①导入pom依赖

 <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.2</version>
    </dependency>

②Mybatis.cfg.xml配置拦截器

<plugins>
    <!-- 配置分页插件PageHelper, 4.0.0以后的版本支持自动识别使用的数据库 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
    </plugin>
</plugins>

注意事项:该标签不能写在后面,因为该文件的DTD约束了每个标签的先后顺序

③使用PageHelper进行分页

BookMapper.xml

<select id="listPager" resultType="com.csdn.xw.model.Book" parameterType="java.lang.String">
  select * from t_mvc_book where bname like concat(concat('%',#{bname}),'%')
</select>

BookMapper

List<Book> listPager(@Param("bname") String bname);

BookBiz

List<Book> listPager(String bname);

BookBizImpl

package com.csdn.xw.biz.Impl;
import com.csdn.xw.biz.BookBiz;
import com.csdn.xw.mapper.BookMapper;
import com.csdn.xw.model.Book;
import java.util.List;
/**
 * @author Java方文山
 * @compay csdn_Java方文山
 * @create 2023-08-19-13:41
 */
public class BookBizImpl implements BookBiz {
    private BookMapper bookMapper;
    public BookMapper getBookMapper() {
        return bookMapper;
    }
    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }
    @Override
    public List<Book> listPager(String bname) {
        return bookMapper.listPager(bname);
    }
}

BookBizImplTest

package demo;
import com.csdn.xw.biz.Impl.BookBizImpl;
import com.csdn.xw.mapper.BookMapper;
import com.csdn.xw.util.SessionUtil;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
/**
 * @author Java方文山
 * @compay csdn_Java方文山
 * @create 2023-08-19-13:46
 */
public class demo1 {
    private BookBizImpl bookBiz = new BookBizImpl();
    SqlSession sqlSession;
    @Before
    public void setUp() throws Exception {
        System.out.println("初始换方法。。。");
        //工具类中获取session对象
        sqlSession = SessionUtil.openSession();
        //从session对象中获取mapper对象
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        bookBiz.setBookMapper(mapper);
    }
    @After
    public void tearDown() throws Exception {
        System.out.println("方法测试结束。。");
        sqlSession.commit();
    }
    @Test
    public void listPager() {
        System.out.println("测试的mybatis的分页插件方法");
        PageHelper.startPage(1, 10); // 第1页,每页10条数据
        System.out.println("当前页数:"+PageHelper.getLocalPage().getPageNum()+"当前页展示数:"+PageHelper.getLocalPage().getEndRow());
        bookBiz.listPager("圣墟").forEach(System.out::println);
    }
}

④处理分页结果

1.3.避免SQL注入的技巧

  1. 使用参数化查询:使用参数化查询是防止SQL注入的最有效方法之一。通过将查询参数化,将用户提供的输入值作为参数传递给查询,而不是将输入值直接拼接到SQL语句中。这样可以确保输入值被正确地转义和处理,减少SQL注入的风险。
  2. 使用存储过程:存储过程是一种在数据库中预编译的SQL代码块,可以通过调用存储过程来执行SQL操作。使用存储过程可以避免SQL注入,因为它们不允许用户直接输入数据,而是使用预先定义好的参数来传递数据。
  3. 过滤用户输入:对用户输入进行过滤和验证,确保输入数据的合法性。例如,可以使用正则表达式或白名单来限制用户输入的字符集,或者限制输入长度等。

二、特殊字符的正确使用方式

2.1.什么是特殊字符

在Mybatis中,特殊字符是指在XML文件中需要转义的字符。这些字符包括:&、<、>、"、'、/等。为了避免这些字符对XML文件造成影响,我们需要对它们进行转义。

2.2.特殊字符在SQL查询中的作用

在SQL查询中,特殊字符可以用来进行模糊查询。其中,%表示任何字符出现任意次数(可以是0次),而_表示一个字符。除此之外,还有一些其他的字符,比如[]^\\等等,它们也可以用来进行模糊查询。

例如,假设有一个名为"users"的表,其中包含一个名为"name"的列,我们可以使用以下语句来查找名字以字母"A"开头的所有用户:

SELECT * FROM users WHERE name LIKE 'A%';

这将返回所有名字以字母"A"开头的用户。另外,如果我们想要查找名字中包含两个字母"A"的用户,我们可以使用以下语句:

SELECT * FROM users WHERE name LIKE '%A%A%';

2.3.如何避免特殊字符引起的问题

先来一个没有特殊处理过的

BookMapper.xml

<select id="listPagerS" resultType="com.csdn.xw.model.Book" parameterType="java.util.Map">
  select * from t_mvc_book where bname like concat(concat('%',#{bname}),'%') and price < #{max}
</select>

BookBizImplTest

 @Test
    public void listPagerS() {
        System.out.println("没有处理特殊字符之前");
        Map map=new HashMap();
        map.put("dname","圣墟");
        map.put("max",20);
        bookBiz.listPagerS(map).forEach(System.out::println);
    }

测试结果:

直接报红了,因为有些特殊字符是需要处理的,下面我来给大家介绍两种处理方案:

2.3.1.使用CDATA区段

CDATA区段是XML中的一个元素,它包含了不会被解析器解析的文本。一个CDATA区段中的标签不会被视为标记,同时实体也不会被展开。主要的目的是为了包含诸如XML片段之类的材料,而无需转义所有的分隔符 。

我们只需在需要有特殊字符的地方加上即可

BookMapper.xml

  <select id="listPagerS" resultType="com.csdn.xw.model.Book" parameterType="java.util.Map">
  select * from t_mvc_book where bname like concat(concat('%',#{bname}),'%') and <![CDATA[  price <#{max}]]>
</select>

这时候再来看看效果:

2.3.2.使用实体引用

在XML中,一些字符具有特殊的意义,比如<>&等符号。如果我们需要在文本中使用这些符号,就需要将它们转义为对应的实体引用。例如,<应该被转义为<>应该被转义为>&应该被转义为&

BookMapper.xml

 <select id="listPagerS" resultType="com.csdn.xw.model.Book" parameterType="java.util.Map">
  select * from t_mvc_book where bname like concat(concat('%',#{bname}),'%') and   price &gt; #{max}
</select>

测试效果:

以下是一些常见的需要转义的XML特殊字符及其对应的实体引用:

特殊字符 实体引用
< &lt;
> &gt;
& &amp;
" &quot;
' &apos;
/ &#x2F;
\ &#x5C;
" &quot;
' &apos;

三、总结和展望

3.1.MyBatis的优点和不足

优点

  1. 灵活:MyBatis提供了高度可配置的选项来满足不同需求,支持多种数据库和数据源。
  2. 易于使用:MyBatis提供了简单直观的SQL映射文件和接口,使得开发人员能够快速上手并编写高效的SQL语句。
  3. 解耦性高:MyBatis将SQL语句与Java代码分离,使得开发人员可以专注于业务逻辑的开发,而不需要关心底层的数据访问细节。
  4. 缓存支持:MyBatis提供了一级缓存和二级缓存的支持,可以提高查询性能。
  5. 动态SQL:MyBatis支持动态SQL,可以根据不同的条件生成不同的SQL语句,提高了SQL语句的灵活性。

不足之处

  1. 学习曲线较陡峭:相对于其他持久层框架,MyBatis的学习曲线较为陡峭,需要一定的时间来熟悉其配置和使用方式。
  2. XML配置文件复杂:MyBatis使用XML配置文件来定义SQL映射关系,对于复杂的SQL语句和大量的映射关系,XML配置文件可能会变得冗长且难以维护。
  3. SQL语句优化困难:由于MyBatis将SQL语句与Java代码分离,对于复杂的SQL语句优化可能需要额外的工作。

3.2.未来发展趋势和应用场景

  1. 自动化生成:随着AI技术的发展,MyBatis有望通过自动化生成技术减少手动编写SQL语句的工作量,提高开发效率。
  2. 插件化扩展:MyBatis可以通过插件化的方式扩展其功能,满足不同场景的需求,如分页插件、缓存插件等。
  3. 云原生支持:随着云计算的普及,MyBatis可以进一步提供云原生的支持,如容器化部署、微服务架构等。
  4. 多租户支持:随着多租户应用的兴起,MyBatis可以提供更好的多租户支持,如数据隔离、权限控制等。
  5. 大数据处理:MyBatis可以结合大数据处理框架(如Spark、Flink)进行大规模数据的处理和分析。
  6. 低代码开发平台:随着低代码开发平台的兴起,MyBatis可以作为其核心组件之一,提供快速搭建数据模型和数据访问的能力。

综上所述,MyBatis作为一种优秀的持久层框架,在未来将继续发挥重要作用。虽然存在一些不足之处,但随着技术的不断发展和创新,相信MyBatis将会不断改进和完善,为开发者提供更多便利和支持。

到这里我的分享就结束了,欢迎到评论区探讨交流!!

如果觉得有用的话还请点个赞吧 ♥  ♥


相关文章
|
14天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
31 10
|
2月前
|
SQL XML Java
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
|
2月前
|
SQL 安全 数据库
惊!Python Web安全黑洞大曝光:SQL注入、XSS、CSRF,你中招了吗?
在数字化时代,Web应用的安全性至关重要。许多Python开发者在追求功能时,常忽视SQL注入、XSS和CSRF等安全威胁。本文将深入剖析这些风险并提供最佳实践:使用参数化查询预防SQL注入;通过HTML转义阻止XSS攻击;在表单中加入CSRF令牌增强安全性。遵循这些方法,可有效提升Web应用的安全防护水平,保护用户数据与隐私。安全需持续关注与改进,每个细节都至关重要。
128 5
|
2月前
|
SQL 安全 数据库
深度揭秘:Python Web安全攻防战,SQL注入、XSS、CSRF一网打尽!
在Web开发领域,Python虽强大灵活,却也面临着SQL注入、XSS与CSRF等安全威胁。本文将剖析这些常见攻击手段,并提供示例代码,展示如何利用参数化查询、HTML转义及CSRF令牌等技术构建坚固防线,确保Python Web应用的安全性。安全之路永无止境,唯有不断改进方能应对挑战。
67 5
|
2月前
|
SQL 安全 数据安全/隐私保护
Python Web安全大挑战:面对SQL注入、XSS、CSRF,你准备好了吗?
在构建Python Web应用时,安全性至关重要。本文通过三个真实案例,探讨了如何防范SQL注入、XSS和CSRF攻击。首先,通过参数化查询替代字符串拼接,防止SQL注入;其次,利用HTML转义机制,避免XSS攻击;最后,采用CSRF令牌验证,保护用户免受CSRF攻击。这些策略能显著增强应用的安全性,帮助开发者应对复杂的网络威胁。安全是一个持续的过程,需不断学习新知识以抵御不断变化的威胁。
117 1
|
2月前
|
SQL 安全 数据库
Python Web开发者必看!SQL注入、XSS、CSRF全面解析,守护你的网站安全!
在Python Web开发中,构建安全应用至关重要。本文通过问答形式,详细解析了三种常见Web安全威胁——SQL注入、XSS和CSRF,并提供了实用的防御策略及示例代码。针对SQL注入,建议使用参数化查询;对于XSS,需对输出进行HTML编码;而防范CSRF,则应利用CSRF令牌。通过这些措施,帮助开发者有效提升应用安全性,确保网站稳定运行。
47 1
|
2月前
|
SQL 安全 数据库
深度揭秘:Python Web安全攻防战,SQL注入、XSS、CSRF一网打尽!
在Web开发领域,Python虽强大灵活,但安全挑战不容小觑。本文剖析Python Web应用中的三大安全威胁:SQL注入、XSS及CSRF,并提供防御策略。通过示例代码展示如何利用参数化查询、HTML转义与CSRF令牌构建安全防线,助您打造更安全的应用。安全是一场持久战,需不断改进优化。
46 3
|
2月前
|
SQL 安全 数据库
从入门到精通:Python Web安全守护指南,SQL注入、XSS、CSRF全防御!
【9月更文挑战第13天】在开发Python Web应用时,安全性至关重要。本文通过问答形式,详细介绍如何防范SQL注入、XSS及CSRF等常见威胁。通过使用参数化查询、HTML转义和CSRF令牌等技术,确保应用安全。附带示例代码,帮助读者从入门到精通Python Web安全。
87 6
|
2月前
|
SQL 安全 JavaScript
告别Web安全小白!Python实战指南:抵御SQL注入、XSS、CSRF的秘密武器!
【9月更文挑战第12天】在Web开发中,安全漏洞如同暗礁,尤其对初学者而言,SQL注入、跨站脚本(XSS)和跨站请求伪造(CSRF)是常见挑战。本文通过实战案例,展示如何利用Python应对这些威胁。首先,通过参数化查询防止SQL注入;其次,借助Jinja2模板引擎自动转义机制抵御XSS攻击;最后,使用Flask-WTF库生成和验证CSRF令牌,确保转账功能安全。掌握这些技巧,助你构建更安全的Web应用。
50 5

热门文章

最新文章