2012-08-11 68 views
1

我使用表單身份驗證的LightSwitch 2011 Web應用程序出現問題。LS 2011 Web應用程序中自己的AD表單身份驗證問題

我已經實現了我自己的登錄屏幕,可以根據活動目錄對用戶進行身份驗證。我的代碼還會檢查用戶是否分配給特定的活動目錄組,以決定是否可以添加/編輯/刪除數據。

登錄表單放置在Login.aspx頁面上。登錄按鈕保持以下代碼:

protected void buttonLogin_Click(object sender, EventArgs e) 
{ 
    LdapAuthentication authentication = new LdapAuthentication(); 

    try 
    { 
     bool isUserAdmin = false; 
     if (authentication.IsUserAuthenticated(textBoxUserName.Text, textBoxPassword.Text, ref isUserAdmin)) 
     { 
      FormsAuthenticationTicket authenticationTicket = new FormsAuthenticationTicket(1, 
      textBoxUserName.Text, DateTime.Now, DateTime.Now.AddSeconds(1), false, String.Empty); 

      //Encrypt the ticket. 
      string encryptedTicket = FormsAuthentication.Encrypt(authenticationTicket); 

      //Create a cookie, and then add the encrypted ticket to the cookie as data. 
      HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); 

      //Add the cookie to the outgoing cookies collection. 
      Response.Cookies.Add(authCookie); 

      //If the everyoneAdmin is set to true the validation of the administratorgroup 
      //is decativated so we have to grant the current user administrator rights 
      if (everyoneAdmin) 
       isUserAdmin = true; 

      Session["isUserAdmin"] = isUserAdmin ; 

      Response.Redirect("default.htm"); 
     } 
    } 
    catch (Exception ex) 
    { 
     labelError.Text = ex.Message; 
     labelError.Visible = true; 
     textBoxPassword.Text = String.Empty; 
    } 
} 

public bool IsUserAuthenticated(String userName, String password, ref bool isUserAdmin) 
{ 
    if (String.IsNullOrEmpty(userName) || String.IsNullOrEmpty(password)) 
     return false; 

    String domain = String.Empty; 
    if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["Domain"])) 
     domain = Convert.ToString(ConfigurationManager.AppSettings["Domain"]).Trim(); 
    else 
     throw new NullReferenceException("The Domain in the configuration must not be null!"); 

    String ldpa = String.Empty; 
    if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["LDPA"])) 
     ldpa = String.Format("LDAP://{0}", Convert.ToString(ConfigurationManager.AppSettings["LDPA"]).Trim()); 
    else 
     throw new NullReferenceException("The LDPA in the configuration must not be null!"); 

    String administrationGroup = String.Empty; 
    if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["AdministratorGroup"])) 
     administrationGroup = Convert.ToString(ConfigurationManager.AppSettings["AdministratorGroup"]).Trim(); 
    else 
     throw new NullReferenceException("The AdministrationGroup in the configuration must not be null!"); 

    String domainUserName = String.Format(@"{0}\{1}", domain.Trim(), userName.Trim()); 
    DirectoryEntry directoryEntry = new DirectoryEntry(ldpa, domainUserName, password); 

    try 
    { 
     //Bind to the native AdsObject to force authentication. 
     object obj = directoryEntry.NativeObject; 
     DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry); 

     directorySearcher.Filter = String.Format("(SAMAccountName={0})", userName.Trim()); 
     directorySearcher.PropertiesToLoad.Add("cn"); 
     directorySearcher.PropertiesToLoad.Add("memberOf"); 
     SearchResult directorySearchResult = directorySearcher.FindOne(); 

     //unable to find a user with the provided data 
     if (directorySearchResult == null) 
      return false; 

     if (directorySearchResult.Properties["memberof"] != null) 
     { 
      //If the memberof string contains the specified admin group 
      for (int i = 0; i < directorySearchResult.Properties["memberof"].Count; i++) 
      { 
       string temp = directorySearchResult.Properties["memberof"].ToString(); 
       // get the group name, for example: 
       if (directorySearchResult.Properties["memberof"].ToString().ToLower().Contains(administrationGroup.ToLower())) 
       { 
        isUserAdmin = true; 
        break; 
       } 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     throw new Exception(String.Format("Error authenticating user.\n\rMessage:\n\r {0}", ex.Message)); 
    } 

    return true; 
} 

在保持我實現以下方法CanExcecute(服務器層)方法的類:

public bool IsCurrentUserAdmin() 
{ 
    if (HttpContext.Current.Session["isUserAdmin"] == null) 
     return false; 

    return (bool)(HttpContext.Current.Session["isUserAdmin"]); 
} 

例如, CanExcecute方法爲一個表

partial void dtFacilities_CanDelete(ref bool result) 
{ 
    result = this.IsCurrentUserAdmin(); 
} 

partial void dtFacilities_CanInsert(ref bool result) 
{ 
    result = this.IsCurrentUserAdmin(); 
} 

partial void dtFacilities_CanUpdate(ref bool result) 
{ 
    result = this.IsCurrentUserAdmin(); 
} 

