在JSP基本登錄模塊Ⅳ中,如果在密碼欄輸入“' or '1'='1”,我們發(fā)現(xiàn)不知道密碼也可以登錄成功。
這是因為當(dāng)我們的密碼為“' or '1'='1”時,SQL語句變?yōu)椋?br />
Select * FROM member Where username='magci' and password='' or '1'='1'
'1'='1'是永真的,這條SQL語句是能通過驗證的。
這就是SQL注入攻擊。
為了防止SQL注入攻擊,可以使用PraparedStatement對象操作數(shù)據(jù)庫。
改進后的登錄模塊如下:
附加功能:防止SQL注入攻擊
登錄模塊至少需要以下幾個頁面:
1.檢查Cookie頁面(index.jsp);
2.輸入用戶信息頁面(login.jsp);
3.用戶合法性驗證頁面(check.jsp);
4.登錄成功歡迎頁面(pass.jsp)(檢查Session設(shè)置);
5.登錄失敗提示頁面(failure.jsp);
6.注銷登錄頁面(logout.jsp)。
數(shù)據(jù)庫:member.mdb
結(jié)構(gòu)圖:
---------------------------------------------------------------------
index.jsp
|
|判斷Cookie中有無用戶名、密碼
----------------------
| Y N |
| V
| login.jsp<--------------------
| |輸入用戶名、密碼 |
| V |
---------------->check.jsp |
|查詢用戶名、密碼 |
V |
member.mdb |
|返回結(jié)果 |
V |
check.jsp |
|判斷用戶是否合法 |
--------------------- |
| Y N | |
V V |
pass.jsp failure.jsp------->|
| |
| 檢查session是否含有用戶名 |
----------------- |
| Y N | |
V V |
pass.jsp 跳轉(zhuǎn)------------------------->|
| |
|注銷 |
V |
logout.jsp------------------------------------>|
---------------------------------------------------------------------
index.jsp:
程序代碼
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>index</title>
</head>
<body>
<%
int i;
//初始化,用于保存Cookie中的用戶名、密碼
String C_username="";
String C_password="";
//獲取全部Cookie
Cookie c[]=request.getCookies();
for(i=0;i<c.length;i++)
{
//在Cookie中查找用戶名、密碼,如果找到,則分別將其賦值給用戶名、密碼變量
if("username".equals(c[i].getName()))
C_username=c[i].getValue();
if("password".equals(c[i].getName()))
C_password=c[i].getValue();
}
if(!"".equals(C_username) && !"".equals(C_password))
{
//Cookie中有用戶名、密碼,將用戶名、密碼提交到驗證頁面
response.sendRedirect("check.jsp?username="+C_username+"&password="+C_password);
}
else
{
//Cookie中沒有用戶名、密碼,跳轉(zhuǎn)到登錄頁面
%>
<jsp:forward page="login.jsp" />
<%
}
%>
</body>
</html>
login.jsp:
程序代碼
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>登錄</title>
</head>
<body>
<center>
<h1>登錄頁面</h1>
<hr>
<form action="check.jsp" method="post">
<table>
<tr>
<td>用戶名:</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td>密 碼:</td>
<td><input type="password" name="password" /></td>
</tr>
<tr>
<td>Cookie選項:</td>
<td>
<input type="radio" name="cookie" value="nosave" checked>不保存
<input type="radio" name="cookie" value="save">保存1分鐘
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="登錄" />
<input type="reset" value="重置" />
</td>
</tr>
</table>
</form>
</center>
</body>
</html>
check.jsp:
程序代碼
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.sql.*" %>
<html>
<head>
<title>驗證頁面</title>
</head>
<body>
<%
String Username=request.getParameter("username");
String Password=request.getParameter("password");
String IsCookie=request.getParameter("cookie");
//定義標(biāo)志,標(biāo)記是否為合法用戶,true為合法,false為非法
Boolean isUser=false;
//定義數(shù)據(jù)庫連接驅(qū)動
final String DBDRIVER="sun.jdbc.odbc.JdbcOdbcDriver";
//定義數(shù)據(jù)庫連接地址
final String DBURL="jdbc:odbc:member";
//定義變量存放SQL語句
String sql=null;
//定義數(shù)據(jù)庫連接對象
Connection conn=null;
//定義數(shù)據(jù)庫操作對象
PreparedStatement pstmt=null;
//定義結(jié)果集
ResultSet rs=null;
try{
//加載數(shù)據(jù)庫驅(qū)動
Class.forName(DBDRIVER);
//連接數(shù)據(jù)庫
conn=DriverManager.getConnection(DBURL);
//預(yù)預(yù)處SQL語句
sql="Select * FROM member Where username=? and password=?";
//實例化數(shù)據(jù)庫操作對象
pstmt=conn.prepareStatement(sql);
//設(shè)置psmt中“?”對應(yīng)的變量
pstmt.setString(1,Username);
pstmt.setString(2,Password);
//查詢數(shù)據(jù)庫,返回結(jié)果集
rs=pstmt.executeQuery();
if(rs.next())
{
//數(shù)據(jù)庫中有符合的記錄,合法用戶
isUser=true;
}
//關(guān)閉結(jié)果集
rs.close();
//關(guān)閉操作
pstmt.close();
//關(guān)閉連接
conn.close();
}
catch(Exception e)
{
System.out.println(e);
}
//判斷用戶名、密碼的合法性
if(isUser)
{
//合法用戶
if("save".equals(IsCookie))
{
//如果選擇了保存Cookie選項,則保存Cookie
Cookie c1=new Cookie("username",Username);
Cookie c2=new Cookie("password",Password);
//設(shè)置Cookie保存時間為1分鐘
c1.setMaxAge(60);
c2.setMaxAge(60);
response.addCookie(c1);
response.addCookie(c2);
}
//設(shè)置session屬性
session.setAttribute("username",Username);
//跳轉(zhuǎn)到歡迎頁面
%>
<jsp:forward page="pass.jsp"/>
<%
}
else
{
//非法用戶,跳轉(zhuǎn)到登錄失敗頁面
%>
<jsp:forward page="failure.jsp" />
<%
}
%>
</body>
</html>
pass.jsp:
程序代碼
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>登錄成功</title>
</head>
<body>
<center>
<%
//獲取session屬性值
String Mem_Session=(String)session.getAttribute("username");
if(Mem_Session!=null)
{
//session的username屬性里含有用戶名,可以瀏覽此頁面
%>
<h1>登錄成功!!</h1>
<hr>
<h3>歡迎<font size="12" color="red">
<%--forward跳轉(zhuǎn)為服務(wù)器端跳轉(zhuǎn),跳轉(zhuǎn)后仍在check.jsp頁面,可以繼續(xù)使用usename參數(shù) --%>
<%=request.getParameter("username") %>
</font>光臨!</h3>
<p>
<a href="logout.jsp">注銷登錄</a>
<%
}
else
{
//session的username屬性里沒有正確的用戶名,無法瀏覽此頁面,跳轉(zhuǎn)到登錄頁面
%>
<h1>您還沒有登錄!</h1>
3秒之后跳轉(zhuǎn)到登錄頁面
<p>
如果沒有跳轉(zhuǎn),請點<a href="login.jsp">這里</a>
<%
response.setHeader("refresh","3;URL=login.jsp");
}
%>
</center>
</body>
</html>
failure.jsp:
程序代碼
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>登錄失敗</title>
</head>
<body>
<div align="center">
<h1>登錄失敗!!</h1>
<hr>
<a href="login.jsp">重新登錄</a>
</div>
</body>
</html>
logout.jsp:
程序代碼
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>注銷登錄</title>
</head>
<body>
<%
//使session失效
session.invalidate();
%>
<center>
<h1>注銷成功!</h1>
3秒后跳轉(zhuǎn)到登錄頁面
<p>
如果沒有跳轉(zhuǎn),請點<a href="login.jsp">這里</a>
<%
response.setHeader("refresh","3;URL=login.jsp");
%>
</center>
</body>
</html>
本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/samsunge808/archive/2009/02/11/3878091.aspx