Asp.net mvc 阻止没有确认电子邮件的用户使用标识2登录ASP.Net MVC

Asp.net mvc 阻止没有确认电子邮件的用户使用标识2登录ASP.Net MVC,asp.net-mvc,asp.net-identity,Asp.net Mvc,Asp.net Identity,在microsoft Identity 2中,用户可以确认这些电子邮件地址。我从中下载了Identity 2示例项目。在该项目中,用户确认了他们的电子邮件与谁不确认他们的电子邮件之间没有任何区别。我想问人们如何不确认他们的电子邮件无法登录这是我尝试的: public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { if (!ModelState.IsValid)

在microsoft Identity 2中,用户可以确认这些电子邮件地址。我从中下载了Identity 2示例项目。在该项目中,用户确认了他们的电子邮件与谁不确认他们的电子邮件之间没有任何区别。我想问人们如何不确认他们的电子邮件无法登录这是我尝试的:

public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }


        var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true);
        switch (result)
        {
            case SignInStatus.Success:
                {


                    var user = await UserManager.FindByNameAsync(model.Email);
                    if (user != null)
                    {
                        if (!await UserManager.IsEmailConfirmedAsync(user.Id))
                        {
                            //first I tried this.
                            //return LogOff();
                            HttpContext.Server.TransferRequest("~/Account/LogOff");
                            return RedirectToAction("Login");
                        }
                    }

                    return RedirectToLocal(returnUrl);
                }
            case SignInStatus.LockedOut:
                return View("Lockout");
            case SignInStatus.RequiresVerification:
                return RedirectToAction("SendCode", new { ReturnUrl = returnUrl });
            case SignInStatus.Failure:
            default:
                ModelState.AddModelError("", "Invalid login attempt.");
                return View(model);

我已经在谷歌上搜索了好几天,没有任何运气

与其移动到另一个页面,为什么不完成此页面并重定向到正确的操作/视图:

if (!await UserManager.IsEmailConfirmedAsync(user.Id))
{
    return RedirectToAction("ConfirmEmailAddress", new { ReturnUrl = returnUrl });
}

您确实需要一个名为
ConfirmEmailAddress
的操作(可能还有一个视图)。

我会让管理员创建一个没有任何密码的用户。带有链接的电子邮件应发送给用户。然后,用户被引导到SetPassword页面以设置新密码。这样,任何人都无法访问用户帐户,除非他确认并设置密码

不使用密码调用CreateAsync

var adminresult = await UserManager.CreateAsync(user);
将管理员重定向到新的自定义视图,如“电子邮件已发送给用户”

@{
ViewBag.Title=“创建新用户并发送电子邮件”;
}
@ViewBag.Title。

新用户必须按照说明完成用户创建过程。

请更改此代码以在IdentityConfig中注册电子邮件服务以发送电子邮件。


可能有点晚了,但我希望它能帮助其他人

加上这个

var userid = UserManager.FindByEmail(model.Email).Id;
        if (!UserManager.IsEmailConfirmed(userid))
        {
            return View("EmailNotConfirmed");
        }
以前

var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
第一段代码只检查模型中的电子邮件是否存在于数据库中,并获取其id,以检查是否未确认,如果未确认,则向用户返回一个视图,该视图显示为已确认,如果已确认,则只允许用户登录

然后像这样删除对结果开关的更改

switch (result)
        {
            case SignInStatus.Success:
                    return RedirectToLocal(returnUrl);
            case SignInStatus.LockedOut:
                return View("Lockout");
            case SignInStatus.RequiresVerification:
                return RedirectToAction("SendCode", new { ReturnUrl = returnUrl });
            case SignInStatus.Failure:
            default:
                ModelState.AddModelError("", "Invalid login attempt.");
                return View(model);
        }

有一个解决方案,它可能不是最好的方法,但它是有效的。首先让我试着澄清为什么你的方法不起作用

在提到的其中一条注释中,AuthenticationManager使用。为了更新cookie,您需要使用另一个页面将其发送到客户端。这就是TransferRequest不起作用的原因

如何处理电子邮件验证?我使用的策略是:

1) 成功这意味着用户已登录

2) 未确认电子邮件时:向使用的电子邮件地址发送电子邮件。这是安全的,因为用户已登录。我们只是在验证电子邮件之前阻止进一步访问。每次用户在未验证电子邮件的情况下尝试登录时,都会发送一封新的电子邮件(具有相同的链接)。这可以通过跟踪发送电子邮件的数量来限制

3) 我们无法使用注销:这是HttpPost并使用ValidateAntiForgeryToken

4) 重定向到显示已发送电子邮件的消息的页面(HttpGet,需要授权)。输入时,请注销用户

