麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > .NET > 正文

Asp.Net實現FORM認證的一些使用技巧(必看篇)

2024-07-10 13:31:12
字體:
來源:轉載
供稿:網友

最近因為項目代碼重構需要重新整理用戶登錄和權限控制的部分,現有的代碼大體是參照了.NET的FORM認證,并結合了PORTAL KITS的登錄控制,代碼比較啰嗦,可維護性比較差。于是有了以下的幾個需求(大多數系統應該都會碰到):

1.用.NET自帶的FORM認證來實現安全登錄

2.登錄后需要記錄登錄用戶的基本信息,方便所有頁面調用

3.記錄本機登錄狀態,短時間關閉窗口后不用重新登錄

4.權限控制和代碼的文件夾結構相呼應,即按角色允許訪問不同的目錄

5.權限控制有可能需要細化到每一個頁面,即按角色允許訪問不同的頁面

6.以上的部分盡量自己少寫代碼,用自帶的類庫和機制實現

第一步:準備工作

先準備一個名為Test的WEB項目,包含:

Default.aspx,默認頁,隨便顯示一些信息,

Login.aspx,登錄頁,上面放兩個文本框,用來輸入用戶名和密碼,一個登錄按鈕,一個指向Register.aspx的超鏈,

Register.aspx,用戶注冊頁,注冊用戶信息,隨便放一點文本框,主要是模擬一下注冊,不用真正實現,

Web.config,配置頁面。

注冊頁與登錄頁在同一目錄的機妙后面會說。

第二步:Web.config文件的修改

1、打開Web.config文件,找到authentication節,將其改為如下:

<authentication mode="Forms">  <forms name=".ASPXAUTH" loginUrl="Login.aspx" protection="All" path="/" timeout="20"/></authentication><authorization>  <deny users="?"></deny></authorization>

配置節屬性的具體意義和其他沒有加入的屬性網上到處都有查。這里注意一下的是authentication節和authorization節,兩個單詞很相似,但卻不是同一個單詞,每個節下面的內容也不能寫到一起。

其中,authorization節中的“allow”表示允許的意思,“*”表示所有用戶;而“deny”表示拒絕的意思;“?”表示匿名用戶;此處加入后,則代表根目錄下的所有文件和所有的子目錄都不能匿名訪問,Login.aspx 頁面除外。

2、Web.config中,Location節的應用

做了上面的配置之后,我們會發現,在沒登錄的情況下,用瀏覽器打開Default.aspx會自動轉到Login.aspx,同理Register.aspx頁面也會如此。問題:注冊用戶怎么可能在登錄后才能訪問呢?

那么我們就得說了,當注冊頁與登錄頁在同一目錄,為了達到不用登錄就能訪問注冊頁的目的,我們就得對訪問限制的Web.config配置處理一下。

方法一 :注冊頁與登錄頁放在不的目錄內

我們在根目錄添加一個文件夾Pub,將Register.aspx移動到此文件夾里,此時仍不能訪問,需要在文件夾內添加一個Web.config文件,加入:

<configuration>  <system.web>   <authorization>   <allow users="*"/>  </authorization>  </system.web> </configuration> 

此處,即說明此目錄下的所有文件,允許所有人訪問。

關于 Web.config 作用范圍的說明:

• Web.config 的設置將作用于所在目錄的所有文件及其子目錄下的所有東東(繼承:子隨父姓)

• 子目錄下的 Web.config 設置將覆蓋由父目錄繼承下來的設置(覆蓋:縣官不如現管)

• 也就是,屬性設置由最深一層的目錄里的Web.config決定;如果子目錄里沒有Web.config文件,則由離它最近的父目錄里的Web.config決定

方法二:仍然保持注冊頁和登錄頁在同一目錄下

只需要在根目錄下的Web.config 中加入以下一段:

<location path="Register.aspx"> <system.web>   <authorization>    <allow users="*"/>   </authorization> </system.web></location>

通過location節的path屬性的值指定Register.aspx頁面,以及下面authorization節的設置,說明了Register.aspx頁面是允許被所有人訪問。

