ASP.NET Core 双因素验证2FA 实战经验分享

640?

必读

本文源码核心逻辑使用AspNetCore.Totp,为什么不使用AspNetCore.Totp而是使用源码封装后面将会说明。

为了防止不提供原网址的转载,特在这里加上原文链接:

双因素认证

双因素身份认证就是通过你所知道再加上你所能拥有的这二个要素组合到一起才能发挥作用的身份认证系统。双因素认证是一种采用时间同步技术的系统,采用了基于时间、事件和密钥三变量而产生的一次性密码来代替传统的静态密码。每个动态密码卡都有一个唯一的密钥,该密钥同时存放在服务器端,每次认证时动态密码卡与服务器分别根据同样的密钥,同样的随机参数(时间、事件)和同样的算法计算了认证的动态密码,从而确保密码的一致性,从而实现了用户的认证。就像我们去银行办卡送的口令牌.640?wx_fmt=jpeg

一. 前言

最近公司内部SSO登录一直在找一种安全的方式,目前已实现方案:账号密码登录以及手机验证码登录,通过Apollo切换不同的登录方式,想起18年看到AspNetCore.Totp并也编写了DemodotNetCore-2FA登录,将之前写的再完善并且在此记录和分析,希望对大家有些帮助。

二. AspNetCore.Totp

说明一下为什么要用AspNetCore.Totp修改并且重新打包Brook.TotpAspNetCore.Totp在生成二维码链接时会访问404(google.com)网站,国内基本无法使用,这很不清真,还有就是注入需要注入接口和实现类,使用起来很繁琐,所以才萌生了让使用起来更方便,并且不依赖Google生成二维码的想法

1.生成二维码

accountIdentity = accountIdentity.Replace(" ", "");var encodedSecretKey = Base32.Encode(accountSecretKey);var provisionUrl = UrlEncoder.Encode(string.Format("otpauth://totp/{0}?secret={1}&issuer={2}", accountIdentity, encodedSecretKey, UrlEncoder.Encode(issuer)));var protocol = useHttps ? "https" : "http";var url = $"{protocol}://chart.googleapis.com/chart?cht=qr&chs={qrCodeWidth}x{qrCodeHeight}&chl={provisionUrl}";var totpSetup = new TotpSetup{QrCodeImage = this.GetQrImage(url),ManualSetupKey = encodedSecretKey};

2.注入方式

  • Startup注入

services.AddSingleton<ITotpSetupGenerator, TotpSetupGenerator>();
services.AddSingleton<ITotpValidator, TotpValidator>();
services.AddSingleton<ITotpGenerator, TotpGenerator>();
  • Controller注入

 private readonly ITotpGenerator _totpGenerator;private readonly ITotpSetupGenerator _totpSetupGenerator;private readonly ITotpValidator _totpValidator;public ValuesController(ITotpSetupGenerator totpSetupGenerator){_totpSetupGenerator = totpSetupGenerator;_totpGenerator = new TotpGenerator();_totpValidator = new TotpValidator(_totpGenerator);}

三. Brook.Totp

1.二维码使用QRCoder来生成,不依赖外部网络

        /// <summary>/// 生成二维码/// </summary>/// <param name="provisionUrl"></param>/// <param name="pixelsPerModule"></param>/// <returns></returns>private string GetQrBase64Imageg(string provisionUrl,int pixelsPerModule){QRCodeGenerator qrGenerator = new QRCodeGenerator();QRCodeData qrCodeData = qrGenerator.CreateQrCode(provisionUrl, QRCodeGenerator.ECCLevel.Q);Base64QRCode qrCode = new Base64QRCode(qrCodeData);string qrCodeImageAsBase64 = qrCode.GetGraphic(2);return  $"data:image/png;base64,{qrCodeImageAsBase64}";}

2.注入方式

  • Startup注入

services.AddBrookTotp();
  • Controller注入

private readonly ITotp _totp;
public AccountController(ITotp totp)
{_totp = totp;
}

四.双因素APP

推荐使用Microsoft Authenticator支持IOS、安卓可自动备份

五. 完整流程效果图

使用Microsoft Authenticator640?wx_fmt=jpeg

  1. 正常登录640?wx_fmt=jpeg

  2. 登录成功后绑定,使用Microsoft Authenticator扫描二维码,然后输入显示的6位数字验证码640?wx_fmt=jpeg

  3. 绑定后再次登录640?wx_fmt=jpeg

六.如何使用

所有源代码请参照我的GitHub https://github.com/yuefengkai/Brook.Totp

  1. EF Core In Memory Database所有的数据只存在内存中

  2. Cache in-memory

  3. dotNET Core Authentication

