0

嗨,

我是 blazor 和 .net 的新手,想知道如何以最佳方式实现密码重置。目前我正在使用此示例登录等:Blazor 身份验证示例。此示例不包括重置密码的示例。所以我自己正在寻找解决方案。

这就是所拥有的,它是一个 Razor 组件

@page "/ResetPassword"

@inject UserManager<IdentityUser> userManager
@inject NavigationManager navigationManager
@inject IDataProtectionProvider dataProtectionProvider

@if (IsResetSend)
{
    <h3>Reset Password</h3>
    <div>
        A mail has been send with a password reset link, please click this link to set a new password.
    </div>
    <br />
    <a href="/">Back</a>
}
else
{
    <h3>Reset Password</h3>
    <EditForm Model="resetPassword" OnValidSubmit="@SendResetPassword">
        <div class="field">
            <label class="label">E-mail</label>
            <div class="control">
                <InputText id="email" class="input" type="email" @bind-Value="@resetPassword.Email"></InputText>
            </div>
        </div>
        <div class="field">
            <div class="control">
                <button type="submit" class="button is-primary">Sign in</button>
            </div>
        </div>
    </EditForm>
}

@code {

    ResetPassword resetPassword = new ResetPassword();

    bool IsResetSend = false;

    public async void SendResetPassword()
    {
        List<string> mailTo = new List<string>();

        string passwordResetToken;

        var user = await userManager.FindByEmailAsync(resetPassword.Email);

        if (user != null)
        {
            mailTo.Add(resetPassword.Email);

            passwordResetToken = await userManager.GeneratePasswordResetTokenAsync(user);

            //Send mail with the relevant token
            Webco.Email.Entities.EmailObject emailObject = new Webco.Email.Entities.EmailObject();
            emailObject.Email_To = mailTo;
            emailObject.Email_Subject = "Password Reset Webco !";
            emailObject.Email_Message = "Hy There, <br> Please click this link to reset your password : <br> https://localhost:44384/" + passwordResetToken;
            emailObject.SendEmail(emailObject);

            IsResetSend = true;
        }
    }

    public class ResetPassword
    {
        [Required]
        public string Email { get; set; }

    }

如您所见,这是一种简单的方法,目前我似乎找不到一种方法来存储密码重置令牌,并在邮件中单击它时捕获它。

在我之前;

  1. 创建一个随机令牌,将其存储在字段中的数据库中;当前用户的 UserResetToken
  2. 当用户然后单击链接时,令牌将被提供给网页 [参数]。
  3. 然后存储过程会找到令牌并清除它,然后在另一个用户表单上更改密码。

我不认为这是基于自定义存储过程的最佳实践。有人可以指导我吗?

问候,

4

2 回答 2

3

Blazor 已包含所有必需的示例。创建一个新项目并选择作为身份验证应用内存储。在您的项目上单击鼠标右键,然后选择 Add->New Scaffolding element,然后选择右侧的 Identity。Visual Studio 将询问您要覆盖哪些文件并创建一个完整的示例,您可以使用该示例在您的主应用程序中构建它。

这个页面是可能的: 在此处输入图像描述

于 2020-06-01T20:31:11.093 回答
2

经过一番搜索,感谢马文的回应,我来到了下面的代码。也许它可以帮助任何搜索这个主题的人。开放改进...

我在开发中的服务器端应用程序中对此进行了测试。不在iis上

了解 usermanager kudvenkat 的链接,这是 .net 核心上很棒的 youtube 系列

剃须刀组件

@page "/ResetPassword"

@inject UserManager<IdentityUser> userManager
@inject NavigationManager navigationManager
@inject IDataProtectionProvider dataProtectionProvider

@using Microsoft.AspNetCore.WebUtilities;
@using System.Text.Encodings.Web;
@using System.Text;

@* THIS IS THE PART HANDLING THE RESET TOKEN INCOMING VALIDATION *@
@if (IsResetToken)
{

    <h3>Reset Password</h3>
    <div>
        Please enter a new Password bellow;
    </div>
    <br />
    <EditForm Model="@validatePasswordModel" OnValidSubmit="@SetResetPassword">
        <DataAnnotationsValidator />
        <ValidationSummary />

        <div class="field">
            <label class="label">Password</label>
            <div class="control">
                <InputText id="password" class="input" type="password" @bind-Value="@validatePasswordModel.Password"></InputText>
            </div>
        </div>
        <div class="field">
            <label class="label">Confirm password</label>
            <div class="control">
                <InputText id="cpassword" class="input" type="password" @bind-Value="@validatePasswordModel.ConfirmPassword"></InputText>
            </div>
        </div>
        <div class="field">
            <div class="control">
                <button type="submit" class="button is-primary">Set Password</button>
            </div>
        </div>
    </EditForm>
    <br />
    <a href="/">Back</a>

}
else
{

    @* THIS IS THE PART HANDLING THE RESET TOKEN OUTGOING VALIDATION *@

    @if (IsResetSend)
    {
        <h3>Reset Password</h3>
        <div>
            A mail has been send with a password reset link, please click this link to set a new password.
        </div>
        <br />
        <a href="/">Back</a>
    }
    else
    {
        <h3>Reset Password</h3>
        <EditForm Model="requestPasswordModel" OnValidSubmit="@SendResetPassword">
            <div class="field">
                <label class="label">E-mail</label>
                <div class="control">
                    <InputText id="email" class="input" type="email" @bind-Value="@requestPasswordModel.Email"></InputText>
                </div>
            </div>
            <div class="field">
                <div class="control">
                    <button type="submit" class="button is-primary">Sign in</button>
                </div>
            </div>
        </EditForm>
    }
}

@code {

    InputModel requestPasswordModel = new InputModel();
    ResetPasswordModel validatePasswordModel = new ResetPasswordModel();

    string email = "";
    string token = "";

    bool IsResetSend = false;
    bool IsResetToken = false;

    protected override void OnInitialized()
    {

        GetHttpParameters();

    }

    public void GetHttpParameters()
    {
        var uriBuilder = new UriBuilder(navigationManager.Uri);
        var httpQuery = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);

        email = httpQuery["email"] ?? "";
        token = httpQuery["token"] ?? "";

        if (!string.IsNullOrEmpty(email) && !string.IsNullOrEmpty(token))
        {
            IsResetToken = true;

        }
    }

    public async void SendResetPassword()
    {
        List<string> mailTo = new List<string>();

        string passwordResetToken;
        string passwordResetUrl;

        var user = await userManager.FindByEmailAsync(requestPasswordModel.Email);

        if (user != null)
        {
            passwordResetUrl = navigationManager.BaseUri;

            passwordResetToken = await userManager.GeneratePasswordResetTokenAsync(user);

            passwordResetToken = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(passwordResetToken));

            passwordResetUrl = "https://localhost:44384/ResetPassword?email=" + user.Email + "&token=" + passwordResetToken;

            mailTo.Add(requestPasswordModel.Email);

            //Send mail with the relevant token
            Webco.Email.Entities.EmailObject emailObject = new Webco.Email.Entities.EmailObject();
            emailObject.Email_To = mailTo;
            emailObject.Email_Subject = "Password Reset Webco !";
            emailObject.Email_Message = $"Hy There, <br> Please click this link to reset your password : <br><a href='{HtmlEncoder.Default.Encode(passwordResetUrl)}'> clikcing here </a>.";
            emailObject.SendEmail(emailObject);

            IsResetSend = true;
        }
        else
        {
            //it's a lie
            IsResetSend = true;
        }
    }

    public async void SetResetPassword()
    {
        List<string> mailTo = new List<string>();

        var user = await userManager.FindByEmailAsync(email);

        if (user != null)
        {
            token = System.Text.Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(token));

            var result = await userManager.ResetPasswordAsync(user, token, validatePasswordModel.ConfirmPassword);

            if (result.Succeeded)
            {

                mailTo.Add(email);

                //Send mail with the relevant token
                Webco.Email.Entities.EmailObject emailObject = new Webco.Email.Entities.EmailObject();
                emailObject.Email_To = mailTo;
                emailObject.Email_Subject = "Password Reset Webco !";
                emailObject.Email_Message = $"Hy There, <br> You password was just reset at webco. Not you ? <br> Contact webco for support.";
                emailObject.SendEmail(emailObject);

                navigationManager.NavigateTo("/LoginUserResetPasswordComplete", true);
            }
            else
            {
                navigationManager.NavigateTo("/LoginUserResetPasswordError", true);
            }
        }
        else
        {
            navigationManager.NavigateTo("/LoginUserResetPasswordError",true);
        }

    }

    public class InputModel
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; }
    }

    public class ResetPasswordModel
    {
        [Required]
        public string Password { get; set; }
        [Required]
        [Compare(nameof(Password))]
        public string ConfirmPassword { get; set; }
    }

}
于 2020-06-02T20:12:01.010 回答