为了实现公司网路访问项目登录时免复杂校验的功能,需要获取公司网络的ip地址,但是公司没有购买固定ip,ip地址会动态变化。
方案设计:
1、项目中维护一个ip白名单列表,用于请求校验ip是否在白名单中。
2、通过在公司机房允许python脚本,将获取到的ip地址通过http请求更新到项目中。
python代码如下:
获取当前ip为了防止失败,使用了三个不同的网站进行获取ip,当前一个失败时,会通过下一个网站获取ip,每个网站的返回格式都不一样,需要单独解析;
import time
from datetime import datetime
import requests
import schedule
import hashlib
# 获取公网IP,为了方式地址失效,使用了3个网站获取
def get_public_ip():
ip = get_public_ip_1()
if ip is None:
ip = get_public_ip_2()
if ip is None:
ip = get_public_ip_3()
return ip
# 第一种获取ip的方式
def get_public_ip_1():
url = 'http://ipinfo.io/ip'
try:
response = requests.get(url, timeout=5)
return response.text.strip()
except:
return None
# 第二种获取ip的方式
def get_public_ip_2():
url = 'https://httpbin.org/ip'
try:
response = requests.get(url, timeout=5)
data = response.json()
return data.get('origin')
except:
return None
# 第三种获取ip的方式
def get_public_ip_3():
url = 'https://v4.ident.me/json'
try:
response = requests.get(url, timeout=5)
data = response.json()
return data.get('ip').strip()
except:
return None
def update_ip_record_http_test(ip):
# 测试环境地址
url = 'http://xxxxxx'
input_str = "ipAddr="+ ip
# 步骤1:将字符串编码为字节数据(必须操作)
byte_data = input_str.encode("utf-8")
# 步骤2:计算MD5哈希值
md5_hash = hashlib.md5(byte_data)
# 步骤3:获取十六进制格式结果
signature = md5_hash.hexdigest()
try:
headers = {"Content-Type": "application/json"}
payload = {
"ipAddr": ip,
"signature": signature
}
response = requests.post(url, json=payload, headers=headers)
text = response.text
print(f"[{datetime.now()}] IP {ip}, test 更新结果: {text}")
return None
except:
print(f"[{datetime.now()}] IP {ip}, test 更新异常")
return None
def update_ip_record_http_prod(ip):
# 生产环境地址
url = 'https://xxxxxx'
input_str = "ipAddr="+ ip
# 步骤1:将字符串编码为字节数据(必须操作)
byte_data = input_str.encode("utf-8")
# 步骤2:计算MD5哈希值
md5_hash = hashlib.md5(byte_data)
# 步骤3:获取十六进制格式结果
signature = md5_hash.hexdigest()
try:
headers = {"Content-Type": "application/json"}
payload = {
"ipAddr": ip,
"signature": signature
}
response = requests.post(url, json=payload, headers=headers)
text = response.text
print(f"[{datetime.now()}] IP {ip}, prod 更新结果: {text}")
return None
except:
print(f"[{datetime.now()}] IP {ip}, prod 更新异常")
return None
# 定时任务
def scheduled_job():
ip = get_public_ip()
if ip is None:
print("[警告] 无法获取公网IP")
else:
update_ip_record_http_test(ip)
update_ip_record_http_prod(ip)
if __name__ == "__main__":
# 立即执行一次
scheduled_job()
# 设置定时任务(每5分钟)
schedule.every(5).minutes.do(scheduled_job)
# 常驻运行
try:
while True:
schedule.run_pending()
time.sleep(1)
except KeyboardInterrupt:
print("\n监控已停止")
可优化的点:
1、http中的签名目前是md5简单处理,后续可以改为RSA。
2、当三个网站都获取失败后,可以使用钉钉机器人发送告警信息,方便监控(钉钉群通过使用http接口发送消息-优快云博客)。
2304

被折叠的 条评论
为什么被折叠?



