2013-12-23 86 views
0

我正在開發一個Intranet Web應用程序(asp.net和C#),現在我已經到達了安全和訪問控制界標。基於列表表單身份驗證和隱藏菜單項的角色

的應用程序有:

  • 的Login.aspx頁
  • Home.aspx頁(僅在登錄後訪問)(可通過公司內部的任何訪問)上有一個菜單左邊的所有部門網頁和退出按鈕不火
幾個部門的網頁

現在,我通過應用程序使用的數據庫上的「用戶」表獲得了登錄系統的工作方式(FORMS AUTHENTICATION),然而在搜索了相當長的一段時間之後,我不知道如何實現角色以限制訪問部門頁面和隱藏菜單選項。

這裏是在VS Express的網絡解決方案結構:

structure

「用戶」表中的記錄是這樣的,你可以看到,詹姆斯是特殊的,可以訪問多個頁面:

Users

我計劃有以下情況:

  • 用戶只能訪問其部門網頁

  • 某些用戶可以訪問其他部門的網頁

我知道我必須有這樣的事情,在網絡上的配置,但如何如果我有表格身份驗證,我可以完成嗎?:

<location path="Marketing.aspx"> 
<system.web> 
    <authorization> 
     <deny roles="AD\Grupo Planeamento"/> 
     <allow roles="AD\Grupo Marketing"/> 
    </authorization> 
</system.web> 

現在到了代碼,Page_Load事件中的所有網頁上是空的

母版頁

<div class="span4"> 
       <asp:ContentPlaceholder ID="menu_lateral" runat="server"> 
        <ul class="nav nav-list"> 
          <li class="nav-header">Departamentos</li> 
          <li><a href="Comercial.aspx" title="Comercial">Comercial</a></li> 
          <li><a href="Compras.aspx">Compras</a></li> 
          <li><a href="Contabilidade.aspx">Contabilidade</a></li> 
          <li><a href="Controloegestao.aspx">Controlo e Gestão</a></li> 
          <li><a href="Exportação.aspx">Exportação</a></li> 
          <li><a href="Manutenção.aspx">Manutenção</a></li> 
          <li><a href="Matérias Primas.aspx">Matérias Primas</a></li> 
          <li><a href="Mercado Nacional.aspx">Mercado Nacional</a></li> 
          <li><a href="Planeamento.aspx">Planeamento</a></li> 
          <li><a href="Qualidade.aspx">Qualidade</a></li> 
          <li><a href="Tesouraria.aspx">Tesouraria</a></li> 
        </ul> 
       </asp:ContentPlaceholder> 
      </div> 

Webconfig

<system.web> 
<authentication mode="Forms"> 
    <forms name="frmlogin" /> 
    <!—if i add 「loginUrl="Login.aspx"」 I can only login at the second page load/attempt, dunno why />--> 
</authentication> 
    <authorization> 
     <deny users="?"/> 
    </authorization> 

的Login.aspx

<asp:Content ID="rightcontentdown" ContentPlaceHolderID="rightcontentdown" Runat="Server"> 
<form id="frmlogin" runat="server"> 
      <table class="logintable"> 
      <tr><th colspan="3" rowspan="1">Login</th> 
      <tr><td>User:</td> 
       <td colspan="2" rowspan="1"><input id="UserNameTextBox" type="text" runat="server"></td> 
       <td colspan="2" rowspan="1"><asp:RequiredFieldValidator ID="vUserName" ControlToValidate="UserNameTextBox" Display="Static" ErrorMessage="Username Inválido" runat="server" /></td> 

      <tr> 
       <td>Password:</td> 
       <td colspan="2" rowspan="1"><input id="PasswordTextBox" type="password" runat="server"></td> 
       <td colspan="2" rowspan="1"><asp:RequiredFieldValidator ID="vUserPass" ControlToValidate="PasswordTextBox" Display="Static" ErrorMessage="Password Inválida" runat="server" /></td> 

      <tr> 
       <td><asp:Button ID="LoginButton" runat="server" Text="Login" onclick="LoginButton_Click" /><asp:CheckBox id="RemPassword" runat="server" autopostback="false" text="Lembrar-me"/></td> 
      <tr> 
       <td><asp:Label id="MsgLabel" runat="server" /></td> 

     </table> 
</form> 
上菜單

Login.aspx。CS

private bool ValidateUser(string userName, string password) 
{ 
    SqlConnection conn; 
    SqlCommand cmd; 
    string pwd = null; 

    //Checks for invalid userName 
    //username must not be null 
    if ((userName == null) || (userName.Length == 0)) 
    { 
     return false; 
    } 

    //checks for invalid password, password should not be null 
    if ((password == null) || (password.Length == 0)) 
    { 
     return false; 
    } 

    try 
    { 
     //Creating connection to the sql server 
     //Connection string is fetched from web.config file, see TestDb1ConnectionString there 
     conn = new SqlConnection(GetConnectionString()); 
     conn.Open(); //Opening connection 

     string sqlcmd = "Select PASSWORD from [Users] where [email protected]"; 
     cmd = new SqlCommand(sqlcmd, conn); 
     cmd.Parameters.Add("@username", System.Data.SqlDbType.VarChar).Value = userName; 

     // Execute command and fetch password field into pwd string 
     pwd = (string)cmd.ExecuteScalar(); 

     //Cleanup command and close connection 
     cmd.Dispose(); 
     conn.Close(); 
     if (pwd == password) 
      return true; // Validates the user and return true 
     else 
      return false; 
    } 
    catch (Exception ex) 
    { 
     // Add errer handling code here 
     throw ex; 
    } 
} 

protected void LoginButton_Click(object sender, EventArgs e) 
{ 
    if (ValidateUser(UserNameTextBox.Value, PasswordTextBox.Value)) 
     { 
       FormsAuthenticationTicket tkt; 
       string cookiestr; 
       HttpCookie ck; 
       tkt = new FormsAuthenticationTicket(1, UserNameTextBox.Value, DateTime.Now, DateTime.Now.AddMinutes(30), RemPassword.Checked, "Custom Data"); 
       cookiestr = FormsAuthentication.Encrypt(tkt); 
       ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr); 
       if (RemPassword.Checked) 
       ck.Expires = tkt.Expiration; 
       ck.Path = FormsAuthentication.FormsCookiePath; 
       Response.Cookies.Add(ck); 

       string strRedirect; 
       strRedirect = Request["ReturnUrl"]; 
       if (strRedirect == null) 
       strRedirect = "Home.aspx"; 
       Response.Redirect(strRedirect, true); 
     } 
       else 
       Response.Redirect("Login.aspx", true); 
} 

