目录
StudentDao:
(本文代码第1部分参考书写,负责学生端就对学生端进行分析)
(一)IDEA中的Java源码:
package com.jakey.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.swing.JOptionPane;
import com.jakey.model.Course;
import com.jakey.model.Sinfo;
import com.jakey.model.Student;
import com.jakey.util.StringUtil;
/**
* 学生Dao类
* 负责处理学生相关的操作,包括学生信息查询、密码修改等
*/
public class StudentDao {
/**
* 学生信息查询
* @param con 数据库连接
* @param sinfo 学生信息对象,用于查询条件
* @return 查询结果ResultSet对象
* @throws SQLException
*/
public ResultSet StudentList(Connection con,Sinfo sinfo) throws SQLException{
StringBuffer sb=new StringBuffer("select * from t_sinfo ");
if(sinfo.getSno()!=-1){
sb.append(" and Sno="+sinfo.getSno());
}
if(StringUtil.isNotEmpty(sinfo.getSname())){
sb.append(" and Sname like '%"+sinfo.getSname()+"%'");
}
PreparedStatement pstmt=con.prepareStatement(sb.toString().replaceFirst("and", "where"));
return pstmt.executeQuery(); // 执行查询操作,并返回结果ResultSet对象
}
/**
* 查询学生密码信息
* @param con 数据库连接
* @param student 学生对象,用于查询条件
* @return 查询结果ResultSet对象
* @throws SQLException
*/
public ResultSet PasswordList(Connection con,Student student)throws SQLException{
StringBuffer sb=new StringBuffer("select * from t_slogon ");
if(student.getSno()!=-1){
sb.append("where Sno="+student.getSno());
}
PreparedStatement pstmt=con.prepareStatement(sb.toString());
return pstmt.executeQuery(); // 执行查询操作,并返回结果ResultSet对象
}
/**
* 修改学生密码
* @param con 数据库连接
* @param student 学生对象,包含修改后的密码信息和查询条件
* @return 影响的行数
* @throws Exception
*/
public int PasswordModify(Connection con,Student student)throws Exception{
String sql="update t_slogon set Spassword=? where Sno=? "; // 修改学生密码的sql语句
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setString(1, student.getSpassword());
pstmt.setInt(2, student.getSno());
return pstmt.executeUpdate(); // 执行更新操作,并返回影响的行数
}
}
(二)上述数据库安全性的添加后代码
package com.jakey.dao;
import com.jakey.model.Sinfo;
import com.jakey.model.Student;
import com.jakey.util.StringUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class StudentDao {
public StudentDao() {
}
/**
* 查询学生信息列表
* @param con 数据库连接
* @param sinfo 学生信息
* @return 学生信息结果集
* @throws SQLException
*/
public ResultSet StudentList(Connection con, Sinfo sinfo) throws SQLException {
StringBuffer sb = new StringBuffer("select * from t_sinfo ");
// 判断学号是否为空
if (sinfo.getSno() != -1) {
// 使用预编译语句防止SQL注入
sb.append(" and Sno=?");
}
// 判断姓名是否为空
if (StringUtil.isNotEmpty(sinfo.getSname())) {
// 使用预编译语句防止SQL注入
sb.append(" and Sname like ?");
}
// 将and替换为where
PreparedStatement pstmt = con.prepareStatement(sb.toString().replaceFirst("and", "where"));
int index = 1;
// 如果学号不为空,则设置预编译语句参数
if (sinfo.getSno() != -1) {
pstmt.setInt(index++, sinfo.getSno());
}
// 如果姓名不为空,则设置预编译语句参数
if (StringUtil.isNotEmpty(sinfo.getSname())) {
pstmt.setString(index++, "%" + sinfo.getSname() + "%");
}
return pstmt.executeQuery();
}
/**
* 查询学生密码信息
* @param con 数据库连接
* @param student 学生信息
* @return 学生密码结果集
* @throws SQLException
*/
public ResultSet PasswordList(Connection con, Student student) throws SQLException {
StringBuffer sb = new StringBuffer("select * from t_slogon ");
// 判断学号是否为空
if (student.getSno() != -1) {
// 使用预编译语句防止SQL注入
sb.append("where Sno=?");
}
PreparedStatement pstmt = con.prepareStatement(sb.toString());
// 如果学号不为空,则设置预编译语句参数
if (student.getSno() != -1) {
pstmt.setInt(1, student.getSno());
}
return pstmt.executeQuery();
}
/**
* 修改学生密码信息
* @param con 数据库连接
* @param student 学生信息
* @return 受影响的行数
* @throws Exception
*/
public int PasswordModify(Connection con, Student student) throws Exception {
String sql = "update t_slogon set Spassword=? where Sno=? ";
PreparedStatement pstmt = con.prepareStatement(sql);
// 对密码进行加密处理
pstmt.setString(1, PasswordUtil.encode(student.getSpassword()));
pstmt.setInt(2, student.getSno());
return pstmt.executeUpdate();
}
/**
* 对密码进行加密处理
*/
public static class PasswordUtil {
public static String encode(String password) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password.getBytes());
byte[] bytes = md.digest();
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(Integer.toHexString(b & 0xff));
}
return sb.toString();
}
}
}
这段代码定义了一个静态的内部类PasswordUtil,并且提供了一个静态方法encode,用于对传入的密码进行加密处理。
在该方法内部,首先使用MessageDigest类获取SHA-256算法的实例md,然后将传入的密码字符串转化为字节数组,并使用update方法将其传入md中,进行加密处理。
接着,调用md.digest()方法,获取加密后的字节数组bytes。
然后,定义一个StringBuilder对象sb,遍历字节数组bytes,并将其转换为16进制字符串,并使用append方法添加到sb中。
最后,将sb转换为字符串,作为加密后的密码,并返回该字符串。
PS: 对传入的密码进行SHA-256加密处理,并返回加密后的字符串。需要注意的是,在使用该方法时,需要捕获NoSuchAlgorithmException异常。
(三)其他数据库安全性分析
-
使用连接池管理数据库连接
import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSource; public class DBPool { private static DataSource dataSource; static { BasicDataSource ds = new BasicDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/test"); ds.setUsername("root"); ds.setPassword("password"); ds.setInitialSize(5); ds.setMaxTotal(10); ds.setMaxWaitMillis(10000); dataSource = ds; } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }
-
使用预编译语句防范SQL注入
public ResultSet StudentList(Connection con, Sinfo sinfo) throws SQLException { StringBuffer sb = new StringBuffer("select * from t_sinfo where 1=1"); if (sinfo.getSno() != -1) { sb.append(" and Sno=?"); } if (StringUtil.isNotEmpty(sinfo.getSname())) { sb.append(" and Sname like ?"); } PreparedStatement pstmt = con.prepareStatement(sb.toString()); int index = 1; if (sinfo.getSno() != -1) { pstmt.setInt(index++, sinfo.getSno()); } if (StringUtil.isNotEmpty(sinfo.getSname())) { pstmt.setString(index++, "%" + sinfo.getSname() + "%"); } return pstmt.executeQuery(); }
-
限制用户访问权限
public ResultSet StudentList(Connection con, Sinfo sinfo, int userId) throws SQLException { StringBuffer sb = new StringBuffer("select * from t_sinfo where 1=1"); if (sinfo.getSno() != -1) { sb.append(" and Sno=?"); } if (StringUtil.isNotEmpty(sinfo.getSname())) { sb.append(" and Sname like ?"); } sb.append(" and userId=?"); PreparedStatement pstmt = con.prepareStatement(sb.toString()); int index = 1; if (sinfo.getSno() != -1) { pstmt.setInt(index++, sinfo.getSno()); } if (StringUtil.isNotEmpty(sinfo.getSname())) { pstmt.setString(index++, "%" + sinfo.getSname() + "%"); } pstmt.setInt(index++, userId); return pstmt.executeQuery(); }
-
使用加密算法保护密码
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class PasswordUtil { public static String encode(String password) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(password.getBytes()); byte[] bytes = md.digest(); StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(Integer.toHexString(b & 0xff)); } return sb.toString(); } }
-
对传输的数据进行加密处理
public ResultSet PasswordList(Connection con, Student student) throws SQLException {
StringBuffer sb = new StringBuffer("select * from t_slogon where Sno=?");
PreparedStatement pstmt = con.prepareStatement(sb.toString());
pstmt.setInt(1, student.getSno());
return pstmt.executeQuery();
}
public int PasswordModify(Connection con, Student student, String password) throws Exception {
String sql = "update t_slogon set Spassword=? where Sno=? ";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, PasswordUtil.encode(password));
pstmt.setInt(2, student.getSno());
return pstmt.executeUpdate();
}
(四)MySQL Bench 数据库写法
/*Table structure for table t_sinfo */ // 对表t_sinfo进行结构描述的注释
DROP TABLE IF EXISTS t_sinfo; // 如果表t_sinfo存在,就删除该表
CREATE TABLE t_sinfo ( // 创建表t_sinfo
Sno int(11) NOT NULL, // 学号字段,类型为整型,长度为11,不能为空
Sname varchar(10) NOT NULL, // 姓名字段,类型为字符串类型,最大长度为10,不能为空
Ssex varchar(5) NOT NULL, // 性别字段,类型为字符串类型,最大长度为5,不能为空
Smajor varchar(20) NOT NULL, // 专业字段,类型为字符串类型,最大长度为20,不能为空
Stele varchar(20) NOT NULL, // 电话字段,类型为字符串类型,最大长度为20,不能为空
PRIMARY KEY (Sno) // 学号字段为主键
) ENGINE=InnoDB DEFAULT CHARSET=utf8; // 引擎类型为InnoDB,字符集为utf8
/*Data for the table t_sinfo */ // 对表t_sinfo中数据进行描述的注释
insert into t_sinfo(Sno,Sname,Ssex,Smajor,Stele) values (1,'张三','男','计算机','12345'),(2,'李四','男','机电','120'),(3,'王一','女','英语','88888'); // 向表t_sinfo中插入数据,分别为学号、姓名、性别、专业和电话
/*Table structure for table t_slogon */ // 对表t_slogon进行结构描述的注释
DROP TABLE IF EXISTS t_slogon; // 如果表t_slogon存在,就删除该表
CREATE TABLE t_slogon ( // 创建表t_slogon
Sno int(11) NOT NULL, // 学号字段,类型为整型,长度为11,不能为空
Spassword varchar(20) NOT NULL, // 密码字段,类型为字符串类型,最大长度为20,不能为空
PRIMARY KEY (Sno) // 学号字段为主键
) ENGINE=InnoDB DEFAULT CHARSET=utf8; // 引擎类型为InnoDB,字符集为utf8
/*Data for the table t_slogon / // 对表t_slogon中数据进行描述的注释
insert into t_slogon(Sno,Spassword) values (1,'3'),(2,'2'),(3,'3'); // 向表t_slogon中插入数据,分别为学号和密码
/!40101 SET SQL_MODE=@OLD_SQL_MODE /; // 设置SQL_MODE为旧的SQL_MODE
/!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS /; // 设置FOREIGN_KEY_CHECKS为旧的FOREIGN_KEY_CHECKS
/!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS /; // 设置UNIQUE_CHECKS为旧的UNIQUE_CHECKS
/!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; // 设置SQL_NOTES为旧的SQL_NOTES
(五)学生端界面GUI
嘻嘻,我很喜欢这个表情!