fromnowoncoding commited on
Commit
7c33f9c
·
verified ·
1 Parent(s): c6d85e8

增加開啟頁面初始化觸發

Browse files
Files changed (1) hide show
  1. app.py +39 -52
app.py CHANGED
@@ -6,10 +6,10 @@ import time
6
  import requests
7
  import json
8
  import binascii
 
9
 
10
  # Base32 解碼 (類似於 PHP 中 Base32::decode)
11
  def base32_decode(encoded_secret):
12
- # 檢查 Base32 字符串的長度是否為 8 的倍數,不是的話進行填充
13
  missing_padding = len(encoded_secret) % 8
14
  if missing_padding != 0:
15
  encoded_secret += '=' * (8 - missing_padding)
@@ -20,93 +20,80 @@ def base32_decode(encoded_secret):
20
 
21
  # HOTP 驗證碼生成
22
  def generate_hotp(secret, counter):
23
- # 將密鑰解碼 (Base32)
24
  decoded_secret = base32_decode(secret)
25
-
26
- # 將計數器轉換為 8 位字節
27
- counter_bytes = counter.to_bytes(8, byteorder='big')
28
-
29
- # 使用 HMAC-SHA1 生成哈希值
30
  hmac_hash = hmac.new(decoded_secret, counter_bytes, hashlib.sha1).digest()
31
-
32
- # 動態截斷算法
33
  return dynamic_truncation(hmac_hash) % (10 ** 6)
34
 
35
  # 動態截斷算法
36
  def dynamic_truncation(hmac_value):
37
- # 取哈希值的最後一個字節並將其最低 4 位作為偏移量
38
  offset = hmac_value[-1] & 0x0F
39
-
40
- # 從偏移量開始取 4 字節,組成 31-bit 整數
41
  code = (
42
- ((hmac_value[offset] & 0x7f) << 24) |
43
- ((hmac_value[offset + 1] & 0xff) << 16) |
44
- ((hmac_value[offset + 2] & 0xff) << 8) |
45
- (hmac_value[offset + 3] & 0xff)
46
  )
47
  return code
48
 
49
- # 驗證碼生成 (使用基於時間的計數器,每 30 秒更新一次)
50
  def generate_otp(secret):
