作者: Rick Anderson 和 Swiss-Devs
警告
使用基于时间的一次性密码算法(TOTP)的双重身份验证(2FA)验证器应用是 2FA 的行业推荐方法。 相较于 SMS 2FA,更推荐使用 TOTP 的 2FA。 有关详细信息,请参阅 ASP.NET Core for ASP.NET Core 2.0 或更高版本中为 TOTP 验证器应用启用 QR 码生成 。
本教程演示如何使用短信设置双因素身份验证(2FA)。 说明适用于 twilio 和 ASPSMS(https://www.aspsms.com/asp.net/identity/core/testcredits/
),但你可以使用任何其他 SMS 提供程序。 建议在开始本教程之前完成 帐户确认和密码恢复 。
创建新的 ASP.NET Core 项目
创建一个新的 ASP.NET 核心 Web 应用,其中包含 Web2FA
单个帐户。 按照ASP.NET Core 中的强制 HTTPS中的说明进行设置,并强制使用 HTTPS。
创建短信帐户
创建短信帐户,例如来自twilio或ASPSMS(https://www.aspsms.com/asp.net/identity/core/testcredits/
)。 记录身份验证凭据(对于 twilio:accountSid 和 authToken,对于 ASPSMS:Userkey 和 Password)。
找出 SMS 提供程序凭据
Twilio:
在 Twilio 帐户的“仪表板”选项卡中,复制 帐户 SID 和 身份验证令牌。
ASPSMS:
在帐户设置中,导航到 Userkey 并将其与 密码一起复制。
稍后,我们将这些值与密钥SMSAccountIdentification
SMSAccountPassword
中的机密管理器工具一起存储。
指定发送者身份/发件人
Twilio: 在“号码”选项卡中,复制 Twilio 电话号码。
ASPSMS: 在“解锁发起方”菜单中,解锁一个或多个发起方或选择一个字母数字发起方(并非所有网络支持)。
稍后,我们将使用密钥 SMSAccountFrom
中的机密管理器工具存储此值。
请提供短信服务的凭据
我们将使用 “选项”模式 访问用户帐户和密钥设置。
- 创建一个类来提取安全短信密钥。 对于此示例,将在
SMSoptions
文件中创建Services/SMSoptions.cs
类。
namespace Web2FA.Services
{
public class SMSoptions
{
public string SMSAccountIdentification { get; set; }
public string SMSAccountPassword { get; set; }
public string SMSAccountFrom { get; set; }
}
}
设置 SMSAccountIdentification
、SMSAccountPassword
和 SMSAccountFrom
,并使用 机密管理器工具。 例如:
C:/Web2FA/src/WebApp1>dotnet user-secrets set SMSAccountIdentification 12345
info: Successfully saved SMSAccountIdentification = 12345 to the secret store.
- 为 SMS 提供程序添加 NuGet 包。 请在软件包管理控制台(PMC)中运行:
Twilio:
Install-Package Twilio
ASPSMS:
Install-Package ASPSMS
- 在
Services/MessageServices.cs
文件中添加代码以启用短信。 使用 Twilio 或 ASPSMS 的对应部分:
Twilio:
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;
namespace Web2FA.Services
{
// This class is used by the application to send Email and SMS
// when you turn on two-factor authentication in ASP.NET Identity.
// For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
public class AuthMessageSender : IEmailSender, ISmsSender
{
public AuthMessageSender(IOptions<SMSoptions> optionsAccessor)
{
Options = optionsAccessor.Value;
}
public SMSoptions Options { get; } // set only via Secret Manager
public Task SendEmailAsync(string email, string subject, string message)
{
// Plug in your email service here to send an email.
return Task.FromResult(0);
}
public Task SendSmsAsync(string number, string message)
{
// Plug in your SMS service here to send a text message.
// Your Account SID from twilio.com/console
var accountSid = Options.SMSAccountIdentification;
// Your Auth Token from twilio.com/console
var authToken = Options.SMSAccountPassword;
TwilioClient.Init(accountSid, authToken);
return MessageResource.CreateAsync(
to: new PhoneNumber(number),
from: new PhoneNumber(Options.SMSAccountFrom),
body: message);
}
}
}
ASPSMS:
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
namespace Web2FA.Services
{
// This class is used by the application to send Email and SMS
// when you turn on two-factor authentication in ASP.NET Identity.
// For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
public class AuthMessageSender : IEmailSender, ISmsSender
{
public AuthMessageSender(IOptions<SMSoptions> optionsAccessor)
{
Options = optionsAccessor.Value;
}
public SMSoptions Options { get; } // set only via Secret Manager
public Task SendEmailAsync(string email, string subject, string message)
{
// Plug in your email service here to send an email.
return Task.FromResult(0);
}
public Task SendSmsAsync(string number, string message)
{
ASPSMS.SMS SMSSender = new ASPSMS.SMS();
SMSSender.Userkey = Options.SMSAccountIdentification;
SMSSender.Password = Options.SMSAccountPassword;
SMSSender.Originator = Options.SMSAccountFrom;
SMSSender.AddRecipient(number);
SMSSender.MessageData = message;
SMSSender.SendTextSMS();
return Task.FromResult(0);
}
}
}
配置启动以使用 SMSoptions
请在Startup.cs
的ConfigureServices
方法中将SMSoptions
添加到服务容器:
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.Configure<SMSoptions>(Configuration);
}
启用双因素身份验证
打开Views/Manage/Index.cshtml
Razor视图文件并删除注释字符,这样就没有任何标记被注释掉。
使用双重身份验证登录
- 运行应用并注册新用户
- 点击您的用户名,该动作会在管理控制器中的
Index
操作方法中激活。 然后点击电话号码 “添加 ”链接。
- 添加一个将接收验证码的电话号码,然后点击 “发送验证码”。
- 将收到包含验证码的短信。 输入并点击 “提交”
如果未收到短信,请参阅 twilio 日志页。
- “管理”视图显示已成功添加电话号码。
- 点击 “启用” 以启用双重身份验证。
测试双因素身份验证
登出。
登录。
用户帐户已启用双重身份验证,因此必须提供第二重身份验证。 在本教程中,你已启用电话验证。 内置模板还允许将电子邮件设置为第二个因素。 可以为身份验证设置其他第二个因素,例如 QR 码。 点击“提交”。
输入在短信中获取的代码。
单击“ 记住此浏览器 ”复选框将免除在使用相同设备和浏览器时需要使用 2FA 登录。 启用 2FA 并单击“ 记住”此浏览器 将为你提供针对尝试访问帐户的恶意用户的强 2FA 保护,前提是他们无权访问你的设备。 可以在经常使用的任何专用设备上进行此操作。 通过设置 “记住此浏览器”,可以从不经常使用的设备获取 2FA 的附加安全性,并且无需在自己的设备上通过 2FA 即可获得便利。
用于防范暴力攻击的帐户锁定
建议使用 2FA 锁定帐户。 用户通过本地帐户或社交帐户登录后,将存储 2FA 的每个失败尝试。 如果达到最大失败的访问尝试次数,则用户将被锁定(默认值:5 分钟锁定后 5 次失败的访问尝试)。 成功的身份验证会重置失败的访问尝试计数并重置时钟。 可以通过设置MaxFailedAccessAttempts和DefaultLockoutTimeSpan来确定最大失败访问尝试次数和锁定时间。 以下配置将在 10 次访问尝试失败后将帐户锁定 10 分钟:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
services.Configure<IdentityOptions>(options =>
{
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
});
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.Configure<SMSoptions>(Configuration);
}
请确认PasswordSignInAsync是否将lockoutOnFailure
设置为true
:
var result = await _signInManager.PasswordSignInAsync(
Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);