Это продолжение моего предыдущего вопроса здесь.
Я пытался использовать встроенный механизм входа в систему ASP, но у меня это не сработало. Основная причина в том, что меня попросили сделать это голым и простым.
Теперь, вот где я стою:
Web.config
<system.web>
<sessionState timeout="10" />
<authentication mode="Forms">
<forms timeout="30" loginUrl="~/SecuredArea/LogInOut/log-in.aspx" />
</authentication>
<authorization>
<allow users="?" />
</authorization>
</system.web>
<location path="SecuredArea/AdminArea">
<system.web>
<authorization>
<allow roles="administrators" />
<deny users="*" />
</authorization>
</system.web>
</location>
<location path="SecuredArea/EmployeeArea">
<system.web>
<authorization>
<allow roles="employees" />
<deny users="*" />
</authorization>
</system.web>
</location>
Global.asax
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
IIdentity userId = HttpContext.Current.User.Identity;
//if role info is already NOT loaded into cache, put the role info in cache
//if (HttpContext.Current.Cache[userId.Name] == null)
//{
// string[] roles;
// if (userId.Name == "admin")
// {
// roles = new string[1] { "administrators" };
// }
// else if (userId.Name == "member1")
// {
// roles = new string[1] { "employees" };
// }
// else
// {
// roles = new string[1] { "public" };
// }
//1 hour sliding expiring time. Adding the roles in cache.
//This will be used in Application_AuthenticateRequest event located in Global.ascx.cs
//file to attach user Principal object.
// HttpContext.Current.Cache.Add(userId.Name, roles, null, DateTime.MaxValue, TimeSpan.FromHours(1), CacheItemPriority.BelowNormal, null);
//}
//now assign the user role in the current security context
HttpContext.Current.User = new GenericPrincipal(userId, (string[])HttpContext.Current.Cache[userId.Name]);
}
}
}
Я прокомментировал запутанный код здесь, потому что я не хочу получать доступ к БД и перебирать здесь всех возможных сотрудников. Для учетной записи администратора это просто, а для учетной записи сотрудника это невозможно.
log-in.aspx.cs
protected void ButtonLogOn_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(txtUserName.Value.Trim()) || String.IsNullOrEmpty(txtPassword.Value.Trim()))
{
labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
}
else
{
try
{
LoginPage loginBack = new LoginPage();
int result = loginBack.VerifyCredentials(txtUserName.Value.Trim(), txtPassword.Value.Trim());
switch (result)
{
case -9:
//System needs provisioning
labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("SMB Password Reset System need provisioning. Login as Administrator.");
break;
case 0:
//Enroll-able User
// Success, create non-persistent authentication cookie.
FormsAuthentication.SetAuthCookie(txtUserName.Value.Trim(), false);
FormsAuthenticationTicket ticketEmployee =
new FormsAuthenticationTicket(
1, // version
txtUserName.Value.Trim(), // get username from the form
DateTime.Now, // issue time is now
DateTime.Now.AddMinutes(10), // expires in 10 minutes
false, // cookie is not persistent
"employees");
HttpCookie cookieEmployee = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticketEmployee));
Response.Cookies.Add(cookieEmployee);
SiteLogin.PerformAuthentication(txtUserName.Value.Trim(), false);
break;
case 1:
//User not in required directory group
labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("You cannot login because you are not authorized.");
break;
default:
//Bad name and/or password
labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
break;
}
}
catch (MessageSecurityException expMse)
{
//Bad name and/or password
Debug.WriteLine("Error: " + expMse.Message);
labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
}
catch (Exception exp)
{
labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("Some general error has occured. Message reads: " + exp.Message);
}
}
}
protected void ButtonAdminLogOn_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(txtUserName.Value) || String.IsNullOrEmpty(txtPassword.Value))
labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("<strong>Login Please!</strong><hr/>You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
else
{
//if the log-in is successful
if (txtUserName.Value == "admin" && txtPassword.Value == "AlphaBeta")
{
// Success, create non-persistent authentication cookie.
FormsAuthentication.SetAuthCookie(txtUserName.Value.Trim(), false);
FormsAuthenticationTicket ticketAdmin =
new FormsAuthenticationTicket(
1, // version
txtUserName.Value.Trim(), // get username from the form
DateTime.Now, // issue time is now
DateTime.Now.AddMinutes(10), // expires in 10 minutes
false, // cookie is not persistent
"administrators");
HttpCookie cookieAdmin = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticketAdmin));
Response.Cookies.Add(cookieAdmin);
SiteLogin.PerformAdminAuthentication(txtUserName.Value.Trim(), false);
}
else
{
labelMessage.Text = MessageFormatter.GetFormattedErrorMessage("<strong>Login Failed!</strong><hr/>The username and/or password you entered do not belong to any Administrator account on our system.<br/>You can login using a username and a password associated with your account. Make sure that it is typed correctly.");
}
}
}
Наконец, служебный класс: SiteLogin.cs.
public sealed class SiteLogin
{
public static void PerformAuthentication(string userName, bool remember)
{
FormsAuthentication.RedirectFromLoginPage(userName, remember);
if (HttpContext.Current.Request.QueryString["ReturnUrl"] == null)
{
RedirectToDefaultPage();
}
else
{
HttpContext.Current.Response.Redirect(HttpContext.Current.Request.QueryString["ReturnUrl"]);
}
}
public static void PerformAdminAuthentication(string userName, bool remember)
{
FormsAuthentication.RedirectFromLoginPage(userName, remember);
if (HttpContext.Current.Request.QueryString["ReturnUrl"] == null)
{
RedirectToAdminDefaultPage();
}
else
{
HttpContext.Current.Response.Redirect(HttpContext.Current.Request.QueryString["ReturnUrl"]);
}
}
/// <summary>
/// Redirects the current user based on role
/// </summary>
public static void RedirectToDefaultPage()
{
HttpContext.Current.Response.Redirect("~/SecuredArea/EmployeeArea/EmployeeDefaultPage.aspx");
}
/// <summary>
/// Redirects the current user based on role
/// </summary>
public static void RedirectToAdminDefaultPage()
{
HttpContext.Current.Response.Redirect("~/SecuredArea/AdminArea/AdminDefaultPage.aspx");
}
public static void LogOff()
{
// Put user code to initialize the page here
FormsAuthentication.SignOut();
//// Invalidate roles token
//Response.Cookies[Globals.UserRoles].Value = "";
//Response.Cookies[Globals.UserRoles].Path = "/";
//Response.Cookies[Globals.UserRoles].Expires = new System.DateTime(1999, 10, 12);
//Set the current user as null
HttpContext.Current.User = null;
}
}
Теперь я получаю серьезно непоследовательное поведение всякий раз, когда пытаюсь войти в систему. Самая большая проблема заключается в том, что когда я пытаюсь получить доступ к любой из защищенных страниц для администратора или сотрудника, меня перенаправляют на страницу входа. Я предоставляю данные и пытаюсь войти в систему, и в обоих случаях (простой вход администратора и сложный вход сотрудника) я получаю сообщение об ошибке в браузере. IE не имел особого смысла, но жалобы Firefox имели смысл:
Страница перенаправляется неправильно Pale Moon обнаружила, что сервер перенаправляет запрос на этот адрес способом, который никогда не будет завершен. Иногда эта проблема может быть вызвана отключение или отказ от приема файлов cookie.
У меня проблемы с отладкой, но кажется, что внутри метода Global.asax
Application_AuthenticateRequest()
этот метод просто вызывается снова и снова.
Забавно, что если я захожу на незащищенные страницы, я вижу, что я вошел в систему, и получаю «Добро пожаловать, администратор!, Выход» в моем заголовке. Это делается динамически через мастер-страницу.
<div class="info-area">
<asp:LoginView ID="HeadLoginView" runat="server" EnableViewState="false">
<LoggedInTemplate>
Welcome <span class="bold">
<asp:LoginName ID="HeadLoginName" runat="server" />
</span>! |
</LoggedInTemplate>
</asp:LoginView>
<asp:LoginStatus ID="HeadLoginStatus" runat="server" LogoutAction="Redirect" LogoutText="Logout" LogoutPageUrl="~/SecuredArea/LogInOut/log-out.aspx" />
</div>
Кто-нибудь может определить проблему? Мне действительно нужно закрыть это дело сегодня. Спасибо.
ИЗМЕНИТЬ
Я использовал fiddler и вижу, что после входа в систему создается бесконечный цикл. Я могу показать поведение через изображения:
Перебрасывается на страницу входа при входе в защищенную зону
Ввел учетные данные и нажал кнопку входа
Учетные данные приняты и перенаправлены обратно на защищенную страницу и снова перенаправлены на вход и т. д.
Я выбираю вкладку Cookies скрипача, потому что там было обнаружено явное изменение.
SiteLogin
— это просто служебный класс для скрытия инструкций по перенаправлению. Дело в том, что внутри методаPerformAdminAuthentication()
есть if-else. Я всегда попадаю в другую часть, что означает, что я не вошел в систему. Или это то, что я сделал вывод из Интернета. - person Hassan Gulzar   schedule 03.06.2012