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



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

如果你打开自动生成的"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 };

问题:为什么最后一行的用户名和电子邮件的值相同???在这种情况下,既然已经有了"电子邮件"列,为什么还需要"用户名"列?


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


我正试图通过在注册表中添加一个名为"用户名"的新文本框字段来解决这个问题:

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

然后我更改了登录功能,如下所示:

登录.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)。在我看来,用户名必须与注册时的电子邮件相同才能登录。

有办法解决这个问题吗?

首先,这根本不是一个bug。这就是它的工作原理,如果你想使用开箱即用的默认实现,它是用visualstudio2013模板创建的(与个人用户一起),那么你就会得到它。

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

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

身份框架版本1只提供了用户名,没有支持UI的电子邮件地址,但随着版本2.x和visualstudio2013更新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);
        }

您可以看到用户名和电子邮件都使用模型。电子邮件

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

然后更新所有视图以使用用户名,而不是像下面这样发送电子邮件。

@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")
}

相关内容

  • 没有找到相关文章

最新更新