これは私の以前の質問 hereの続きです。
組み込みの 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]);
}
}
}
DB にアクセスして、考えられるすべての従業員をここでループしたくないので、ここで紛らわしいコードにコメントしました。管理者アカウントの場合は簡単ですが、従業員アカウントの場合は不可能です。
ログイン.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
の1つで、メソッドが何度も呼び出されているようです。Application_AuthenticateRequest()
面白いことに、保護されていないページにアクセスすると、自分がログインしていることを確認でき、ヘッダーに「Welcome Admin!, Logout」と表示されます。これは、マスター ページを通じて動的に行われます。
<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>
誰でも問題を特定できますか? 今日は本当にこれを閉じる必要があります。ありがとう。
編集
フィドラーを使用しましたが、ログインを押すと無限ループが作成されることがわかりました。画像を通して動作を示すことができます:
セキュリティで保護された領域にアクセスすると、ログイン ページにスローされます
資格情報を入力し、ログインボタンを押しました
認証情報が受け入れられ、安全なページにリダイレクトされ、再度ログインにリダイレクトされるなど
明らかな変更が検出されたため、フィドラーの Cookies タブを選択します。