1.SQL注入的概念
SQL注入是指用户输入的条件中含有SQL的关键字,并且参与了SQL语句执行,改变了SQL语句的执行结果,叫SQL注入。SQL注入坏处:他人可以通过SQL注入盗取信息等等。
在tt_user表中查询userna为 'zs' 的用户,输入语句
SELECT * FROM tt_user WHERE username = 'zs AND password = 'z1234'就行了;
但是在我们在后面添加一个 OR 1 = 1时,就能把我们表里的数据都查询出来。
这是因为不论前面的条件是否成立而 OR 后面的 1 = 1 绝对会成立,最终条件是成立的所以就能查询到我们表里的全部数据。
2.SQL注入的解决方案
预编译:
预编译就是我们先将SQL语句预先处理,处理了以后,用户只能输入条件,而且输入的这个条件不能改变SQL语句的执行结果。
预编译的好处:
1.可以有效防止SQL注入;
2.安全且效率高;
3.可以动态填充数据。
3.登录示例理解 PreparedStatement
PreparedStatement概述:
PreparedStatement 继承了 Statement 类,可以有效的防止SQL注入。
登录示例:
需求:1.写一个登录界面,有账号、密码,账号和密码取数据库表中的username和password;
2.写一个登录成功的界面,内容随意;
3.利用PreparedStatement 对象,验证登录密码是否正确,且登录成功后跳转登录成功界 面
第一步,先写登录界面login.jsp,eclipse新建jsp文件,这里注意了action里要写请求 Servlet 的名
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录页面</title>
</head>
<body>
<!-- action写要请求 Servlet 的名 -->
<form action="leleServlet" method="post">
用户名:<input type="text" name="uname"><br><br>
密码:<input type="password" name="pwd"><br><br>
<input type="submit" value="登录">
<input type="reset" value="重置">
</form>
</body>
</html>
第二步,再把登录成功界面hello.jsp搞出来,这个也很简单,就是一个jsp界面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功页面</title>
</head>
<body>
登录成功!<br>
<a href="链接">返回登录页面</a>
</body>
</html>
第三步---编写Java代码
(1)新建一个带doget方法的servlet类
(2)PreparedStatement 代码:
具体由以下几步:
1.先加载驱动
Class.forName("com.mysql.jdbc.Driver");
报错不要慌,鼠标放在 forName 上点击 surround with try/catch 即可, 我们接下来的代码写在 try 里
,
2.获取数据库的链接和获取前面jsp传输过来的数据
// 2.获取数据库链接
String url = "jdbc:mysql://localhost:3306/数据库名称?useSSL=false";
String username = "用户名";
String password = "密码";
Connection connt =DriverManager.getConnection(url,username,password);
// 获取通过HTTP协议传输过来的数据
String name = request.getParameter("uname");
String pwd = request.getParameter("pwd");
3.定义SQL语句,注意SQL语句中的参数值,使用 ?占位符替代,并获取 PreparedStatement 对象
// 定义SQL语句
// SQL语句中的参数值,使用 ?占位符替代
String sql = "SELECT username,password FROM tt_user WHERE username=? AND password=?";
// 获取 PreparedStatement 对象
PreparedStatement pstmt = conn.prepareStatement(sql);
4.执行SQL,并根据用户输入的数据判断
// 执行SQL
ResultSet resultSet=pstmt.executeQuery(sql);
// 判断
if (resultSet.next()) {
request.getRequestDispatcher("hello.jsp").forward(request, response);
} else {
request.getRequestDispatcher("login.jsp").forward(request, response);
}
5.最后释放资源就行了,但是try里是局部变量,我们无法释放资源,所以我们把一些变量对的定义放在try外面即可。
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null
完整代码如下:
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/leleServlet")
public class leleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public leleServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
try {
// 注册MySQL驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取链接
String url = "jdbc:mysql://localhost:3306/数据库名称?useSSL=false";
String username = "用户名";
String password = "密码";
conn = DriverManager.getConnection(url, username, password);
// 获取通过HTTP协议传输过来的数据
String name = request.getParameter("uname");
String pwd = request.getParameter("pwd");
// 定义SQL语句
// SQL语句中的参数值,使用 ?占位符替代
String sql = "SELECT username,password FROM tt_user WHERE username=? AND password=?";
// 获取 PreparedStatement 对象
pstmt = conn.prepareStatement(sql);
// 设置 ? 的值
pstmt.setString(1, name);
pstmt.setString(2, pwd);
// 执行SQL
resultSet = pstmt.executeQuery();
if (resultSet.next()) {
request.getRequestDispatcher("hello.jsp").forward(request, response);
System.out.println("yes");
} else {
request.getRequestDispatcher("login.jsp").forward(request, response);
System.out.println("no");;
}
}
// 捕捉异常,打印异常
catch (Exception e) {
e.printStackTrace();
}
}
}