Application_AuthenticateRequest продолжает вызывать бесконечные перенаправления
Это продолжение моего предыдущего вопроса здесь.
Я пытался использовать встроенный механизм ASP Login, но он не работал для меня. Основная причина в том, что меня просят держать это голым и простым.
Вот где я стою:
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 обнаружил, что сервер перенаправляет запрос на этот адрес способом, который никогда не будет завершен. Эта проблема иногда может быть вызвана отключением или отказом принимать куки.
Я плохо отлаживаю это, но кажется, что один внутри Global.asax
"s Application_AuthenticateRequest()
метод, метод просто вызывается снова и снова.
Забавно, что если я захожу на незащищенные страницы, я вижу себя вошедшим в систему и получаю "Welcome Admin!, Выход из системы" в заголовке. Это динамически выполняется через главную страницу
<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" в Fiddler, потому что там было обнаружено явное изменение.