我在使用表单身份验证的LightSwitch 2011 Web应用程序时遇到了问题。
我已经实现了自己的登录屏幕,该屏幕根据活动目录对用户进行身份验证。我的代码还检查用户是否被分配到特定的活动目录组,以决定他们是否可以添加/编辑/删除数据。
登录表单放在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>
问题:
问题是,如果用户空闲的时间超过timeout
会话超时。因此,会话令牌isUserAdmin
为NULL
。此时我希望应用程序返回登录屏幕。 Response.Redirect
和Server.Transfer
在IsCurrentUserAdmin()
方法中不起作用。如果会话令牌isUserAdmin
是NULL
,我该如何让应用程序将用户返回到登录屏幕?请记住,会话令牌是在<{p>
login.aspx
页面代码中设置的
当用户关闭Lightswitch应用程序的最后一个选项卡时,应用程序将打开一个新选项卡并浏览登录页面,并自动登录,而无需在login.aspx
页面上处理登录过程。这意味着会话令牌isUserAdmin
为NULL
。即使用户在关闭应用程序的最终选项卡之前尚未登录,也会发生这种情况。这又导致了问题1.
提前致谢!
答案 0 :(得分:0)
如果我正确理解您的问题,如果由于某种原因,isUserAdmin
设置为NULL
,您希望将用户返回到登录屏幕。
在我的应用程序中,我只需使用一个用户可以单击即可注销的按钮。但在你的情况下,基础方法应该是一样的。
首先创建一个名为LogOff.aspx的新页面。页面本身,您可以保留默认生成的代码:
<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):
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");
}
}
}
这是我使用按钮的代码。但是,如果您选择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.您正在寻找的资源(或其中一个 依赖项)可能已被删除,其名称已更改,或者是 暂时不可用。请查看以下网址并制作 确保它拼写正确。
请求的网址: /LogOff.aspx
解决方法是:
首先在解决方案资源管理器和卸载项目中右键单击您的项目名称。卸载项目后,右键单击它并编辑project_name.lsproj。 Ctrl+F
default.htm
。您正在寻找_BuildFile
所在的部分。将该部分从_BuildFile
复制到/_BuildFile
,粘贴到该部分下方并修改如下。
<_BuildFile Include="Server/LogOff.aspx">
<SubFolder>
</SubFolder>
<PublishType>
</PublishType>
</_BuildFile>
现在右键单击并重新加载项目。如果在尝试构建时遇到错误,请尝试构建|清洁并再次建造。如果在Debug中运行应用程序,则此代码将重新加载页面。但是,一旦您发布并随后使isUserAdmin
成为NULL
,代码就会将您注销并带您返回登录屏幕。
<强>参考文献:强>