3

这是我之前的问题的延续。

我曾尝试使用内置的 ASP 登录机制,但它对我不起作用。主要原因是,我被要求保持简洁。

现在,这就是我的立场:

网页配置

<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>

全球.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]);
        }
    }
}

我在这里评论了令人困惑的代码,因为我不想在这里访问数据库并遍历所有可能的员工。对于管理员帐户,这很容易,但对于员工帐户,这是不可能的。

登录.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 引起的。

我在调试它时遇到了麻烦,但似乎是 insideGlobal.asaxApplication_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 选项卡,因为那里检测到了明显的变化。

4

0 回答 0