下方只展示部分代码

1.新建netCoreMVC项目添加Nuget包Brook.Totp

640?wx_fmt=jpeg

2.注入方式

  • Startup注入

services.AddMemoryCache();
services.AddSingleton<ICacheManage, CacheManage>();
services.AddBrookTotp();
services.AddDbContext<BrookTotpDBContext>(options => options.UseInMemoryDatabase(databaseName: "BrookTotpDB"));
  • Controller使用

private readonly ITotp _totp;
public AccountController(ITotp totp)
{_totp = totp;
}
//获取二维码
[Authorize]
public IActionResult GetQr()
{var totpSetup = _totp.GenerateUrl("dotNETBuild", CurremtUser.Email, CurremtUser.SecretKeyFor2FA);return Json(new { qrCodeContennt = totpSetup.QrCodeImageContent });
}
//验证双因素校验码
[Authorize]
[HttpPost]
public async Task<IActionResult> Valid(int code)
{var valid = _totp.Validate(CurremtUser.SecretKeyFor2FA, code, 30);if (!valid){return Json(new { result = 0, msg = "2FA校验失败" });}//校验成功后 如果是第一次绑定校验 需将用户的accountSecretKey 存入数据库CurremtUser.IsOpen2FA = true;await _userService.UpdateAsync(CurremtUser);_cacheManage.Remove(string.Format(CacheKeys.GetUserForEmail, CurremtUser.Email));var claims = new List<Claim>{new Claim("user", CurremtUser.Email),new Claim("role", "Member")};await HttpContext.SignInAsync(new ClaimsPrincipal(new ClaimsIdentity(claims, "Cookies", "user", "role")));return Json(new { result = 1, msg = "2FA校验成功", url = "/Home/Index" });
}

七.写在最后

以上所有源代码已开源在 https://github.com/yuefengkai/Brook.Totp

作者:Brook

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

银行卡BIN码大全

BIN号即银行标识代码的英文缩写。BIN由6位数字表示,出现在卡号的前6位,由国际标准化组织(ISO)分配给各从事跨行转接交换的银行卡组织。银行卡的卡号是标识发卡机构和持卡人信息的号码,由以下三部分组成:发卡行标识代码(BIN号)、发…

HDU 1404 Digital Deletions(博弈 + SG函数打表)

Digital Deletions 思路 一道博弈论的题目,考虑到题目所给的范围是字符长度为1−>61-> 61−>6,所以我们可以考虑暴力打表出10610 ^ 6106内的所有状态, 确定基本的两个状态sg[0]1[先手胜],sg[1]0[后手胜]sg[0] 1[先手胜], sg[1] …

cjy基础动态规划

cjy基础动态规划 P2219 [HAOI2007]修筑绿化带 对于一个nm的矩形空间内,然后选择一个ab的矩形加上它所在部分的权值,然后在内部再选择一个c*d的矩形,然后减去它的权值和,求解最大的权值。 首先我们可以通过枚举求得所有右下角对…

Be the Winner(结论:反nim博弈)

