Django框架15 /Python使用license设置项目有效期

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文件

  • 代码示例:parse_license.py
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

  • 代码示例:my_middleware.py
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', '')})
posted @ 2022-05-22 10:21  LBZHK  阅读(974)  评论(1编辑  收藏  举报