Home.aspx

<asp:Content ID="rightcontentdown" ContentPlaceHolderID="rightcontentdown" Runat="Server"> 
    <asp:Button runat="server" Text="Terminar Sessão" ID="SignOutButton" OnClick="Signoutbutton_click" /> 
</asp:Content> 

Home.aspx.cs

protected void Signoutbutton_click(object sender, EventArgs e) 
{ 
    FormsAuthentication.SignOut(); 
    Session.Abandon(); 
    Session.Contents.RemoveAll(); 
    Response.Redirect("Login.aspx", true); 
} 
+0

只是一個想法,你有沒有考慮過使用一個單獨的角色表,並使用1〜 1關係來組織訪問。這樣你可以允許管理員/經理/用戶。 –

+0

我是否必須爲角色設置單獨的表格?把所有東西都放在一張表中的重點就是在後面創建一個管理頁面,我們可以添加用戶並分配他們的部門,從而讓他們訪問我們想要的任何內容 – user2983177

回答

0

首先創建一個pagesByDepatment表和部門表如下所示:

    • ID(INT)
    • 名稱(字符串)
  • PagesByDepartment
    • ID(INT)
    • DepartmentID的(INT)
    • 頁面名稱(字符串)
  • 用戶
    • ID (INT)
    • 用戶名(字符串)
    • 密碼(字符串) - 它會更好,如果你可以散列成一個位陣列:)
    • DepartmentID的(INT)

您需要授權用戶在所有頁面的每個請求中,對我來說可能是這種情況自定義用戶的主要對象

例如:

