码农家园

关闭
导航

关于c#:在asp.net Web应用程序中进行身份验证时遇到问题


asp.netauthenticationauthorizationc#login

Having trouble with authentication in asp.net web application

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

以下是我的HTML的相关部分。一切正常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<form id="form1" runat="server">


   
<input id="txtUserName" type="text" runat="server">
<ASP:RequiredFieldValidator ControlToValidate="txtUserName"
       Display="Static" ErrorMessage="*" runat="server"
       ID="vUserName" />







        <input id="txtUserPass" type="password" runat="server">
<ASP:RequiredFieldValidator ControlToValidate="txtUserPass"
      Display="Static" ErrorMessage="*" runat="server"
      ID="vUserPass" />



<p>

</p>
<input type="submit" Value="Logon" runat="server" ID="cmdLogin"><p>

</p>
<ASP:CheckBox id="chkPersistCookie" runat="server" autopostback="false" />
</form>

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

下面是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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数据库中的一个表,该数据库包含3列用户、密码和用户角色。现在我在表中只有一个测试条目,如图所示。

但是,当我运行应用程序并在"txtUserName"中输入"test",在"txtUserPass"中输入"password"并单击"submit"时,它将重定向回登录页面,这意味着它将返回"if(validateuser(txtUserName.value,txtUserPass.value))"的false。

如果有人能帮我解决这个错误,我会感激的。谢谢你的帮助。:)

相关讨论

  • 您使用的是ASP.NET吗?
  • @亚历山大是的,我是,不知怎么地,它被我贴在这里的代码剪掉了。为了清晰起见进行了编辑。
  • @Jago如果在if (ValidateUser(txtUse..处设置一个断点,返回值是什么?是真是假?如何在authenticateRequest中创建iprincipal?
  • 听起来您需要学习如何使用调试器以及如何设置事件处理程序。我会看一些IsPostBack代码并学习如何使用它。看起来很马虎
  • 尝试在重定向之前添加FormsAuthentication.setAuthcookie(用户名,真)
  • @partha op手动创建身份验证cookie。如果手动创建cookie,则不应使用setauthcookie;它将覆盖cookie的到期日期。
  • @win我希望这不是太令人沮丧,但我对编程非常陌生,这是我第一次尝试进行身份验证,所以我不完全确定如何通过使用断点获得返回值。当我在您提到的行上放置一个断点时,登录屏幕会正常运行,当我按下登录时,Visual Studio会弹出一个突出显示"if"的行。浏览器开始加载,但不执行任何其他操作。关于我的问题,你能给我解释一下那是什么吗?令人尴尬的是,我不知道那是什么。(不过,我非常感谢你的时间。
  • 在validateuser函数中放置一个断点。它将进入该功能。你也可以在那里检查你的值
  • 可能web.config有问题?@Jago你能给我们看一下web.config的认证/授权部分吗?
  • @Partha </authentication> </authorization>试图尽可能地将其格式化……:/
  • . 除去这个。你拒绝匿名用户吗?。不需要允许用户="
  • @好的,谢谢。但最初的问题仍然存在。我真的很感谢你的时间,顺便说一句,对不起,如果我感到沮丧,我是非常新的编码。
  • 没有问题。就连我今天也从@win中学到了新东西。
  • 是否尝试在validate函数中保留断点并对其进行调试?
  • @Partha我应该把断点放在哪里?在"if(validateuser(textusername.value,txtuser.value))"行上?在我跑完之后我该找什么呢?当我在您提到的行上放置一个断点时,登录屏幕正常运行,当我按Logon时,Visual Studio弹出一行突出显示"if"
  • 让我们在聊天中继续讨论。


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之前,您需要使用硬编码的用户名和密码进行测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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中检索身份验证票据,并创建一个主体对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 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;
        }
    }
}

用法

1
2
3
4
5
6
7
8
9
10
11
12
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");
        }
    }
}
相关讨论

  • 感谢您的详细答复。当我使用"johndoe"时,身份验证会起作用,这意味着从SQL Server获取信息时一定有问题,对吧?
  • 我得说是的。连接到SQL Server是不同的动物;很多事情很容易出错。所以慢慢来,先研究一下如何调试Web应用程序。否则,你很容易受挫。祝你好运!
  • 好吧,酷。我能够在应用程序的其他地方用来自相同数据库和相同连接字符串的数据填充一个表,所以我猜这肯定是我在"CmdLoginServerClick"中做的错误。我会调查一下是什么问题。你帮了我很大的忙,我欠你一个,赢。


  • 关于安全:基于表单的网站认证的最终指南
  • 关于C#:如何从ASP.NET MVC中的枚举创建DropDownList?
  • 关于.NET:ASP.NET网站或ASP.NET Web应用程序?
  • 关于.net:在C#中,public,private,protected和没有访问修饰符有什么区别?

Copyright ©  码农家园 联系:[email protected]