5) 对于其他验证错误,请重定向到另一个方法以注销(HttpGet,需要授权)。无需查看,重定向到登录页面

在代码中:更新AccountController中的代码。登录到:

        case SignInStatus.Success:
        {
            var currentUser = UserManager.FindByNameAsync(model.Email);
            if (!await UserManager.IsEmailConfirmedAsync(currentUser.Id))
            {
                // Send email
                var code = await UserManager.GenerateEmailConfirmationTokenAsync(currentUser.Id);
                var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = currentUser.Id, code = code}, protocol: Request.Url.Scheme);
                await UserManager.SendEmailAsync(currentUser.Id, "Confirm your account", string.Format("Please confirm your account by clicking this link: <a href=\"{0}\">link</a>", callbackUrl));
                // Show message
                return RedirectToAction("DisplayEmail");
            }
            // Some validation
            if (true)
            {
                return RedirectToAction("SilentLogOff");
            }
            return RedirectToLocal(returnUrl);
        }
DisplayEmail.cshtml

@{
    ViewBag.Title = "Verify e-mail";
}

<h2>@ViewBag.Title.</h2>
<p class="text-info">
    Please check your email and confirm your email address.
</p>
@{
ViewBag.Title=“验证电子邮件”;
}
@ViewBag.Title。

请检查您的电子邮件并确认您的电子邮件地址。

您会注意到,在验证电子邮件之前,用户无法访问其他页面。我们能够使用SignInManager的功能

这种方法可能存在一个问题(我可以想到),即用户在发送电子邮件时登录,并且用户被重定向到DisplayMessage视图。这可能不是一个真正的问题,但它表明我们并没有阻止用户登录,只是通过自动注销用户来拒绝登录后的进一步访问

==更新====

请注意,必须正确处理例外情况。在这种情况下,授予用户访问权限,然后撤销访问权限。但是,如果在注销之前发生异常,并且未捕获该异常,则用户将保持登录状态

当邮件服务器不可用或凭据为空或无效时,可能会发生异常


=============

如果数据存储中根本不存在电子邮件,@INFINITY_18的回答可能会导致对象引用未设置为对象实例的
错误。在这种情况下,为什么不返回带有模型错误的登录视图呢

我建议如下:

var userid = UserManager.FindByEmail(model.Email)?.Id;
if (string.IsNullOrEmpty(userid) || !UserManager.IsEmailConfirmed(userid)))
{
    ModelState.AddModelError("", "Invalid login attempt.");
    return View(model);
}

需要电子邮件确认

最好的做法是确认新用户注册的电子邮件,以验证他们没有模仿其他人(也就是说,他们没有注册其他人的电子邮件)。假设你有一个讨论论坛,你想阻止“yli@example.com“从注册为”nolivetto@contoso.com.“没有电子邮件确认,”nolivetto@contoso.com“可能会从你的应用程序中收到不需要的电子邮件。假设用户意外注册为“ylo@example.com如果没有注意到“yli”的拼写错误,他们将无法使用密码恢复,因为应用程序没有正确的电子邮件。电子邮件确认仅对机器人提供有限的保护,不提供对已确定的垃圾邮件发送者的保护,这些垃圾邮件发送者有许多可用于注册的工作电子邮件别名

您通常希望防止新用户在收到确认电子邮件之前向您的网站发布任何数据

更新ConfigureServices以要求确认电子邮件: ​

public void配置服务(IServiceCollection服务)
{
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”));
services.AddIdentity(配置=>
{
config.SignIn.RequireConfirmedEmail=true;
})
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
//添加应用程序服务。
services.AddTransient();
services.AddMvc();
服务配置(Configu
// GET: /Account/SilentLogOff
[HttpGet]
[Authorize]
public ActionResult SilentLogOff()
{
    // Sign out and redirect to Login
    AuthenticationManager.SignOut();
    return RedirectToAction("Login");
}

// GET: /Account/DisplayEmail
[HttpGet]
[Authorize]
public ActionResult DisplayEmail()
{
    // Sign out and show DisplayEmail view
    AuthenticationManager.SignOut();
    return View();
}
@{
    ViewBag.Title = "Verify e-mail";
}

<h2>@ViewBag.Title.</h2>
<p class="text-info">
    Please check your email and confirm your email address.
</p>
var userid = UserManager.FindByEmail(model.Email)?.Id;
if (string.IsNullOrEmpty(userid) || !UserManager.IsEmailConfirmed(userid)))
{
    ModelState.AddModelError("", "Invalid login attempt.");
    return View(model);
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>(config =>
        {
            config.SignIn.RequireConfirmedEmail = true;
        })
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    // Add application services.
    services.AddTransient<IEmailSender, EmailSender>();

    services.AddMvc();

    services.Configure<AuthMessageSenderOptions>(Configuration);
}