注意:

location節應加在原有的system.web節的外面,包含在configuration節內,和system.web節是同級的。  

當根目錄下,有多個頁面不需要登錄就可以訪問時,可以設置多個location節,修改對應path屬性值指向的頁面就可以了。

另外,path屬性的值也可以指定目錄,用來指定該目錄的訪問限制。通過修改authorization節的內容來限定訪問權限。詳細的設置,后面會提到。

第三步:實現登錄的代碼

1、普通的代碼實現

方法一:

如果forms節中設置了“defaultUrl”的屬性,也就是登錄后默認轉向的頁面,則可以用如下的方法:

private void Btn_Login_Click(object sender, System.EventArgs e) {  if(this.Txt_UserName.Text=="Admin" && this.Txt_Password.Text=="123456")  {    FormsAuthentication.RedirectFromLoginPage(this.Txt_UserName.Text,false);  } } 

此處只是簡單模擬了一下登錄的驗證過程,RedirectFromLoginPage方法能發送驗證票據驗證Cookie(如何進行可以用Reflector去查看源代碼),返回請求頁面,即“從哪來就打哪去”。比如:用戶沒登錄前直接在 IE 地址欄輸入 http://localhost/Test/Default.aspx ,那么該用戶將看到的是 Login.aspx?ReturnUrl=Default.aspx ,輸入用戶名與密碼登錄成功后,系統將根據“ReturnUrl”的值,返回相應的頁面;如果沒有“ReturnUrl”,則按照“defaultUrl”的屬性自動轉向。

方法二:

private void Btn_Login_Click(object sender, System.EventArgs e){   if(this.Txt_UserName.Text=="Admin" && this.Txt_Password.Text=="123456")   {    FormsAuthentication.SetAuthCookie(this.Txt_UserName.Text,false);    Response.Redirect("Default.aspx");   } } 

此處是分兩步走:通過驗證后就直接發放 Cookie ,跳轉頁面將由程序員自行指定,無需“defaultUrl”設置。此方法對于程序員來說,更靈活。  

 

2、手工實現需要記錄用戶登錄信息的情況

當我們需要記錄用戶登錄的信息,不單單只是一個ID還需要更多屬性的時候,一般都用一個類存儲到Session或Cookie實現,然后做一個基類頁,在基類頁中設置屬性來讀取Session或Cookie。

Session實際也和支不支持Cookie有關,且存在服務器,多少會占用服務器端資源。因此這里還是考慮用Cookie實現。那么在RedirectFromLoginPage方法或SetAuthCookie方法已經設置了驗證票據并設置了Cookie,我們能不能把用戶登錄信息也存儲到這個默認的Cookie里呢?答案是能。

首先,我們在項目里添加AppCode目錄,增加一個UserInfo的類,用以簡單模擬用戶登錄信息。代碼如下:

