SQL注入是一种常规性的攻击,通过此方法一些不法用户可以检索他人的数据,改变服务器的设置,或者有意破坏他人的服务器。SQL注入式攻击不是SQL Server的问题,而是不适当的程序造成的。
本实例通过替换掉字符串中的危险字符来防止SQL语句的注入,提高程序的安全性。运行来实例,在“用户名”文本框中输入“11‘or’1‘=’1”,并选中“替换”单选按钮,单击“登录”按钮后将显示登录失败,如果选中“不替换”单选按钮,将显示登录成功。运行过程如下图所示。
页面运行效果,选择“替换”单选按钮
点击“登录”按钮后的执行结果
技术要点
如果程序中忽略了SQL注入式攻击的情况,就会给程序造成危害。例如在“用户名”文本框中输入“11 'or' 1 '=' 1”,则程序中的SQL语句如下:
select * from tb_userlogon where user_name='11' or '1'='1'
从上面的SQL语句中可以看出,由于表达式“'1'='1'”的值永远为true,所以即使输入的用户名不正确,条件表达式“user_name='11' or '1'='1'”的值仍为true,此时该用户将成功登录系统。
对输入的危险字符进行替换后将生成如下SQL语句,这样就避免了SQL注入式攻击。
通常情况下,需要进行替换的危险字符主要包括以下几个。
“'”:SQL Server数据库中的预留字符,用来判别字段值的结束。
“--”:SQL Server数据库中的单行注释标志。
“;”:SQL Server数据库中的语句的结束标志。
“<”和“>”:HTML语言中的标志的定界符。
“&”:字符实体的开始标志。如:“ ”表示空格。
实现过程
(1)创建用来替换字符的Checkstr类文件,Checkstr.java代码如下:
package com.safe.SQL;
public class Checkstr {
public Checkstr(){}
public String dostring(String str){
str=str.replaceAll(";","");
str=str.replaceAll("&","&");
str=str.replaceAll("<","<");
str=str.replaceAll(">",">");
str=str.replaceAll("'","");
str=str.replaceAll("--","");
str=str.replaceAll("/","");
str=str.replaceAll("%","");
return str;
}
}
(2)创建对数据库操作的DB类文件。DB.java代码如下:
package com.safe.SQL;
import java.sql.*;
public class DB {
private Connection con;
private Statement stm;
private ResultSet rs;
private String classname="com.microsoft.sqlserver.jdbc.SQLServerDriver";
private String url="jdbc:sqlserver://localhost:1433;DatabaseName=db_database15";
public DB(){}
public Connection getCon(){
try{
Class.forName(classname);
}
catch(ClassNotFoundException e){
e.printStackTrace();
}
try{
con=DriverManager.getConnection(url,"admin","123456");
}
catch(Exception e){
e.printStackTrace(System.err);
con=null;
}
return con;
}
public Statement getStm(){
try{
con=getCon();
stm=con.createStatement();
}catch(Exception e){e.printStackTrace(System.err);}
return stm;
}
public Statement getStmed(){
try{
con=getCon();
stm=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
}catch(Exception e){e.printStackTrace(System.err);}
return stm;
}
public ResultSet search(String sql){
if(sql==null)sql="";
System.out.println("sql:"+sql);
try{
stm=getStmed();
rs=stm.executeQuery(sql);
}
catch(Exception e){e.printStackTrace();}
return rs;
}
public int dosql(String sql){
int num=-1;
if(sql==null)sql="";
try{
stm=getStmed();
num=stm.executeUpdate(sql);
}
catch(Exception e){e.printStackTrace();num=-1;}
return num;
}
public void closed(){
try{
if(rs!=null)rs.close();
}
catch(Exception e){e.printStackTrace();}
try{
if(stm!=null)stm.close();
}
catch(Exception e){e.printStackTrace();}
try{
if(con!=null)con.close();
}
catch(Exception e){e.printStackTrace();}
}
}
(3)创建Logon类文件验证用户的身份并返回提示信息。Logon.java代码如下:
package com.safe.SQL;
import java.sql.*;
public class Logon {
private String username;
private String mark="yes";
private Checkstr check=new Checkstr();
public Logon(){}
public void setUsername(String username){
if(mark.equals("yes"))
this.username=check.dostring(username);
else
this.username=username;
}
public String getUsername(){
return this.username;
}
public void setMark(String mark){
this.mark=mark;
}
public String checklogon(){
String backmess="";
boolean mark=true;
if(this.username.equals("")){
mark=false;
backmess+="<li>请输入<b>用户名!</b></li><br>";
}
if(!mark){
return backmess;
}
String sql="select * from tb_userlogon where user_name='"+this.username+"'";
DB db=new DB();
ResultSet rs=db.search(sql);
try{
if(rs.next()){
backmess="登录成功!<br>输入的用户名:<br>"+this.username;
}
else{
backmess="登录失败!<br>输入的<b>用户名</b>不存在!<br>输入:"+this.username;
}
}
catch(Exception e){
e.printStackTrace();
backmess="操作失败!<br>输入的用户名:<br>"+this.username;
}
db.closed();
return backmess;
}
}
(4)创建首页面index.jsp供用户输入登录信息。代码如下:
<%@ page contentType="text/html;charset=gb2312"%>
<html>
<head>
<title>替换输入字符串中的危险字符</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<center>
<form action="dologon.jsp">
<table style="margin-top:200" width="250" border="1" cellpadding="0" cellspacing="0" bordercolor="black" bordercolorlight="black" bordercolordark="white">
<tr bgcolor="lightgrey" height="30">
<td align="center">替换输入字符串中的危险字符</td>
</tr>
<tr height="30">
<td align="center">
用户名:<input type="text" name="username" size="30">
</tr>
<tr>
<td align="center">
<input type="radio" name="mark" value="yes" checked>替换
<input type="radio" name="mark" value="no">不替换
</td>
</tr>
<tr bgcolor="lightgrey">
<td align="center">
<input type="submit" name="logon" value="登录">
<input type="reset" name="clear" value="重置">
</td>
</tr>
</table>
</form>
</center>
</body>
</html>
(5)创建接收Form表单的dologon.jsp。在该页面中调用创建的Logon类中的checklogon()方法,处理用户输入的信息并显示相应的提示。其代码如下:
<%@ page contentType="text/html;charset=gb2312"%>
<jsp:useBean id="mylogon" class="com.safe.SQL.Logon"/>
<%
String username=request.getParameter("username");
if(username==null)
username="";
username=new String(username.getBytes("ISO-8859-1"),"gbk");
String mark=request.getParameter("mark");
if(mark==null)
mark="yes";
mylogon.setMark(mark);
mylogon.setUsername(username);
%>
<html>
<head>
<title>替换输入字符串中的危险字符</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<center>
<table style="margin-top:200" border="1" cellpadding="0" cellspacing="0" bordercolor="black" bordercolorlight="black" bordercolordark="white">
<tr bgcolor="lightgrey" height="30">
<td align="center">登录状况</td>
</tr>
<tr height="50">
<td align="center">
<%=mylogon.checklogon()%>
</td>
</tr>
</table>
<a href="index.jsp">[返回]</a>
</center>
</body>
</html>