明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

在ASP.NET中創(chuàng)建安全的web網(wǎng)站

[摘要]以前用ASP,PHP,JSP編寫網(wǎng)站代碼的時(shí)候,站點(diǎn)安全性總是一件頭疼的事情,雖然我們編寫了用戶登錄,注冊(cè),驗(yàn)證頁(yè)面,但是效果總是不理想。有時(shí)候我們不得不用大量的session變量來(lái)存放相關(guān)信息,處處設(shè)防。而在.NET環(huán)境下,這個(gè)問(wèn)題處理起來(lái)就非常容易了。關(guān)鍵是要充分理解web.config文件。...

以前用ASP,PHP,JSP編寫網(wǎng)站代碼的時(shí)候,站點(diǎn)安全性總是一件頭疼的事情,雖然我們編寫了用戶登錄,注冊(cè),驗(yàn)證頁(yè)面,但是效果總是不理想。有時(shí)候我們不得不用大量的session變量來(lái)存放相關(guān)信息,處處設(shè)防。而在.NET環(huán)境下,這個(gè)問(wèn)題處理起來(lái)就非常容易了。關(guān)鍵是要充分理解web.config文件。首先,介紹一下web.config文件。 <?xml version="1.0" encoding="utf-8" ?>
<configuration><system.web><!-- 動(dòng)態(tài)調(diào)試編譯
設(shè)置 compilation debug="true" 以將調(diào)試符號(hào)(.pdb 信息)
插入到編譯頁(yè)中。因?yàn)檫@將創(chuàng)建執(zhí)行起來(lái)
較慢的大文件,所以應(yīng)該只在調(diào)試時(shí)將該值設(shè)置為 true,而所有其他時(shí)候都設(shè)置為
false。有關(guān)更多信息,請(qǐng)參考有關(guān)
調(diào)試 ASP.NET 文件的文檔。
-->
<compilation defaultLanguage="vb" debug="true" /><!-- 自定義錯(cuò)誤信息
設(shè)置 customErrors mode="On" 或 "RemoteOnly" 以啟用自定義錯(cuò)誤信息,或設(shè)置為 "Off" 以禁用自定義錯(cuò)誤信息。
為每個(gè)要處理的錯(cuò)誤添加 <error> 標(biāo)記。
-->
<customErrors mode="RemoteOnly" /><!-- 身份驗(yàn)證
此節(jié)設(shè)置應(yīng)用程序的身份驗(yàn)證策略?赡艿哪J绞 \“Windows\”、
\“Forms\”、\“Passport\”和 \“None\”
-->
<authentication mode="Windows" />
<!-- 授權(quán)
此節(jié)設(shè)置應(yīng)用程序的授權(quán)策略。可以允許或拒絕用戶或角色訪問(wèn)
應(yīng)用程序資源。通配符:"*" 表示任何人,"?" 表示匿名
(未授權(quán)的)用戶。
-->
<authorization>
<allow users="*" /> <!-- 允許所有用戶 --><!-- <allow users="[逗號(hào)分隔的用戶列表]"
roles="[逗號(hào)分隔的角色列表]"/>
<deny users="[逗號(hào)分隔的用戶列表]"
roles="[逗號(hào)分隔的角色列表]"/>
-->
</authorization><!-- 應(yīng)用程序級(jí)別跟蹤記錄
應(yīng)用程序級(jí)別跟蹤在應(yīng)用程序內(nèi)為每一頁(yè)啟用跟蹤日志輸出。
設(shè)置 trace enabled="true" 以啟用應(yīng)用程序跟蹤記錄。如果 pageOutput="true",則
跟蹤信息將顯示在每一頁(yè)的底部。否則,可以通過(guò)從 Web 應(yīng)用程序
根瀏覽 "trace.axd" 頁(yè)來(lái)查看
應(yīng)用程序跟蹤日志。
-->
<trace enabled="false" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true" />
<!-- 會(huì)話狀態(tài)設(shè)置
默認(rèn)情況下,ASP.NET 使用 cookie 標(biāo)識(shí)哪些請(qǐng)求屬于特定的會(huì)話。
如果 cookie 不可用,則可以通過(guò)將會(huì)話標(biāo)識(shí)符添加到 URL 來(lái)跟蹤會(huì)話。
若要禁用 cookie,請(qǐng)?jiān)O(shè)置 sessionState cookieless="true"。
-->
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;user id=sa;password="
cookieless="false"
timeout="20"
/><!-- 全球化
此節(jié)設(shè)置應(yīng)用程序的全球化設(shè)置。
-->
<globalization requestEncoding="utf-8" responseEncoding="utf-8" /></system.web></configuration>好了,相信看過(guò)上面的介紹以后,對(duì)web.config文件一定非常了解了吧。下面我們就切入主題。為了防止用戶沒(méi)有經(jīng)過(guò)驗(yàn)證就訪問(wèn)站點(diǎn),我們的處理方法是當(dāng)用戶沒(méi)有通過(guò)驗(yàn)證的時(shí)候點(diǎn)擊任何頁(yè)面將會(huì)直接跳到Login.aspx頁(yè)面,具體代碼如下:<authentication mode="Forms">
<forms name="yourAuthCookie" loginUrl="login.aspx"
protection="All" path="/" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
但是這樣會(huì)產(chǎn)生一個(gè)問(wèn)題,那就是如果我的站點(diǎn)有一些信息是可以讓任意用戶隨意訪問(wèn)的,比如站點(diǎn)簡(jiǎn)介,使用說(shuō)明等。如果按照上面的處理方法豈不讓用戶覺(jué)得很麻煩,呵呵,不急,在ASP.NET中自然有相應(yīng)的解決辦法。下面的代碼可以實(shí)現(xiàn)匿名用戶訪問(wèn)Test.aspx頁(yè)面:<location path="test.aspx">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>解決了上面兩個(gè)問(wèn)題,相信大家心里一定有底了吧。下面就開(kāi)始實(shí)現(xiàn)login.aspx頁(yè)面。利用C#和SQL Server2000,創(chuàng)建一個(gè)webform頁(yè)面,加入相應(yīng)的控件。具體代碼如下:<%@ Page language="c#" Codebehind="login.aspx.cs"
AutoEventWireup="false" Inherits="secure.login" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>Secure Site</title>
<meta content="Microsoft Visual Studio 7.0" name="GENERATOR">
<meta content="C#" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<meta content="http://schemas.microsoft.com/intellisense/ie5"
name="vs_targetSchema">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="login" method="post" runat="server">
<table cellSpacing="0" cellPadding="0" border="0">
<tr>
<td vAlign="top" align="left">
<asp:label id="Message" Runat="server" ForeColor="#ff0000">
</asp:label>
</td>
</tr>
<tr>
<td vAlign="top" align="left">
<b>E-mail:</b>
</td>
</tr>
<tr>
<td vAlign="top" align="left">
<asp:textbox id="username" Runat="server" Width="120">
</asp:textbox>
</td>
</tr>
<tr>
<td vAlign="top" align="left">
<b>Password:</b>
</td>
</tr>
<tr>
<td vAlign="top" align="left">
<asp:textbox id="password" Runat="server"
Width="120" TextMode="Password">
</asp:textbox>
</td>
</tr>
<tr>
<td vAlign="top" align="left">
<asp:checkbox id="saveLogin" Runat="server"
Text="<b>Save my login</b>">
</asp:checkbox>
</td>
</tr>
<tr>
<td vAlign="top" align="right">
<asp:imagebutton id="btnLogin" Runat="server"
ImageUrl="/images/w2k/login/btnLogin.gif">
</asp:imagebutton>
</td>
</tr>
</table>
</form>
</body>
</HTML>
界面做好之后,就開(kāi)始編寫提交按鈕事件,首先需要注冊(cè)該事件,代碼如下:private void InitializeComponent()
{
this.btnLogin.Click += new System.Web.UI.ImageClickEventHandler(this.btnLogin_Click);
.
.
.
}
事件注冊(cè)好之后,自然就是編寫事件處理函數(shù)了:private void btnLogin_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
CCommonDB sql = new CCommonDB();
string redirect = "";if((redirect = sql.AuthenticateUser(this.Session, this.Response,
username.Text, password.Text, saveLogin.Checked)) != string.Empty)
{
// Redirect the user
Response.Redirect(redirect);
}
else
{
Message.Text = "Login Failed!";
}
}
讀者看完上面的代碼之后一定想問(wèn)CCommonDB是哪里來(lái)的東東,這是我編寫的一個(gè)類,用來(lái)處理用戶登錄信息的,如果成功則把相關(guān)信息寫入session、Cookie和SQL數(shù)據(jù)庫(kù),同時(shí)跳到default.aspx頁(yè)面。具體如下:CCommonDB.csnamespace secure.Components
{
public class CCommonDB : CSql
{
public CCommonDB() : base() { }public string AuthenticateUser(
System.Web.SessionState.HttpSessionState objSession, // Session Variable
System.Web.HttpResponse objResponse, // Response Variable
string email, // Login
string password, // Password
bool bPersist // Persist login
)
{
int nLoginID = 0;
int nLoginType = 0;// Log the user in
Login(email, password, ref nLoginID, ref nLoginType);if(nLoginID != 0) // Success
{
// Log the user in
System.Web.Security.FormsAuthentication.SetAuthCookie(nLoginID.ToString(), bPersist);// Set the session varaibles
objSession["loginID"] = nLoginID.ToString();
objSession["loginType"] = nLoginType.ToString();// Set cookie information incase they made it persistant
System.Web.HttpCookie wrapperCookie = new System.Web.HttpCookie("wrapper");
wrapperCookie.Value = objSession["wrapper"].ToString();
wrapperCookie.Expires = DateTime.Now.AddDays(30);System.Web.HttpCookie lgnTypeCookie = new System.Web.HttpCookie("loginType");
lgnTypeCookie.Value = objSession["loginType"].ToString();
lgnTypeCookie.Expires = DateTime.Now.AddDays(30);// Add the cookie to the response
objResponse.Cookies.Add(wrapperCookie);
objResponse.Cookies.Add(lgnTypeCookie);return "/candidate/default.aspx";
}
case 1: // Admin Login
{
return "/admin/default.aspx";
}
case 2: // Reporting Login
{
return "/reports/default.aspx";
}
default:
{
return string.Empty;
}
}
}
else
{
return string.Empty;
}
}/// <summary>
/// Verifies the login and password that were given
/// </summary>
/// <param name="email">the login</param>
/// <param name="password">the password</param>
/// <param name="nLoginID">returns the login id</param>
/// <param name="nLoginType">returns the login type</param>
public void Login(string email, string password, ref int nLoginID, ref int nLoginType)
{
ResetSql();DataSet ds = new DataSet();// Set our parameters
SqlParameter paramLogin = new SqlParameter("@username", SqlDbType.VarChar, 100);
paramLogin.Value = email;SqlParameter paramPassword = new SqlParameter("@password", SqlDbType.VarChar, 20);
paramPassword.Value = password;
Command.CommandType = CommandType.StoredProcedure;
Command.CommandText = "glbl_Login";
Command.Parameters.Add(paramLogin);
Command.Parameters.Add(paramPassword);Adapter.TableMappings.Add("Table", "Login");
Adapter.SelectCommand = Command;
Adapter.Fill(ds);if(ds.Tables.Count != 0)
{
DataRow row = ds.Tables[0].Rows[0];// Get the login id and the login type
nLoginID = Convert.ToInt32(row["Login_ID"].ToString());
nLoginType = Convert.ToInt32(row["Login_Type"].ToString());
}
else
{
nLoginID = 0;
nLoginType = 0;
}
}
}abstract public class CSql
{
private SqlConnection sqlConnection; // Connection string
private SqlCommand sqlCommand; // Command
private SqlDataAdapter sqlDataAdapter; // Data Adapter
private DataSet sqlDataSet; // Data Setpublic CSql()
{
sqlConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString"]);
sqlCommand = new SqlCommand();
sqlDataAdapter = new SqlDataAdapter();
sqlDataSet = new DataSet();sqlCommand.Connection = sqlConnection;
}/// <summary>
/// Access to our sql command
/// </summary>
protected SqlCommand Command
{
get { return sqlCommand; }
}/// <summary>
/// Access to our data adapter
/// </summary>
protected SqlDataAdapter Adapter
{
get { return sqlDataAdapter; }
}/// <summary>
/// Makes sure that everything is clear and ready for a new query
/// </summary>
protected void ResetSql()
{
if(sqlCommand != null)
{
sqlCommand = new SqlCommand();
sqlCommand.Connection = sqlConnection;
}
if(sqlDataAdapter != null)
sqlDataAdapter = new SqlDataAdapter();if(sqlDataSet != null)
sqlDataSet = new DataSet();
}/// <summary>
/// Runs our command and returns the dataset
/// </summary>
/// <returns>the data set</returns>
protected DataSet RunQuery()
{
sqlDataAdapter.SelectCommand = Command;sqlConnection.Open();
sqlConnection.Close();sqlDataAdapter.Fill(sqlDataSet);return sqlDataSet;
}
}
}(出處:Viphot)