[Serializable]public class UserInfo{  //用戶登錄信息  private int _nId;  private string _sRealName;  private string _sName;    private string _sPassword;  private string _sRoles;  public int Id  {    get { return this._nId; }    set { this._nId = value; }  }  public string RealName  {    get { return this._sRealName; }    set { this._sRealName = value; }  }  public string Name  {    get { return this._sName; }    set { this._sName = value; }  }  public string Password  {    get { return this._sPassword; }    set { this._sPassword = value; }  }  public string Roles  {    get { return this._sRoles; }    set { this._sRoles = value; }  }  public UserInfo()  {      }}

需要注意, 類的屬性中一定要加[Serializable],表示類可以序列化。

 

Forms驗證在內部的機制是,把用戶數據加密后保存在一個基于cookie的票據FormsAuthenticationTicket中,通過RedirectFromLoginPage方法或SetAuthCookie方法就已經實現了Ticket和Cookie的設置,也就是設置了Context.User的值,Context.User在取值和判斷是否經過驗證的時候很有用處。Cookie的屬性是在Web.config的<forms name=".ASPXAUTH" loginUrl="Login.aspx" protection="All" path="/" timeout="20"/>中設置的。因為是經過特殊加密的,所以應該來說是比較安全的。

而.net除了用這個票據存放自己的信息外,還留了一個地給用戶自由支配,這就是現在要說的Ticket的UserData。 UserData用來存儲string類型的信息,并且也享受Forms驗證提供的加密保護,當我們需要這些信息時,也可以通過簡單的Ticket的 UserData屬性得到,兼顧了安全性和易用性,用來保存一些必須的敏感信息還是很有用的。我們就準備將用戶的登錄信息記錄在UserData中,代碼如下:

protected void Button1_Click(object sender, EventArgs e)  {    if (this.TextBox1.Text == "Admin" && this.TextBox2.Text == "123456")    {      // 加密UserInfo      UserInfo user = new UserInfo();      user.Id = 1;      user.Name = this.TextBox1.Text;      user.Password = this.TextBox2.Text;      user.RealName = "系統管理員";      user.Roles = "Administrators,Users";      string strUser = Serialize.Encrypt<UserInfo>(user);      // 設置Ticket信息      FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(        1, user.Name, DateTime.Now, DateTime.Now.AddMinutes(20), false, strUser);      // 加密驗證票據      string strTicket = FormsAuthentication.Encrypt(ticket);      // 使用新userdata保存cookie      HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strTicket);      cookie.Expires = ticket.Expiration;      this.Response.Cookies.Add(cookie);            this.Response.Redirect("Default.aspx");    }}

上面的代碼,實際上類似于手工實現了SetAuthCookie方法的過程。

首先,模擬實現登錄,我們手動設置了一個UserInfo的對象,string strUser = Serialize.Encrypt<UserInfo>(user) 是將對象序列化成字符串的一個方法。

  然后,生成一個FormsAuthenticationTicket票據。此處用到的FormsAuthenticationTicket構造函數的重載方法的簽名解釋

public FormsAuthenticationTicket(     int version, //版本號    string name, //與身份驗證票關聯的用戶名    DateTime issueDate, //票據的發出時間    DateTime expiration,//票據的到期日期    bool isPersistent, //票據是否存儲在持久的 Cookie 中,是為 true;否則為 false    string userData //票據中存儲的用戶定義數據);

再后,string strTicket = FormsAuthentication.Encrypt(ticket) 將票據加密成字符創

最后,HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strTicket) 生成Cookie。

FormsAuthentication.FormsCookieName獲取的就是Web.config中配置的Cookie名稱,也就是默認驗證時產生的Cookie。cookie.Expires = ticket.Expiration 將票據的過期時間和Cookie的過期時間做了同步,也就避免了兩者不同所產生的矛盾。這樣,驗證票據生成了,存儲到默認配置的Cookie中,也就是類似實現了一個SetAuthCookie方法的過程。通過Context.User就能獲取票據的相關信息了。

3、獲取信息

為了在其他登錄后的頁面比較簡單的獲取登錄用戶信息,我們先生成一個基類頁面。在AppCode中新增LoginBasePage類,代碼如下:

public class LoginBasePage : Page{  protected UserInfo LoginUser  {    get    {      string strUser = ((FormsIdentity)this.Context.User.Identity).Ticket.UserData;      return Serialize.Decrypt<UserInfo>(strUser);            }  }  public LoginBasePage()  {    //    // TODO: 在此處添加構造函數邏輯    //  }}

LoginBasePage : Page,基類頁要繼承Page,成為所有登錄以后的頁面的基類。

屬性protected UserInfo LoginUser{ get;}用來訪問登錄信息。將Context.User.Identity強制轉換為FormsIdentity類的對象,通過訪問Ticket屬性的UserData屬性,獲得被序列化后的對象的字符串,最后用方法Serialize.Decrypt<UserInfo>(strUser)將字符串反序列化成對象后再返回UserInfo類型的對象。

我們只需要將Default頁面的后臺代碼改為public partial class _Default : LoginBasePage,就可以通過this.LoginUser來訪問用戶登錄信息了。

第四步:實現不同目錄的權限控制

上面,實現了記錄用戶登錄信息的模擬登錄過程,以及根目錄下文件的訪問控制。但是系統一般都會有多個目錄,接下來就說說目錄的訪問控制。

其實,上面多多少少已經提到過了,通過在每個目錄下增加Web.config文件來進行訪問限制。

首先,我們在根目錄增加一個文件夾ManageAdmin,在此文件夾內增加頁面UserInfo.aspx,頁面內放幾個Label用來展現登錄用戶信息。

然后,再增加一個Web.config文件,配置內容如下:

<configuration>  <appSettings/>  <connectionStrings/>  <system.web>    <authorization>      <allow users="Admin"></allow>      <deny users="*"></deny>    </authorization>  </system.web></configuration>

配置中說明只允許“Admin”用戶訪問,禁止其他所有用戶訪問。

這里,特別要注意的是,FormsAuthenticationTicket票據的name屬性的賦值,一定要和<allow users="Admin"></allow>設置的用戶想對應,且大小寫敏感。如果要設置允許多個用戶訪問,則用“,”隔開,例如<allow users="Admin,User1"></allow>。

不同的目錄,設置不同的允許訪問的用戶,就可以對所有目錄進行訪問控制了。

第五步:實現不同目錄的按角色的權限控制

以上實現了對不同目錄按用戶的訪問限制。但是一般來說,一個網站系統的用戶會很多,如果一直使用精確到用戶的訪問控制,則會造成設置Web.config的工作量加大。

而一般,我們會將用戶分到不同的用戶組來進行權限控制,因此,我們也可以配置Web.config實現按角色來控制不同的目錄的訪問權限。

首先,我們在根目錄下再增加一個目錄ManageUsers,在此文件夾內也增加頁面UserInfo.aspx用來展現登錄用戶信息。此目錄將模擬控制Users組的用戶,文件夾ManageAdmin將模擬控制Administrators組的用戶。

然后,在目錄ManageUsers增加Web.config文件,配置內容如下:

<configuration>  <appSettings/>  <connectionStrings/>  <system.web>    <authorization>      <allow roles="Users"></allow>      <deny users="*"></deny>    </authorization>  </system.web></configuration>

再將文件夾ManageAdmin下的Web.config文件的<allow users="Admin"></allow>改成<allow roles="Administrators"></allow>

最后,修改代碼。

1、注意,我們在模擬用戶信息的時候,有這么一句,user.Roles = "Administrators,Users";也就是用戶Admin具備兩種角色

2、為模擬Users組的用戶登錄,我們再添加如下代碼:

if (this.TextBox1.Text == "User1" && this.TextBox2.Text == "111111"){      // 加密UserInfo      UserInfo user = new UserInfo();      user.Id = 2;      user.Name = this.TextBox1.Text;      user.Password = this.TextBox2.Text;      user.RealName = "普通用戶1";      user.Roles = "Users";      string strUser = Serialize.Encrypt<UserInfo>(user);      // 設置Ticket信息      FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(        1, user.Name, DateTime.Now, DateTime.Now.AddMinutes(20), false, strUser);      // 加密驗證票據      string strTicket = FormsAuthentication.Encrypt(ticket);      // 使用新userdata保存cookie      HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strTicket);      cookie.Expires = ticket.Expiration;      this.Response.Cookies.Add(cookie);            this.Response.Redirect("Default.aspx"); }

這樣,我們登錄時,輸入“Admin”和“User1”的時候,就可以模擬不同角色的用戶登錄了。

3、Forms基于角色的驗證的內部機制是,將角色的屬性也設置到了Context.User中,這里也需要手工代碼處理一下。  

首先,為了支持基于角色的驗證,我們每進入一個頁面都需要將角色信息設置到Context.User中,那么最好的辦法就是在Global.asax 文件中的Application_AuthenticateRequest方法中設置。

Application_AuthenticateRequest方法,是在每次驗證請求時觸發,它與另外一個方法Application_BeginRequest的區別就在于,Application_AuthenticateRequest方法內,能夠訪問Context.User.Identity,而Application_BeginRequest則無法訪問。

我們在根目錄添加一個Global.asax 文件,增加如下代碼:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)  {    if (this.Context.User != null)    {      if (this.Context.User.Identity.IsAuthenticated)      {        if (this.Context.User.Identity is FormsIdentity)        {          string strUser = ((FormsIdentity)this.Context.User.Identity).Ticket.UserData;          string[] roles = Serialize.Decrypt<UserInfo>(strUser).Roles.Split(',');          this.Context.User = new GenericPrincipal(this.Context.User.Identity, roles);        }      }    }  }

此處,主要代碼就是將Context.User.Identity強制轉換為FormsIdentity類的對象,通過訪問Ticket屬性的UserData屬性,獲得被序列化后的對象的字符串,最后用方法Serialize.Decrypt<UserInfo>(strUser)將字符串反序列化成對象,再將UserInfo對象的Roles屬性以“,”為分隔符分隔成角色數組,再用Context.User.Identity和角色數組生成一個新的GenericPrincipal對象,賦值給Context.User ,則Context.User 為已經設置好角色的驗證對象。

按照我們的設置,Admin用戶能訪問兩個目錄,而User1用戶,則只能訪問ManageUsers一個目錄。

第六步:集中管理Web.config文件

目錄的訪問權限控制,是按用戶還是按角色,一般由具體業務決定。

但是,隨著目錄的增多,每個目錄下都存在一個Web.config文件,管理起來特別不方便。

通過上面提到過的location節的path屬性,我們可以實現Web.config配置的統一管理。我們可以將各個文件或目錄的配置都放置在根目錄的Web.config文件內,代碼如下:

<configuration>  <appSettings/>  <connectionStrings/>  <location path ="Register.aspx">    <system.web>      <authorization>        <allow users="*"/>      </authorization>    </system.web>  </location>    <location path ="ManageAdmin">    <system.web>      <authorization>        <allow roles="Administrators"></allow>          <deny users="*"></deny>      </authorization>    </system.web>  </location>    <location path ="ManageUsers">    <system.web>      <authorization>        <allow roles="Users"></allow>          <deny users="*"></deny>      </authorization>    </system.web>  </location>    <system.web>    <!-- 這里放置原來根目錄 Web.config 的內容,就不列出來了 -->     </system.web></configuration>

結尾:

這次徹底理順FORM驗證的過程,發現了不少實用性很強的技巧,中間參考了很多網友的文章,也通過Reflector看了一下具體實現的源代碼。感覺收獲不少,最大的收獲就是對于問題不但要知其然更要知其所以然,要有一種打破沙鍋問到底的凈勝。

大家如果有什么問題有什么疑問,不但要找到解決的辦法,有時間的話最好從理論到底層代碼都好好過一過,對自己的水平長進有很大的幫助。

以上這篇Asp.Net實現FORM認證的一些使用技巧(必看篇)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到ASP.NET教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 久久午夜免费视频 | 久久久成人免费视频 | 日韩av在线网 | 91精品视频网址 | 国产免费黄色 | 成人毛片100部免费观看 | 亚洲网站在线观看视频 | www嫩草| av成人免费看 | 国产免费一区二区三区 | 黄色网址免费进入 | 一级成人在线 | 午夜视频国产 | 免费放黄网站在线播放 | 亚洲婷婷日日综合婷婷噜噜噜 | chinese-xvideos| 中文字幕电影免费播放 | 日韩av在线网 | 欧美性精品videofree | 欧美色大成网站www永久男同 | 国产精品成人av片免费看最爱 | 特级a欧美做爰片毛片 | 国产精品免费一区二区 | 99国内精品视频 | 国产精品国产三级国产在线观看 | av在线播放地址 | 免费在线观看成人av | 久久精品九九 | 欧美 国产 综合 | 韩国一级免费视频 | 一区二区三区在线观看免费视频 | 免费在线观看中文字幕 | 一区二区三区欧美在线 | 干少妇av | 国产精品免费视频观看 | 九九视频精品在线 | 久久精品视频首页 | 国产精品久久久久久久久久了 | 久久精品视频网站 | 99精品在线免费 | 亚洲精品aaaaa |