使用用户名而不是电子邮件登录

时间:2015-03-03 10:44:51

标签: c# asp.net webforms asp.net-identity

我在visual studio 2013中创建了一个新的Web窗体项目,我希望用户能够使用他们的UserName(例如管理员)登录而不是他们的电子邮件地址。

如果打开自动生成的" Register.aspx.cs"文件你会看到这段代码:

var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var signInManager = Context.GetOwinContext().Get<ApplicationSignInManager>();

var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text };

问题: 为什么UserName和Email在最后一行具有相同的值???在这种情况下,为什么您需要UserName列,因为您已经有电子邮件列?


可以使用用户名而不是电子邮件地址登录吗?


我试图通过在注册表单中添加一个名为&#34; UserName&#34;的新文本框字段来解决这个问题:

  

Register.aspx

<div class="form-group">
    <asp:Label runat="server" AssociatedControlID="UserName" CssClass="col-md-2 control-label">UserName</asp:Label>
    <div class="col-md-10">
        <asp:TextBox runat="server" ID="UserName" CssClass="form-control" />
        <asp:RequiredFieldValidator runat="server" ControlToValidate="Email"
            CssClass="text-danger" ErrorMessage="The UserName field is required." />
    </div>
</div>

在注册功能上我做了这个改变:

  

Register.aspx.cs

var user = new ApplicationUser() { UserName = UserName.Text, Email = Email.Text };

然后我改变了登录功能:

  

Login.aspx.cs

protected void LogIn(object sender, EventArgs e)
        {
            if (IsValid)
            {
                // Validate the user password
                var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
                var signinManager = Context.GetOwinContext().GetUserManager<ApplicationSignInManager>();

                // This doen't count login failures towards account lockout
                // To enable password failures to trigger lockout, change to shouldLockout: true
                //var result = signinManager.PasswordSignIn(Email.Text, Password.Text, false, shouldLockout: false);

                SignInStatus result = SignInStatus.Failure;

                // check too see if the user has entered a email address or not
                if (IsValidEmail(NameOrEmail.Text))
                {
                    result = signinManager.PasswordSignIn(NameOrEmail.Text, Password.Text, false, shouldLockout: false);
                }
                else
                {
                    // get users email using his name
                    var user = manager.FindByName(NameOrEmail.Text);

                    result = signinManager.PasswordSignIn(user.Email, Password.Text, false, shouldLockout: false);
                }


                switch (result)
                {
                    case SignInStatus.Success:
                        string queryString = Request.QueryString["ReturnUrl"];
                        if (!string.IsNullOrEmpty(queryString))
                            IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
                        else
                            Response.Redirect("/Account/Dashboard");
                        break;
                    case SignInStatus.LockedOut:
                        Response.Redirect("/Account/Lockout");
                        break;
                    case SignInStatus.Failure:
                    default:
                        FailureTextLabel.Text = "Invalid login!";
                        ErrorMessage.Visible = true;
                        break;
                }
            }
        }

        // check email address
        private bool IsValidEmail(string strIn)
        {
            // Return true if strIn is in valid e-mail format.
            return Regex.IsMatch(strIn, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
        }

模板看起来像这样:

  

的Login.aspx

<div class="form-group">
    <asp:Label runat="server" AssociatedControlID="NameOrEmail" CssClass="col-md-2 control-label">UserName or Email</asp:Label>
    <div class="col-md-10">
        <asp:TextBox runat="server" ID="Email" CssClass="form-control" />
        <asp:RequiredFieldValidator runat="server" ControlToValidate="NameOrEmail"
            CssClass="text-danger" ErrorMessage="The name or email field is required." />
    </div>
</div>

问题: 如果您更改注册用户名,则无法再登录(您将获得SignInStatus.Failure)。 在我注册时,UserName必须与注册时的电子邮件相同才能使登录工作。

有没有办法解决这个问题?

1 个答案:

答案 0 :(得分:0)

首先,这根本不是一个错误。这就是它的工作原理,如果你想使用用 visual studio 2013模板创建的开箱即用的默认实现(对于个人用户)那么你就会这样做。

作为开发人员,asp.net身份可以根据我们的选择进行配置。为此,您需要深入了解身份框架并了解其工作原理。

如果您使用v isual studio 2013 with update 3 或更高版本,则可以在 IdentityConfig.cs 文件中找到大多数简单但非常重要的配置。

身份框架版本1仅附带用户名而没有支持用户界面的电子邮件地址,但更改了版本2.x和visual studio 2013更新3和4 ,其中包括用户名和电子邮件地址电子邮件。

您可以将其更改为使用用户名而不是电子邮件,如下所述。

新的开箱即用注册码是:

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
                var result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);

                    // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
                    // Send an email with this link
                    // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                    // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                    // await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");

                    return RedirectToAction("Index", "Home");
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

您可以看到用户名和电子邮件都使用model.Email。

var user = new ApplicationUser { UserName = model.Email, Email = model.Email };

更新您的代码,如下所示

注册方法

[HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {

            UserManager.UserValidator = new UserValidator<ApplicationUser>(UserManager)
            {
                RequireUniqueEmail = false,
            };

            var user = new ApplicationUser { UserName = model.UserName };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);

                // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
                // Send an email with this link
                // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                // await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");

                return RedirectToAction("Index", "Home");
            }
            AddErrors(result);
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

RegisterViewModel

public class RegisterViewModel
    {
        [Required]
        [Display(Name = "UserName")]
        public string UserName { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    }

LoginViewModel

public class LoginViewModel
    {
        [Required]
        [Display(Name = "UserName")]
        public string UserName { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }

        [Display(Name = "Remember me?")]
        public bool RememberMe { get; set; }
    }

此外,您需要更新其他视图模型,不要使用电子邮件,而是使用用户名

[Required]
    [Display(Name = "UserName")]
    public string UserName { get; set; }

然后更新所有视图以使用UserName而不是电子邮件,如下所示。

@model WebApplication2.Models.RegisterViewModel
@{
    ViewBag.Title = "Register";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Create a new account.</h4>
    <hr />
    @Html.ValidationSummary("", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Register" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
相关问题