# .Net 使用多重要素驗證(免費方案)
###### tags: `.net core` `Auth`
#### [來源連結](https://blog.darkthread.net/blog/mfa-with-ms-authenticator/)
驗證功能部分需安裝套件Otp.Net,QrCode產生部分參閱[另一篇筆記 ](https://hackmd.io/pfJWhzFiR96PD78eQC-EGA)
### Controller
```
public IActionResult Index(string Result=null)
{
//string sercret = Uri.EscapeDataString(Base32Encoding.ToString(KeyGeneration.GenerateRandomKey()));
string sercret = "7FXZV4THYPNLWPJHYFRNT7D2VWHZXUF7"; //實務上需另外儲存且每個人各不相同
ViewBag.QrCode =_qrcodeHelper.CreateQrCode(_MFAHelper.GenQRCodeUrl(sercret));
ViewBag.Sercret = sercret;
ViewBag.Result = Result;
return View();
}
public IActionResult VaildCode(string Code,string Secret)
{
var Result = _MFAHelper.ValidateTotp(Code,Secret);
if(Result.Item1) //驗證通過
{
}
return RedirectToAction("Index", new { Result = Result.Item2 });
}
```
### View
```
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<form action="Home/VaildCode">
<div>
<p>@ViewBag.Result</p>
<label>
請輸入驗證碼
<input name="Code" type="text">
<input hidden="hidden" name="Secret" type="text" value='@ViewBag.Sercret'>
</label>
<button type="submit">送出</button>
</div>
</form>
<img alt="" src='@ViewBag.QrCode' />
</div>
```
### Helper
```
public class MFAuthenticationHelper
{
//需安裝套件Otp.Net
public string GenQRCodeUrl(string Secret,string Lable="Dino",string Issuer= "TOTP測試")
{
return $"otpauth://totp/{Lable}?issuer={Uri.EscapeDataString(Issuer)}&secret={Secret}";
}
public (bool,string) ValidateTotp(string totp,string Secret = null, Totp totpInstance = null)
{
try
{
if(totp == null || Secret==null && totpInstance == null)
return (false, "驗證失敗");
if (totpInstance == null)
totpInstance = new Totp(Base32Encoding.ToBytes(Secret));
long timedWindowUsed;
if (totpInstance.VerifyTotp(totp, out timedWindowUsed))
return (true,$"驗證通過 - {timedWindowUsed}");
else
return (false, "驗證失敗");
}
catch (Exception ex)
{
Console.WriteLine("{0} Top Vaild Faill:{1}",DateTime.Now,ex.ToString());
return (false, "驗證失敗");
}
}
}
```