Files
17168ERP/web/App_Code/gauth/GoogleAuth.cs
2025-08-29 01:27:25 +08:00

166 lines
5.3 KiB
C#

using Google.Authenticator;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for GoogleAuth
/// </summary>
public class GoogleAuth
{
public string User { get; set; }
public string Password { get; set; }
public string WebTitle { get; set; }
public string WebKey { get; set; }
public string SecretKey { get; set; }
public SetupCode setupCode { get; set; }
public GoogleAuth()
{
//
// TODO: Add constructor logic here
//
WebKey = ConfigurationManager.AppSettings["SC"].ToString();
WebTitle = WebKey;//可為中文?
}
public Image CreateSecretKeyAndQrCode()
{
Image ret;
TwoFactorAuthenticator tfA = new TwoFactorAuthenticator();
string issuer = WebKey + ":" + User;//發行者:用戶+網站
string accountTitle = WebKey + "::" + User;//標題(可為中文字?)
string accountSecKey = Password + SecretKey;//密鑰:密碼+隨機
setupCode = tfA.GenerateSetupCode(
issuer, accountTitle, accountSecKey, false, 3);
//1. QRCode圖片從記憶體轉到畫面上
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(
setupCode.QrCodeSetupImageUrl.Replace("data:image/png;base64,", ""))))
{
ret = Image.FromStream(ms);
}
//2. 產生的金鑰與資訊
//this.textBox_Message.Text =
// "結合密鑰的文字 Account: " + textBox_account.Text + System.Environment.NewLine +
// "自已加密的密鑰 Secret Key: " + textBox_SecretKey.Text + System.Environment.NewLine +
// "手動輸入的密鑰 Encoded Key: " + setupCode.ManualEntryKey;
return ret;
}
public string ImageToBase64(Image image)
{
System.Drawing.Imaging.ImageFormat format = ImageFormat.Png;
string mime = "data:image/png;base64,";
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
// Convert byte[] to base 64 string
string base64String = mime+Convert.ToBase64String(imageBytes);
return base64String;
}
}
/// <summary>
/// 驗證碼是否正確
/// </summary>
/// <returns></returns>
public bool ValidateGoogleAuthCode(string ValidateCode)
{
string k = Password + SecretKey; //要存到資料庫, 才能重用
var r = false;
TwoFactorAuthenticator tfA = new TwoFactorAuthenticator();
r = tfA.ValidateTwoFactorPIN(k, ValidateCode);
return r;
}
/// <summary>
/// 產生Secret當前的驗證碼
/// </summary>
public List<string> GeneratorCurrentCode()
{
var resultArray = new TwoFactorAuthenticator().GetCurrentPINs(SecretKey);
var resultList = new List<string>(resultArray);
return resultList;
}
}
/*
# 例:
綁定資訊:
使用者帳號: user1
網站代號: erp17168
使用者密碼: G0t0r5hPel4EJnAfFkmhAI=
動態密鑰: aJn7TSc3Nl2UPUTWtiBE
setupCode: I4YHIMDSGVUFAZLMGRCUU3SBMZDGW3LIIFET2YKKNY3VIU3DGNHGYMSVKBKVIV3UNFBEK
---
# 傳回QRCODE
otpauth://totp/erp17168%3Auser1:erp17168:user1?secret=I4YHIMDSGVUFAZLMGRCUU3SBMZDGW3LIIFET2YKKNY3VIU3DGNHGYMSVKBKVIV3UNFBEK&issuer=erp17168%3Auser1
otpauth://totp/
erp17168:user1:erp17168:user1
?
secret=I4YHIMDSGVUFAZLMGRCUU3SBMZDGW3LIIFET2YKKNY3VIU3DGNHGYMSVKBKVIV3UNFBEK
&
issuer=erp17168%3Auser1
# 建立:
動態=亂數()
U="網站:用戶"
K="密碼+動態"
QRCODE= "otpauth://" + U + SecretKey(回傳的)
SecretKey:不用存
用戶拍QRCODE, 記在Google Anth. App中
每30秒自動更新一次
# 驗證:
(先檢查帳密:通過)
再傳出:
K="密碼+動態" (從資料庫抓:用戶)
V=(用戶即時輸入的驗證碼, 來自APP)
傳回:true / false
---
參考
https://dotblogs.com.tw/milkgreenteaprograme_c_sharp/2020/10/28/135725
https://github.com/gotoa1234/GoogleAuthenticatorExample
---
# 未實作功能
# button : 取得當前SecretKey的密碼
private void button_GeneratorCode_Click(object sender, EventArgs e)
{
DataGridViewRow row = (DataGridViewRow)dataGridView_KeyCode.RowTemplate.Clone();
var currentCodeList = GeneratorCurrentCode().Take(1);
var takeSingle = currentCodeList.Take(1).First();//取一筆做為比較
if (_lastCurrentCode != takeSingle)
{
_lastCurrentCode = takeSingle;
var currentDateTimeNow = DateTime.Now;
foreach (var code in currentCodeList)
{
dataGridView_KeyCode.Rows.Add(
currentDateTimeNow.ToString("yyyy/MM/d HH:mm:ss"),
textBox_account.Text,
textBox_SecretKey.Text,
code);
}
//排序
dataGridView_KeyCode.Sort(dataGridView_KeyCode.Columns["GeneratorDateTime"], System.ComponentModel.ListSortDirection.Descending);
}
}
# grid
產生時間:GeneratorDateTime
手產字串:Account
手產金鑰:SecretKey
當前驗證金鑰:CurrentCode
*/