0 環境準備
1 數據庫環境準備
-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`userName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES (1, 'yang', '123456');
2 依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- SpringBoot web 核心組件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!-- mysql 數據庫驅動. -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- spring-boot mybatis依賴 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- SpringBoot 對lombok 支持 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3 配置文件
spring:
datasource:
url: jdbc:mysql://120.78.134.111:3306/springboot?useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
mybatis:
type-aliases-package: com.snow.entity # mybatis 別名掃描
5 啓動項
package com.snow;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.snow.mapper")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
6 實體類
package com.snow.entity;
import lombok.Data;
import lombok.ToString;
/**
* @author :yang-windows
* @Title : springboot
* @Package :com.snow.entity
* @Description : User
* @date :2020/4/16 11:44
*/
@Data
@ToString
public class User {
private Long id;
private String userName;
private String password;
}
7
UserMapper
package com.snow.mapper;
import com.snow.entity.User;
import org.apache.ibatis.annotations.Select;
/**
* @author :yang-windows
* @Title : springboot
* @Package :com.snow.mapper
* @Description : UserMapper
* @date :2020/4/16 11:46
*/
public interface UserMapper {
@Select("SELECT * FROM user_info WHERE userName=#{userName} AND password=#{password}")
public User login(User user);
}
8
controller
package com.snow.controller;
import com.snow.entity.User;
import com.snow.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author :yang-windows
* @Title : springboot
* @Package :com.snow.controller
* @Description : LoginController
* @date :2020/4/8 22:25
*/
@RestController
public class LoginController {
@Autowired
private UserMapper userMapper;
@RequestMapping("/login")
public String login(User user) {
System.out.println("賬號密碼信息:user:" + user.toString());
User login = userMapper.login(user);
return login == null ? "登陸失敗!" : "登陸成功!";
}
}
9 測試
啓動項目,瀏覽器訪問:http://127.0.0.1:8080/login?userName=yang&password=123456
1 什麼是 SQL
注入
SQL 注入
:利用現有應用程序,將(惡意)的 SQL
命令注入到後臺數據庫執行一些惡意的代碼。
造成 SQL
注入的原因是因爲程序沒有有效過濾用戶的輸入,使攻擊者成功的向服務器提交惡意的 SQL
查詢代碼,程序在接收後錯誤的將攻擊者的輸入作爲查詢語句的一部分執行,導致原始的查詢邏輯被改變,額外的執行了攻擊者精心構造的惡意代碼。
2 演示 SQL
注入攻擊
修改
UserMapper
package com.snow.mapper;
import com.snow.entity.UserEntity;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
@Select("SELECT * FROM user_info WHERE userName=${userName} AND password=${password}")
public UserEntity login(UserEntity userEntity);
}
啓動項目,瀏覽器輸入:http://127.0.0.1:8080/login?userName=yang&password=123456
報錯:
查看日誌:
### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column 'yang' in 'where clause'
### The error may exist in com/snow/mapper/UserMapper.java (best guess)
### The error may involve com.snow.mapper.UserMapper.login-Inline
### The error occurred while setting parameters
### SQL: SELECT * FROM user_info WHERE userName=yang AND password=123456
### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'yang' in 'where clause'
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Unknown column 'yang' in 'where clause'] with root cause
java.sql.SQLSyntaxErrorException: Unknown column 'yang' in 'where clause'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[mysql-connector-java-8.0.19.jar:8.0.19]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.19.jar:8.0.19]
原因:$
是字符串拼接,所以查詢時字段爲 varchar
時,需要添加 '
。
package com.snow.mapper;
import com.snow.entity.User;
import org.apache.ibatis.annotations.Select;
/**
* @author :yang-windows
* @Title : springboot
* @Package :com.snow.mapper
* @Description : UserMapper
* @date :2020/4/16 11:46
*/
public interface UserMapper {
@Select("SELECT * FROM user_info WHERE userName='${userName}' AND password='${password}'")
public User login(User user);
}
再次測試,瀏覽器輸入:http://127.0.0.1:8080/login?userName=yang&password=123456
演示
SQL
注入攻擊
啓動項目,瀏覽器訪問:http://127.0.0.1:8080/login?userName=yang&password=123456’or’1’='1
爲什麼瀏覽器訪問地址會變成:
http://127.0.0.1:8080/login?userName=yang&password=123456%27or%271%27=%271
這是因爲瀏覽器會將特殊的字符進行轉碼。
3 防止 SQL
注入攻擊手段
不要使用拼接 SQL
語句方式、最好使用預編譯方式,在 mybatis
編寫 sql
語句的時候,最好使用 ?
傳參數方式,不要使用 $
傳參數,因爲 $
傳參數方式,可能會受到 sql
語句攻擊。
package com.snow.mapper;
import com.snow.entity.User;
import org.apache.ibatis.annotations.Select;
/**
* @author :yang-windows
* @Title : springboot
* @Package :com.snow.mapper
* @Description : UserMapper
* @date :2020/4/16 11:46
*/
public interface UserMapper {
@Select("SELECT * FROM user_info WHERE userName=#{userName} AND password=#{password}")
public User login(User user);
}
4 MyBatis
#
與 $
區別
-
#{}
:解析爲一個JDBC
預編譯語句(prepared statement)的參數標記符,一個#{ }
被解析爲一個參數佔位符,可以防止SQL
注入問題。 -
${}
:僅僅爲一個純碎的string
替換,在動態SQL
解析階段將會進行變量替換。