I. Objectives
Mybatis Introduction
Mybatis CRUD
SQL injection problems introduced
Mybatis xml and achieve comment
Mybatis page
Two, Mybatis Quick Start
Introduction 2.1 Mybatis
MyBatis supports common SQL queries , stored procedures and advanced mapping class persistence framework. MyBatis eliminates almost all of the code and to manually set parameters JDBC package and retrieve the result set. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJO (Plain Old Java Objects, ordinary Java objects) is mapped to the number of records in the database. JDBC -> MyBatis
2.2 Mybatis environment to build
Add Maven 2.2.1 dependent
<dependencies> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.4</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency> </dependencies>
Table 2.2.2 build
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), age INT); INSERT INTO users(name, age) VALUES('Tom', 12); INSERT INTO users(name, age) VALUES('Jack', 11);
2.2.3 Adding mybatis profile
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:23306/mydatabase" /> <property name="username" value="root" /> <property name="password" value="master" /> </dataSource> </environment> </environments> </configuration>
2.2.4 entity class definition table
package com.hongmoshui.mybatis.entity; public class User { private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
2.2.5 Interface definitions userMapper
package com.hongmoshui.mybatis.mapper; import com.hongmoshui.mybatis.entity.User; public interface UserMapper { public User getUser(int id); public Integer addUser(String name, int age); public Integer delUser(int id); }
2.2.6 users define the operation table mapping file userMapper.xml sql
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hongmoshui.mybatis.mapper.UserMapper"> <select id="getUser" parameterType="int" resultType="com.hongmoshui.mybatis.entity.User"> SELECT * FROM users where id =#{id} </select> <insert id="addUser" parameterType="com.hongmoshui.mybatis.entity.User"> INSERT INTO users(name, age) VALUES(#{name}, #{age}); </insert> <delete id="delUser" parameterType="int"> delete from users where id=#{id} </delete> </mapper>
2.2.7mybatis.xml file to load the configuration file
<mappers> <mapper resource="mapper/userMapper.xml" /> </mappers>
2.2.8mybatis test methods
package com.hongmoshui.mybatis; import java.io.IOException; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import com.hongmoshui.mybatis.entity.User; public class TestMybatis { public static void main(String[] args) throws IOException { String resource = "mybatis.xml"; // 读取配置文件 Reader reader = Resources.getResourceAsReader(resource); // 获取会话工厂 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); SqlSession openSession = sqlSessionFactory.openSession(); addUser(openSession); delUser(openSession); getUser(openSession); } private static void getUser(SqlSession openSession) { // 查询 String sql = "com.hongmoshui.mybatis.mapper.UserMapper.getUser"; // 参数id int id = 1; // 调用api查询 User user = openSession.selectOne(sql, id); System.out.println(user.toString()); } private static void addUser(SqlSession openSession) { // 新增SQL String sql = "com.hongmoshui.mybatis.mapper.UserMapper.addUser"; // 调用api查询 User user = new User(); user.setAge(19); user.setName("hongmoshui"); int reuslt = openSession.insert(sql, user); openSession.commit(); System.out.println(reuslt); } private static void delUser(SqlSession openSession) { // 删除SQL String sql = "com.hongmoshui.mybatis.mapper.UserMapper.delUser"; // 调用api查询 int id = 2; int reuslt = openSession.insert(sql, id); openSession.commit(); System.out.println(reuslt); } }
Three, sql injection case
3.1 + Create a table of test data
create table user_table( id int Primary key, username varchar(30), password varchar(30) ); insert into user_table values(1,'hongmoshui-1','12345'); insert into user_table values(2,'hongmoshui-2','12345');
3.2 jdbc loaded
package com.hongmoshui.mybatis; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class TestSQL { public static void main(String[] args) throws ClassNotFoundException, SQLException { String username = "hongmoshui-1"; String password = "12345"; String sql = "SELECT id,username FROM user_table WHERE " + "username='" + username + "'AND " + "password='" + password + "'"; Class.forName("com.mysql.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://localhost:23306/mydatabase", "root", "master"); PreparedStatement stat = con.prepareStatement(sql); System.out.println(stat.toString()); ResultSet rs = stat.executeQuery(); while (rs.next()) { String id = rs.getString(1); String name = rs.getString(2); System.out.println("id:" + id + ",name:" + name); } } }
3.3 Set the value for the username
username=' OR 1=1 -- 或者username or 1='1
Because - SQL comments indicate, therefore behind the statement is ignored;
Since the establishment of the constant 1 = 1, so username = '' OR 1 = 1 constant established, so SQL statement is equivalent to:
SELECT id,username FROM user_table
3.4sql injection solution
Step One: Compile sql
The second step: the implementation of sql
Advantages: can be precompiled sql statement
package com.hongmoshui.mybatis; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class TestSQL { public static void main(String[] args) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://localhost:23306/mydatabase", "root", "master"); // 无注入情况 String username1 = "hongmoshui-1"; String password1 = "12345"; String sql1 = "SELECT id,username FROM user_table WHERE " + "username='" + username1 + "'AND " + "password='" + password1 + "'"; selectNoInjection(con, username1, password1, sql1); // 注入,但是有预编译 String username2 = "username=' OR 1=1 -- "; String password2 = "12345"; String sql2 = "SELECT id,username FROM user_table WHERE username=? AND password=?"; selectInjection(con, username2, password2, sql2); } private static void selectInjection(Connection con, String username, String password, String sql) throws SQLException { PreparedStatement stat = con.prepareStatement(sql); stat.setString(1, username); stat.setString(2, password); System.out.println(stat.toString()); ResultSet rs = stat.executeQuery(); while (rs.next()) { String id = rs.getString(1); String name = rs.getString(2); System.out.println("id:" + id + "---name:" + name); } } private static void selectNoInjection(Connection con, String username, String password, String sql) throws ClassNotFoundException, SQLException { PreparedStatement stat = con.prepareStatement(sql); System.out.println(stat.toString()); ResultSet rs = stat.executeQuery(); while (rs.next()) { String id = rs.getString(1); String name = rs.getString(2); System.out.println("id:" + id + ",name:" + name); } } }
And $ 3.4 mybatis difference in #
Dynamic sql is one of the main characteristics mybatis, after which the parameters defined in the mapper xml passed in, before the query mybatis will be dynamic resolution. mybatis provides two support our dynamic sql syntax: # {} and $ {}.
In the following statement, if the value of username zhangsan, is no different in two ways:
select * from user where name = #{name}; select * from user where name = ${name};
The results are then parsed
select * from user where name = ' zhangsan ' ;
But $ # {} and {} is processed in the pre-compiler is not the same. ? # {} While pretreatment parameters will partially replaced by a placeholder, into the sql statement as follows:
select * from user where name = ?;
And $ {} string is simply replaced, the dynamic resolution phase, the sql statement is parsed into
select * from user where name = ' zhangsan ' ;
Above, parameter # {} replacement occurs in the DBMS, and {} $ occurs in the dynamic resolution process.
Then, in the course of which way should we use it?
The answer is that the priority use # {}. {Because} $ sql injection can cause problems. See the examples below:
select * from ${tableName} where name = #{name}
In this example, if the table is named
user; delete user; --
After parsing the dynamic sql follows:
select * from user; delete user; -- where name = ?;
- After the statement is commented out, and the original user query statements into a query statement to delete all user information + user table, the database will cause significant damage, most likely resulting in server downtime.
But when the table name passed in parameter, you can only use $ {}, the specific reasons may be their own guess, to verify. It also reminds us to be careful in this usage problems sql injection.
3.4.1 Creating UserTable
package com.hongmoshui.mybatis; public class UserTable { private int id; private String userName; private String passWord; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } }
3.4.2 Creating UserTableMapper
package com.hongmoshui.mybatis.mapper; import com.hongmoshui.mybatis.UserTable; public interface UserTableMapper { public UserTable login(UserTable userTable); }
3.4.3userTableMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hongmoshui.mybatis.mapper.UserTableMapper"> <select id="login" parameterType="com.hongmoshui.mybatis.UserTable" resultType="com.hongmoshui.mybatis.UserTable"> SELECT id ,username as userName FROM user_table WHERE username=${userName} AND password=${passWord} </select> </mapper>
3.4.4 mybatis.xml file to load the configuration file
<mappers> <!-- <mapper resource="mapper/userMapper.xml" /> --> <mapper resource="mapper/userTableMapper.xml" /> </mappers>
3.4.5 Test SQL Injection
package com.hongmoshui.mybatis; import java.io.IOException; import java.io.Reader; import java.sql.SQLException; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class TestLoginMybatis3 { public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException { Resource String = "mybatis.xml" ; // reads the configuration file Reader Reader = Resources.getResourceAsReader (Resource); // get the session factory SqlSessionFactory SqlSessionFactory = new new the SqlSessionFactoryBuilder () Build (Reader);. SqlSession openSession = sqlSessionFactory.openSession ( ); // query String SQL = "com.hongmoshui.mybatis.mapper.UserTableMapper.login" ; // call api query userTable userTable = new new userTable (); userTable.setUserName ( " '' OR 1 = 1 -" ) ; userTable.setPassWord("12345"); List<UserTable> listUserTable = openSession.selectList(sql, userTable); for (UserTable ub : listUserTable) { System.out.println(ub.getUserName()); } } }
3.4.6 summary
Priority use#{}. Because $ {} sql injection causes problems of
A, Mybatis use annotations
Mybatis provides CRUD annotation, @ select @delete @update
4.1 Establish comment Mapper
package com.hongmoshui.mybatis.mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import com.hongmoshui.mybatis.UserTable; public interface UserTestMapper { @Select("select * from user_table where id = ${id};") public UserTable getUser(@Param("id") int id); }
4.2 added mybatis.xml
<mappers> <!-- <mapper resource="mapper/userMapper.xml" /> <mapper resource="mapper/userTableMapper.xml" /> --> <mapper class="com.hongmoshui.mybatis.mapper.UserTestMapper" /> </mappers>
4.3 Test run
package com.hongmoshui.mybatis; import java.io.IOException; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import com.hongmoshui.mybatis.mapper.UserTestMapper; public class TestMybatis3 { public static void main(String[] args) throws IOException { String resource = "mybatis.xml"; // reads the configuration file Reader Reader = Resources.getResourceAsReader (Resource); // get the session factory SqlSessionFactory SqlSessionFactory = new new the SqlSessionFactoryBuilder () Build (Reader);. SqlSession openSession = sqlSessionFactory.openSession (); // call api query UserTestMapper userTestMapper openSession.getMapper = (UserTestMapper. class ); System.out.println (userTestMapper.getUser ( 2 )); } }