2012-08-11 76 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

相关问题