c# - ASP.NET Web 应用程序中的身份验证遇到问题

标签 c# asp.net authentication authorization

我正在尝试对从登录页面登录我的 Web 应用程序的用户进行身份验证。我正在使用 this tutorial作为指南,它几乎准确地解释了我希望做什么,但是当我输入用户名和密码时,验证不起作用。请允许我解释一下。

以下是我的 HTML 的相关部分。没有什么异常:

<form id="form1" runat="server">
<div class=row>
<div class=col-xs-4>
    <div class="form-group">
<input id="txtUserName" type="text" runat="server">
<ASP:RequiredFieldValidator ControlToValidate="txtUserName"
       Display="Static" ErrorMessage="*" runat="server" 
       ID="vUserName" />
</div>
</div>

</div>
<div class=row>
<div class=col-xs-4>
<div class="form-group">
        <input id="txtUserPass" type="password" runat="server">
<ASP:RequiredFieldValidator ControlToValidate="txtUserPass"
      Display="Static" ErrorMessage="*" runat="server" 
      ID="vUserPass" />
</div>
</div>
</div>
<p><asp:Label ID="lblMsg" ForeColor="Red" runat="server" /></p>
<input type="submit" Value="Logon" runat="server" ID="cmdLogin"><p></p>
<ASP:CheckBox id="chkPersistCookie" runat="server" autopostback="false" />
</form>

该页面包含一个用户名和一个登录按钮(以及一个用于记住 cookie 的复选框,但我认为这与我的问题无关)。

这是背后的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Web.Security;

namespace MRAApplication
{
    public partial class _1__0__0__0_LoginScreen : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            this.cmdLogin.ServerClick += new System.EventHandler(this.cmdLogin_ServerClick);
        }

        private bool ValidateUser(string userName, string passWord)
        {
            SqlConnection conn;
            SqlCommand cmd;
            string lookupPassword = null;

            // Check for invalid userName.
            // userName must not be null and must be between 1 and 15 characters.
            if ((null == userName) || (0 == userName.Length) || (userName.Length > 15))
            {
                System.Diagnostics.Trace.WriteLine("[ValidateUser] Input validation of userName failed.");
                return false;
            }

            // Check for invalid passWord.
            // passWord must not be null and must be between 1 and 25 characters.
            if ((null == passWord) || (0 == passWord.Length) || (passWord.Length > 25))
            {
                System.Diagnostics.Trace.WriteLine("[ValidateUser] Input validation of passWord failed.");
                return false;
            }

            try
            {
                // Consult with your SQL Server administrator for an appropriate connection
                // string to use to connect to your local SQL Server.
                conn = new SqlConnection("databaseConnect");
                conn.Open();

                // Create SqlCommand to select pwd field from users table given supplied userName.
                cmd = new SqlCommand("Select Password from Users where User=@userName", conn);
                cmd.Parameters.Add("@userName", System.Data.SqlDbType.VarChar, 25);
                cmd.Parameters["@userName"].Value = userName;

                // Execute command and fetch pwd field into lookupPassword string.
                lookupPassword = (string)cmd.ExecuteScalar();

                // Cleanup command and connection objects.
                cmd.Dispose();
                conn.Dispose();
            }
            catch (Exception ex)
            {
                // Add error handling here for debugging.
                // This error message should not be sent back to the caller.
                System.Diagnostics.Trace.WriteLine("[ValidateUser] Exception " + ex.Message);
            }

            // If no password found, return false.
            if (null == lookupPassword)
            {
                // You could write failed login attempts here to event log for additional security.
                return false;
            }

            // Compare lookupPassword and input passWord, using a case-sensitive comparison.
            return (0 == string.Compare(lookupPassword, passWord, false));

        }

        private void cmdLogin_ServerClick(object sender, System.EventArgs e)
        {
            if (ValidateUser(txtUserName.Value, txtUserPass.Value))
            {
                FormsAuthenticationTicket tkt;
                string cookiestr;
                HttpCookie ck;
                tkt = new FormsAuthenticationTicket(1, txtUserName.Value, DateTime.Now,
          DateTime.Now.AddMinutes(30), chkPersistCookie.Checked, "your custom data");
                cookiestr = FormsAuthentication.Encrypt(tkt);
                ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
                if (chkPersistCookie.Checked)
                    ck.Expires = tkt.Expiration;
                ck.Path = FormsAuthentication.FormsCookiePath;
                Response.Cookies.Add(ck);

                string strRedirect;
                strRedirect = Request["ReturnUrl"];
                if (strRedirect == null)
                    strRedirect = "default.aspx";
                Response.Redirect(strRedirect, true);
            }
            else
                Response.Redirect("1.0.0.0_LoginScreen.aspx", true);
        }
     }
    }