51
- counter = int(time.time() // 30) # 以 30 秒為單位的計數器
52
  otp_code = generate_hotp(secret, counter)
53
  return f"{otp_code:06d}"
54
 
55
  # 發送訊息到 Slack
56
  def send_message_to_slack(message):
57
- slack_webhook_url = os.getenv('SLACK_WEBHOOK_URL')
58
-
59
  if not slack_webhook_url:
60
  raise ValueError("SLACK_WEBHOOK_URL is not set in environment variables.")
61
-
62
- payload = {
63
- "text": message
64
- }
65
  response = requests.post(slack_webhook_url, json=payload)
66
-
67
  if response.status_code != 200:
68
- raise ValueError(f"Request to Slack returned an error {response.status_code}, the response is: {response.text}")
69
-
 
70
  print(f"Message sent to Slack: {response.status_code}")
71
 
72
  # 發送 2FA 驗證碼到 Slack
73
  def send_2fa_code(name, service_type):
74
- # 從環境變數中讀取 Gmail 的 2FA 密鑰
75
- secret = os.getenv('gmail_2fa') # 假設 service_type 是 'hi@gaiconf.com',並且 Gmail 密鑰存儲在環境變數中
76
-
77
  if not secret:
78
  return f"{service_type} 的密鑰沒有正確設置為環境變數。"
79
-
80
- # 生成驗證碼
81
  code = generate_otp(secret)
82
-
83
- # 組合訊息
84
  message = f"{name} 要登入 {service_type} 帳號,驗證碼為 {code}"
85
-
86
- # 發送訊息到 Slack
87
  send_message_to_slack(message)
88
-
89
- # 返回提示訊息給使用者,不顯示實際驗證碼
90
  return "驗證碼已發送至指定的 Slack 頻道。"
91
 
92
- # 前端表單邏輯 (Gradio 表單)
93
- import gradio as gr
 
 
 
 
 
94
 
 
95
  def two_fa_interface(name, service_type):
96
  return send_2fa_code(name, service_type)
97
 
98
  # Gradio 介面
99
- service_options = ["hi@gaiconf.com"] # 未來可以擴展更多服務選項
100
- iface = gr.Interface(
101
- fn=two_fa_interface,
102
- inputs=[
103
- gr.Textbox(label="請輸入您的暱稱", placeholder="您的暱稱"),
104
- gr.Dropdown(label="選擇服務", choices=service_options)
105
- ],
106
- outputs="text",
107
- title="GAI 總籌兩步驗證",
108
- description="六位數驗證碼將會傳送至指定的 Slack 頻道。"
109
- )
 
 
 
 
 
110
 
111
  # 啟動應用
112
- iface.launch(share=True)
 
6
  import requests
7
  import json
8
  import binascii
9
+ import gradio as gr
10
 
11
  # Base32 解碼 (類似於 PHP 中 Base32::decode)
12
  def base32_decode(encoded_secret):
 
13
  missing_padding = len(encoded_secret) % 8
14
  if missing_padding != 0:
15
  encoded_secret += '=' * (8 - missing_padding)
 
20
 
21
  # HOTP 驗證碼生成
22
  def generate_hotp(secret, counter):
 
23
  decoded_secret = base32_decode(secret)
24
+ counter_bytes = counter.to_bytes(8, byteorder="big")
 
 
 
 
25
  hmac_hash = hmac.new(decoded_secret, counter_bytes, hashlib.sha1).digest()
 
 
26
  return dynamic_truncation(hmac_hash) % (10 ** 6)
27
 
28
  # 動態截斷算法
29
  def dynamic_truncation(hmac_value):
 
30
  offset = hmac_value[-1] & 0x0F
 
 
31
  code = (
32
+ ((hmac_value[offset] & 0x7f) << 24)
33
+ | ((hmac_value[offset + 1] & 0xff) << 16)
34
+ | ((hmac_value[offset + 2] & 0xff) << 8)
35
+ | (hmac_value[offset + 3] & 0xff)
36
  )
37
  return code
38
 
39
+ # 驗證碼生成 (基於時間的計數器,每 30 秒更新一次)
40
  def generate_otp(secret):
41
+ counter = int(time.time() // 30)
42
  otp_code = generate_hotp(secret, counter)
43
  return f"{otp_code:06d}"
44
 
45
  # 發送訊息到 Slack
46
  def send_message_to_slack(message):
47
+ slack_webhook_url = os.getenv("SLACK_WEBHOOK_URL")
 
48
  if not slack_webhook_url:
49
  raise ValueError("SLACK_WEBHOOK_URL is not set in environment variables.")
50
+ payload = {"text": message}
 
 
 
51
  response = requests.post(slack_webhook_url, json=payload)
 
52
  if response.status_code != 200:
53
+ raise ValueError(
54
+ f"Request to Slack returned an error {response.status_code}, the response is: {response.text}"
55
+ )
56
  print(f"Message sent to Slack: {response.status_code}")
57
 
58
  # 發送 2FA 驗證碼到 Slack
59
  def send_2fa_code(name, service_type):
60
+ secret = os.getenv("gmail_2fa")
 
 
61
  if not secret:
62
  return f"{service_type} 的密鑰沒有正確設置為環境變數。"
 
 
63
  code = generate_otp(secret)
 
 
64
  message = f"{name} 要登入 {service_type} 帳號,驗證碼為 {code}"
 
 
65
  send_message_to_slack(message)
 
 
66
  return "驗證碼已發送至指定的 Slack 頻道。"
67
 
68
+ # 初始化邏輯
69
+ def initialize():
70
+ if not os.getenv("gmail_2fa"):
71
+ return "初始化失敗:未設置 Gmail 2FA 的密鑰環境變數 'gmail_2fa'"
72
+ if not os.getenv("SLACK_WEBHOOK_URL"):
73
+ return "初始化失敗:未設置 Slack Webhook URL 環境變數 'SLACK_WEBHOOK_URL'"
74
+ return "應用初始化成功,系統已準備就緒!"
75
 
76
+ # Gradio 前端邏輯
77
  def two_fa_interface(name, service_type):
78
  return send_2fa_code(name, service_type)
79
 
80
  # Gradio 介面
81
+ service_options = ["hi@gaiconf.com"]
82
+
83
+ with gr.Blocks() as demo:
84
+ # 初始化狀態
85
+ status_message = gr.Textbox(
86
+ label="應用狀態", interactive=False, value="初始化中..."
87
+ )
88
+ demo.load(initialize, outputs=status_message)
89
+
90
+ # 驗證碼生成介面
91
+ gr.Markdown("### GAI 總籌兩步驗證")
92
+ name = gr.Textbox(label="請輸入您的暱稱", placeholder="您的暱稱")
93
+ service = gr.Dropdown(label="選擇服務", choices=service_options)
94
+ result = gr.Textbox(label="結果", interactive=False)
95
+ submit_button = gr.Button("送出")
96
+ submit_button.click(two_fa_interface, inputs=[name, service], outputs=result)
97
 
98
  # 啟動應用
99
+ demo.launch(share=True)