個WebConfig

<authentication mode="Forms"> 
    <form>s name=".ASPXAUTH" 
     loginUrl="Login.aspx" 
     protection="All" 
     timeout="30" 
     path="/" 
     requireSSL="false" 
     slidingExpiration="true" 
     defaultUrl="Home.aspx" 
     cookieless="UseUri" /> 
</authentication> 
<authorization> 
    <deny users="?"> 
</deny></authorization> 

問題

  1. 的問題是,如果用戶空閒的時間超過了timeout會話超時長。所以,會話令牌isUserAdminNULL。此時我希望應用程序返回到登錄屏幕。 A Response.RedirectServer.TransferIsCurrentUserAdmin()方法中不起作用。如果會話令牌isUserAdminNULL?我怎樣才能讓應用程序將用戶返回到登錄屏幕?請記住,會話令牌設置在login.aspx頁面代碼後面

  2. 當用戶關閉Lightswitch應用程序的最終選項卡時,應用程序將打開一個新選項卡並瀏覽過去的登錄頁面,並自動登錄而不處理登錄過程在login.aspx頁面。這意味着會話令牌isUserAdminNULL。即使用戶在關閉應用程序的最終選項卡之前尚未登錄,也會發生這種情況。這又導致問題1.

在此先感謝!

回答

0

如果我正確理解您的問題,如果因爲某種原因isUserAdmin設置爲NULL,您希望將用戶返回到登錄屏幕。

在我的應用程序中,我只是使用一個按鈕,用戶可以點擊註銷。但底層方法在你的情況下應該是一樣的。

首先創建一個名爲LogOff.aspx的新頁面。該頁面本身,你可以保留默認生成的代碼:

using System.Web.Security; 

namespace LightSwitchApplication 
{ 
    public partial class LogOff : System.Web.UI.Page 
    { 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     FormsAuthentication.SignOut(); 
     Response.Redirect("default.htm"); 
    } 
    } 
} 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
    <title></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 

    </div> 
    </form> 
</body> 
</html> 

對於後面的代碼,你會想這樣的事情(請檢查這一點,我從我的項目,這是在VB中轉換)

這是我使用按鈕的代碼。但是,如果你把其中Dispatcher調用Navigate,並把它放在你的IsCurrentUserAdmin()方法的部分,它應該做同樣的伎倆(再次,檢查C#):

using Microsoft.LightSwitch.Threading; 
using System.Windows.Browser; 

     partial void btnLogOff_Execute() 
     { 
      Dispatchers.Main.Invoke(() => 
      { 
       HtmlPage.Window.Navigate(new Uri("LogOff.aspx", UriKind.Relative)); 
      }); 
     } 

以我的經驗,有一點的在Lightswitch中陷入困境。如果要按原樣執行,您可能會收到以下內容:

'/'應用程序中的服務器錯誤。

無法找到該資源。

說明: HTTP 404。您正在查找的資源(或它的 的一個依賴項)可能已被刪除,更名,或者是 暫時不可用。請檢查以下URL並確定 拼寫正確。

請求的URL: /LogOff.aspx

修復的方法是這樣的:

首先右鍵單擊在Solution Explorer和卸載項目的項目名稱。項目卸載後,右鍵單擊它並編輯project_name.lsproj。 Ctrl+Fdefault.htm。您正在尋找由_BuildFile進行的部分。將該部分從_BuildFile複製到/_BuildFile,粘貼到該部分下面並修改如下。

<_BuildFile Include="Server/LogOff.aspx"> 
    <SubFolder> 
    </SubFolder> 
    <PublishType> 
    </PublishType> 
</_BuildFile> 

現在右鍵單擊並重新加載您的項目。如果在嘗試構建時遇到錯誤,請嘗試構建|清理並重新構建。如果您在Debug中運行應用程序,則此代碼將重新加載頁面。但是,一旦您發佈並隨後導致isUserAdminNULL,代碼應該將您註銷並將您帶回到登錄屏幕。

參考文獻:

Original MSDN Forum Thread

My experience implementing it

+0

感謝您的答覆的方法不會對我實施工作。問題是,我不能使用HtmlPage.Window.Navigate,因爲我不能引用System.Windows.Browser。爲了清楚起見,在這裏實現了IsCurrentUserAdmin()方法(鏈接到一張圖片來清除它):也許我的方法不是正確的方式,我必須重新考慮它?! – 2012-08-13 14:19:35

+0

也許我的解決方案是過度殺傷。如果你只是調用'FormsAuthentication.SignOut(); Response.Redirect(「default.htm」);'來自'IsCurrentUserAdmin()',甚至是'CanExecute'代碼本身?這應該只需要'System.Web.Security',它應該在'DataService'代碼中可用。 – 2012-08-13 15:32:15

+0

這就是我試過的......但它不起作用。該網站只是加載,並沒有重定向到登錄頁面..我不知道爲什麼,但我想我會在未來避免ls。 :) – 2012-08-13 16:30:45