Be the Winner 结论 记一个结论:反nim博弈,先手必胜1:尼姆和为零,所有值为1。2:尼姆和不为零,有一个大于1的数。 代码 /*Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #inc…

结合“性能监视器” 排查、处理性能瓶颈导致应用吞吐率等指标上不去的问题...

双11备战前夕,总绕不过性能压测环节,TPS 一直上不去 / 不达标,除了代码上的问题外,服务器环境、配置、网络、磁盘、CPU 亦是导致性能瓶颈的重要一环,本文旨在分享最近项目性能压测过程中的排查经验,文中的表…

坑点、问题记录

1:项目Spring版本升级之后,服务启动有如下报错: 六月 02, 2018 5:51:49 下午 org.apache.catalina.core.ApplicationContext log 严重: StandardWrapper.Throwable org.springframework.beans.factory.BeanCreationException: Error creatin…

E - The Imp(博弈/动态规划)

E - The Imp 有n个物品且分别为价值vi成本ci,然后每次选择购买后,有人可以使用k次魔法,使得物品消失但是成本仍然花费了,求解最大收益。 首先最后的最优解序列,一定是可以由自己决定的,那么它一定满足vi递…

Mult-Nim博弈

Nim or not Nim? 结论 Mult−NimMult-NimMult−Nim博弈:有nnn堆石子,两个人可以从任意一堆石子中拿任意多个石子(不能不拿)或把一堆数量不少于22石子分为两堆不为空的石子,没法拿的人失败,问谁会胜利。 结论SG(x)x−1[xmod40],…

提高工作效率的方法

1:集中注意力、专注度 1)远离分散你注意力的东西(如:将手机锁到柜子里) 2)保持主航道不变:在做A的时候,不要因为想到了B,就去做B。而是判断B的重要、紧急程度&#xff…

背包dp的核心思想(动态规划)

背包dp 突然发现我一直没有真正理解背包,真正的背包应该是用空间换时间的一种dp方法,本质上就是n个物品选或不选,理论上有2n2^n2n种可能结果,但是背包利用的就是值域很小这一特点来重叠子结构,所以背包本质上处理的应该是一个集合…

秒半价,限四天!Vostro极致轻薄全能本,助你全能全开!

在信息化时代,电脑就是你工作和创业的“合伙人”!每天比别人多处理几件任务、每天比别人快20分钟,每天比别人少重启和崩溃几次,日积月累获益多到算不过来!小编四处打探,有三款王者电脑重磅优惠,…

HDU 3590 PP and QQ(反nim博弈,删边游戏)

PP and QQ 思路 删边游戏了解一下,其实就是个nim博弈吧,只是删边个数有特殊限制, 然后就是一个反nim博弈了。 删边定理: 遇到分叉口时,它的子树上的可操作的sg函数为所有子树节点的sg函数的异或值, 然后…

【活动】侬好上海,Microsoft Reactor来啦

在美国纽约、旧金山和雷德蒙德,在英国伦敦,在澳大利亚悉尼,在以色列特拉维夫,分别都有这样一处专为开发者打造的宝地,在这些地方:❖ 经常举办各种免费的技术讲座,与大家分享最新技术和产品❖ 频…

JDK演化系列(1.0~~~1.9)

系列文章导读 JDK 1.0包含的功能 JDK 1.1新增&优化&去掉的功能 JDK 1.2新增&优化&去掉的功能 JDK 1.3新增&优化&去掉的功能 JDK 1.4新增&优化&去掉的功能 JDK 1.5新增&优化&去掉的功能 JDK 1.6新增&优化&去掉的功能 J…

#6682. 梦中的数论(Min25筛)

#6682. 梦中的数论 推式子 ∑i1n∑jkn∑k1n[(j∣i)∧((jk)∣i)]显然有jk>j,所以我们另jkk′,有j>k′,并且j,k′都是i的约数这就相当于在σ(i)中选取一对有序对了,所以总的选法有C(σ(i),2)种原式∑i1nσ(i)(σ(i)−1)2∑i1nσ2(i)−∑…

A. [2021.1.29多校省选模拟11]最大公约数(杜教筛/数论)

A. [2021.1.29多校省选模拟11]最大公约数 这是一个杜教筛的经典题目,最后我们只需要筛一下1∗xμ(x)1*x\mu(x)1∗xμ(x)这个函数的前缀和即可,然后看到有111这个函数,我们下意识应该想到的就是μ\muμ,然后又有xμ(x)x\mu(x)xμ(x…

.NET Core 小程序开发零基础系列(2)——小程序服务通知(模板消息)

基于上一篇文件“.NET Core 小程序开发零基础系列(1)——开发者启用并校验牵手成功”的反映,个人觉得效果很不错,大家对公众号开发还是有很大需求的,同时也收到了很多同学的问题,后面我也会通过实战性文章慢…

Java工程师修炼之路

文章来自于微信公众号:Hollis,作者网站:https://www.hollischuang.com/ 转载过来方便查看 1 基础篇 01 面向对象 → 什么是面向对象 面向对象、面向过程 面向对象的三大基本特征和五大基本原则 → 平台无关性 Java 如何实现的平台无关 …

P4900 食堂(数学式子推导)

P4900 食堂 推导 ans∑i1n∑j1iij−∑i1n∑j1i⌊ij⌋前项为∑i1ni∑j1iinv(j),两次前缀和即可得到后项为∑i1n∑j1i⌊ij⌋∑i1n∑j1id(j),nloglogn2n即可得到ans \sum_{i 1} ^{n} \sum_{j 1} ^ {i} \frac{i}{j} - \sum_{i 1} ^{n} \sum_{j 1} ^{i} \lfloor\frac{i}{j} \r…

[PowerShell]人人都值得学一点PowerShell实现自动化(2)有哪些可用的场景及方式?

部分读者反应太多知识要学了,学完一轮又一轮,笔者也不想单单为了制造学习而学习,所有Excel催化剂所发布的内容,都是笔者所亲自使用到的,当然很多领域也没有深挖到很底的程度。PowerShell使用场景虽然说PowerShell也是在…