现在,我已经测试了我的连接字符串并且它可以工作。它连接到 SQL Server 数据库中的一个表,其中包含 User、Password 和 UserRole 3 列。现在表中只有一个测试条目 as shown here

但是,当我运行应用程序并在“txtUserName”中输入“test”,在“txtUserPass”中输入“password”并单击“提交”时,它会重定向回登录页面,这意味着“if”返回 false (验证用户(txtUserName.Value,txtUserPass.Value))”。

如果有人能帮助我解决这个错误,我将不胜感激。感谢您的帮助。 :)

最佳答案

this is my first time trying to do authentication so I'm not totally sure how to get the return value by using the breakpoint.

您希望在连接到 SQL Server 之前使用硬编码的用户名和密码进行测试。

protected void cmdLogin_ServerClick(object sender, System.EventArgs e)
{
    if (String.Equals(txtUserName.Value, "johndoe", 
        StringComparison.InvariantCultureIgnoreCase) &&
        String.Equals(txtUserPass.Value, "123456", 
        StringComparison.InvariantCultureIgnoreCase))
    {
        var roles = new[] {"Administrators"};

        var ticket = new FormsAuthenticationTicket(1, 
            txtUserName.Value,
            DateTime.Now,
            DateTime.Now.AddMinutes(30), 
            chkPersistCookie.Checked,
            string.Join(",", roles),
            FormsAuthentication.FormsCookiePath);

        var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, 
            FormsAuthentication.Encrypt(ticket));

        if (chkPersistCookie.Checked)
            cookie.Expires = ticket.Expiration;

        Response.Cookies.Add(cookie);

        string returnUrl = Request["ReturnUrl"];
        if (returnUrl == null)
            returnUrl = "default.aspx";
        Response.Redirect(returnUrl, true);
    }
    else
        Response.Redirect("1.0.0.0_LoginScreen.aspx", true);
}

如何创建主体对象

当经过身份验证的用户请求页面时,您需要从 cookie 中检索身份验证票证,并创建一个主体对象。

// Global.asax.cs
public class Global : HttpApplication
{
    void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        HttpCookie decryptedCookie =
            Context.Request.Cookies[FormsAuthentication.FormsCookieName];

        if (decryptedCookie != null)
        {
            FormsAuthenticationTicket ticket =
                FormsAuthentication.Decrypt(decryptedCookie.Value);

            string[] roles = ticket.UserData.Split(new[] {","}, 
                 StringSplitOptions.RemoveEmptyEntries);

            var identity = new GenericIdentity(ticket.Name);
            var principal = new GenericPrincipal(identity, roles);

            HttpContext.Current.User = principal;
            Thread.CurrentPrincipal = HttpContext.Current.User;
        }
    }
}

用法

public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {    
        if (User.Identity.IsAuthenticated)
        {
            string username = User.Identity.Name;

            bool isAdministrator = User.IsInRole("Administrators");
        }
    }
}

关于c# - ASP.NET Web 应用程序中的身份验证遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25648353/

相关文章:

html - 为什么这个用于验证危险 html 的 ASP.NET RegularExpressionValidator 不起作用?

javascript - 在asp.net中调用javascript返回值到代码页

c# - WCF 添加命名空间属性

asp.net - ASP.Net 中的 JWT token 异常(生命周期验证失败。 token 缺少过期时间。)

authentication - OAuth 2.0授权码Grant中 "code"的生命周期

c# - datagridview 不允许用户删除行

c# - ASP.NET MVC 在 Controller 实例化之前进行身份验证

angular - Ionic 4 - AuthGuard 页面路由权限延迟

c# - 如何从数据行数组中删除数据行?

c# - 有条件地添加一个新的 json.net JProperty