16、python项目使用license
1、将MAC和使用期限加密生成license
- 代码示例:
create_license_file.py
from binascii import b2a_hex
from Crypto.Cipher import AES
aesKey = b'2021052020210520' # 加密与解密所使用的密钥,长度必须是16的倍数
aesIv = b'2021052020210520' # initial Vector,长度要与aesKey一致
aesMode = AES.MODE_CBC # 使用CBC模式
def encrypt(content):
""" 将MAC地址和Date进行加密 """
# 读取加密内容,并处理成16位的倍数
while len(content) % 16:
content += ' '
content = content.encode('utf-8')
# 对物理地址和license期限进行加密
aes = AES.new(aesKey, aesMode, aesIv)
encrypted_content = aes.encrypt(content)
return (b2a_hex(encrypted_content))
def gen_license_file(mac, license_time_limit):
""" 生成license文件 """
license_file = './License.dat'
with open(license_file, 'w') as LF:
LF.write('MAC : ' + mac + '\n')
LF.write('Date : ' + license_time_limit + '\n')
sign = encrypt(mac + '#' + license_time_limit)
LF.write('Sign : ' + str(sign.decode('utf-8')) + '\n')
if __name__ == '__main__':
# MAC地址
mac = '3c:ec:ef:3a:a8:67'
# license使用期限
license_time_limit = '20220522'
# 生成license文件
gen_license_file(mac, license_time_limit)
2、校验license文件
import re
import sys
import uuid
import datetime
from binascii import a2b_hex
from Crypto.Cipher import AES
aesKey = b'2021052020210520' # 加密与解密所使用的密钥,长度必须是16的倍数
aesIv = b'2021052020210520' # initial Vector,长度要与aesKey一致
aesMode = AES.MODE_CBC # 使用CBC模式
class LicenseCheck():
def start_check(self):
license_dic = self.parse_license_file()
sign = self.decrypt(license_dic['Sign'])
sign_list = sign.split('#')
mac = sign_list[0].strip()
date = sign_list[1].strip()
# 校验license文件MAC地址和Date是否被手动更改
if (mac != license_dic['MAC']) or (date != license_dic['Date']):
print('*Error*: License file is modified!')
sys.exit(1)
if len(sign_list) == 2:
mac = self.get_mac() # 获取服务器MAC地址
current_date = datetime.datetime.now().strftime('%Y%m%d') # 获取当前时间
# 校验物理地址是否正确
print("permission_mac:", sign_list[0])
print("current_mac:", mac)
if sign_list[0] != mac:
print('*Error*: Invalid host!')
sys.exit(1)
# 检验license文件是否过期
print("permission_date:", sign_list[1])
print("current_date:", current_date)
if sign_list[1] <= current_date:
print('*Error*: License is expired!')
sys.exit(1)
else:
print('*Error*: Wrong Sign setting on license file.')
sys.exit(1)
def parse_license_file(self):
""" 解析license文件 """
license_dic = {}
license_file = './License.dat'
with open(license_file, 'r') as LF:
for line in LF.readlines():
if re.match('^\s*(\S+)\s*:\s*(\S+)\s*$', line):
my_match = re.match('^\s*(\S+)\s*:\s*(\S+)\s*$', line)
license_dic[my_match.group(1)] = my_match.group(2)
return (license_dic)
def decrypt(self, content):
""" 解密license文件 """
aes = AES.new(aesKey, aesMode, aesIv)
decrypted_content = aes.decrypt(a2b_hex(content.encode('utf-8')))
return (decrypted_content.decode('utf-8'))
def get_mac(self):
""" 获取服务器MAC地址 """
mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
return ":".join([mac[e:e + 2] for e in range(0, 11, 2)])
def function():
""" 测试license是否校验通过 """
print('license is ok!')
if __name__ == '__main__':
license_check_obj = LicenseCheck()
license_check_obj.start_check()
function()
3、Django项目结合中间件设置license
import re
import uuid
import datetime
from binascii import a2b_hex
from Crypto.Cipher import AES
from django.http import JsonResponse
from utils.common_utils import restore_initial
from django.utils.deprecation import MiddlewareMixin
aesKey = b'2021052020210520' # 加密与解密所使用的密钥,长度必须是16的倍数
aesIv = b'2021052020210520' # initial Vector,长度要与aesKey一致
aesMode = AES.MODE_CBC # 使用CBC模式
class LicenseCheck():
def start_check(self):
""" 开始检验license """
license_dic = self.parse_license_file()
sign = self.decrypt(license_dic['Sign'])
sign_list = sign.split('#')
mac = sign_list[0].strip()
date = sign_list[1].strip()
# 校验license文件MAC地址和Date是否被手动更改
if (mac != license_dic['MAC']) or (date != license_dic['Date']):
print('*License Error*: License file is modified!')
return {'code': '0', 'msg': '*License Error*: License file is modified!'}
if len(sign_list) == 2:
mac = self.get_mac() # 获取服务器MAC地址
current_date = datetime.datetime.now().strftime('%Y%m%d') # 获取当前时间
# 校验物理地址是否正确
print("permission_mac:", sign_list[0])
print("current_mac:", mac)
if sign_list[0] != mac:
print('*License Error*: Invalid host!')
return {'code': '0', 'msg': '*License Error*: Invalid host!'}
# 检验license文件是否过期
print("permission_date:", sign_list[1])
print("current_date:", current_date)
if sign_list[1] <= current_date:
print('*License Error*: License is expired!')
return {'code': '0', 'msg': '*License Error*: License is expired!'}
else:
print('*License Error*: Wrong Sign setting on license file.')
return {'code': '0', 'msg': '*License Error*: Wrong Sign setting on license file.'}
def parse_license_file(self):
""" 解析license文件 """
license_dic = {}
license_file = 'License.dat'
try:
with open(license_file, 'r') as LF:
for line in LF.readlines():
if re.match('^\s*(\S+)\s*:\s*(\S+)\s*$', line):
my_match = re.match('^\s*(\S+)\s*:\s*(\S+)\s*$', line)
license_dic[my_match.group(1)] = my_match.group(2)
except Exception as e:
print('*License Error*: License文件不存在')
return {'code': '0', 'msg': '*License Error*: License文件不存在.', 'data': str(e)}
return (license_dic)
def decrypt(self, content):
""" 解密license文件 """
aes = AES.new(aesKey, aesMode, aesIv)
decrypted_content = aes.decrypt(a2b_hex(content.encode('utf-8')))
return (decrypted_content.decode('utf-8'))
def get_mac(self):
""" 获取服务器MAC地址 """
mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
return ":".join([mac[e:e + 2] for e in range(0, 11, 2)])
class LicenseCheckMiddleware(MiddlewareMixin):
""" License校验中间件 """
def process_request(self, request):
license_check_obj = LicenseCheck()
res_data = license_check_obj.start_check()
if res_data and res_data.get('code') == '0':
return JsonResponse({"code": 0, "msg": res_data.get('msg', ''), "data": res_data.get('data', '')})