public class MyAppPrincipal :IPrincipal, IMyAppPrincipal 
     { 
      private IIdentity _identity; 
      private string _department; 
      public MyAppPrincipal(IIdentity identity, department) 
      { 
        _identity = identity; 
        _department = department; 
      } 

      public bool IsPageEnabled(string pageName) 
      { 
       //DB is your access to your database, I know that you´re using plain ADO.NET here so put query here or cache the elements in your app_start and read them from it.... 
       //let´s say you have a method that you pass the pagename and the department 
       return DB.IsPageEnabled(pageName, this._department); 

      } 
     } 

部門添加到自定義的用戶數據類似

protected void LoginButton_Click(object sender, EventArgs e) 
{ 
    if (ValidateUser(UserNameTextBox.Value, PasswordTextBox.Value)) 
     { 
       // get the department from your DB 
       string department = DB.GetDepartmentByUsername(UserNameTextBox.Value); 

       FormsAuthenticationTicket tkt; 
       string cookiestr; 
       HttpCookie ck; 

          tkt = new FormsAuthenticationTicket(2, // version 
          UserNameTextBox.Value, 
          DateTime.Now, 
          DateTime.Now.AddMinutes(30), 
          RemPassword.Checked, 
          department, // instead of custom data 
          FormsAuthentication.FormsCookiePath); 

       cookiestr = FormsAuthentication.Encrypt(tkt); 
       ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr); 
       if (RemPassword.Checked) 
       ck.Expires = tkt.Expiration; 
       ck.Path = FormsAuthentication.FormsCookiePath; 
       Response.Cookies.Add(ck); 

       string strRedirect; 
       strRedirect = Request["ReturnUrl"]; 
       if (strRedirect == null) 
       strRedirect = "Home.aspx"; 
       Response.Redirect(strRedirect, true); 
     } 
       else 
       Response.Redirect("Login.aspx", true); 
} 

,那麼你需要一個HTTP模塊來驗證身份驗證票/授權

public class CustomAuthenticationModule : IHttpModule 
     { 

      public void Init(HttpApplication httpApp) 
      { 
        httpApp.AuthorizeRequest += new EventHandler(this.AuthorizaRequest); 
        httpApp.AuthenticateRequest += new EventHandler(this.AuthenticateRequest); 
      } 
      public void Dispose() 
      {} 

      private void AuthorizaRequest(object sender, EventArgs e) 
      {  
        if (HttpContext.Current.User != null) 
        { 
         if (HttpContext.Current.User.Identity.IsAuthenticated) 
         { 
           if (HttpContext.Current.User is MyAppPrincipal) 
           { 

           MyAppPrincipal principal = (MyAppPrincipal) HttpContext.Current.User; 
           if (!principal.IsPageEnabled(HttpContext.Current.Request.Path)) 
              HttpContext.Current.Server.Transfer("unauthorized.aspx"); 
           } 
         } 
        } 
      } 

      private void AuthenticateRequest(object sender, EventArgs e) 
      { 
        if (HttpContext.Current.User != null) 
        { 

         if (HttpContext.Current.User.Identity.IsAuthenticated) 
         { 
           if (HttpContext.Current.User.Identity is FormsIdentity) 
           { 
            var id = HttpContext.Current.User.Identity; 
            FormsAuthenticationTicket ticket = id.Ticket; 
            string cookieName = System.Web.Security.FormsAuthentication.FormsCookieName; 
            string userData = 
              System.Web.HttpContext.Current.Request.Cookies[cookieName].Value; 

            ticket = FormsAuthentication.Decrypt(userData); 

            string department=""; 
            if(userData.Length > 0) 
              department= ticket.UserData; 
            HttpContext.Current.User = new 
            MyAppPrincipal(_identity, department);       
           } 
         } 
        } 
      }//AuthenticateRequest 
     } //class 
} 

don' t忘記添加您的自定義模塊

<httpModules > 
     < add type ="myapp, SecurityModules" name ="CustomAuthenticationModule" /> 
</ httpModules > 

PD:你可以把它讀作僞代碼,因爲我編碼的文本框,而不是VS,我希望幫助

相關問題