只能加密网页且无需服务器的网页加密器

查看 79|回复 10
作者:PythonPan   
网页加密器
为了解决微信排版导致Markdown内容格式错乱的问题,笔者不得不将费心创作的教程公开至个人网站,方便付费用户阅读原汁原味的原版教程(主要是有动图,打印成PDF还是不够完美)。但是,另一个问题随之而来,那就是公开意味着免费,付费用户岂不成了冤大头?
为了维护付费用户的尊严,笔者特地基于Staticrypt(Nodejs)和nodejs_wheel(Python)实现(套壳)了一个网页加密器,可将普通网页变成需要输入密码的网页(无需后端,纯前端),这样就能让付费用户觉得钱没白花(付费才能解锁)。
网页加密器界面采用最简单的tkinter界面(有点丑陋,只有几个对话框),只做了部分参数的交互输入功能(其他参数的没时间弄)。
生成的加密网页体积会膨胀,但是密码存储在内部,无需后端即可使用。虽然密码无法保证百分比安全,但一般的小白还是只能乖乖付费,这就足够了。
加密器还能生成免密分享码,格式为#staticrypt_pwd={分享码},追加到URL之后,刷新访问可以跳过输入密码的界面。
安装使用方法,使用uv初始化项目(uv sync),然后执行运行加密程序.bat(或者在虚拟环境中运行python main.py),所需的Nodejs库会自动安装。
最后感谢以下项目提供的工具、接口:
  • 网页加密的核心库:https://github.com/robinmoisson/staticrypt
  • 通过Python执行Nodejs命令的关键库:https://github.com/robinmoisson/staticrypt

    代码如下:
    [Python] 纯文本查看 复制代码from nodejs_wheel import npx,npm
    from tkinter.filedialog import askopenfilenames
    from tkinter.simpledialog import askstring
    from tkinter.messagebox import askyesno
    import os,sys
    # 预定义的配置变量
    # 输出目录
    dist = 'dist/'
    # 是否显示生成分享码的选择对话框
    share_show = True
    # 是否生成分享码
    share = True
    def main():
        # 配置文件名
        config = dist+'config.json'
        # 选择要加密的网页
        file_names = askopenfilenames(
            title='选择要加密的网页(支持多选)',
            filetypes=[
                ['网页文件', '*.html'],
            ]
        )
        if not file_names:
            sys.exit()
        config = dist+os.path.basename(file_names[0])+'.json'
        # 检查Nodejs依赖
        if npm(['ls','staticrypt']):
            npm(['install','staticrypt'])
        print('所需的Nodejs依赖已安装。')
        # 界面显示的内容(可修改)
        args = [
            'staticrypt',
            '--remember','1',
            '-d',dist,
            '--template-button','解密',
            '--template-error','密码错误',
            '--template-placeholder','请输入密码',
            '--template-remember','24小时内访问无需密码',
            '--template-title','正在访问加密的网页',
            '--template-toggle-hide','隐藏明文',
            '--template-toggle-show','显示明文',
            '--template-instructions','无分享码或者分享码过期,可输入密码或者使用新的分享码打开。密码、分享码由网页生成者提供。',
            '-c',config,'--short'
        ]
        # 如果输出目录有上次的配置文件,证明没有生成免密分享码,需要询问是否只生成分享码
        generate_share_code = False
        if os.path.exists(config):
            generate_share_code = askyesno(
                title='发现同名配置文件',
                message='上次该文件没有生成免密分享码,是否生成?',
                detail='选择不加密网页,输入原密码可生成免密分享码;\n选择将加密网页,并二次确认是否生成免密分享码',
            )
        # 密码
        password = askstring(
            title = '输入密码',
            prompt = '请输入原密码,用于生成免密分享码:' if generate_share_code else '请指定密码(留空则退出程序):',
            show='*',
            initialvalue=''
        )
        if not password:
            sys.exit()
        if not generate_share_code:
            if password:
                args_ext = ['-p',password]
                args.extend(args_ext)
            args.extend(file_names)
            npx(args=args,return_completed_process=True)
        if share_show:
            share = askyesno(
                title='删除配置文件',
                message='是否生成免密分享码并删除配置文件?',
                detail='选择将生成,并"删除"配置文件;\n选择不生成,同时"保存"配置文件',
            )
        if share:
            args_share = [
                'staticrypt','--share','--share-remember','--remember','1','--short','-c',config
            ]
            args_ext = ['-p',password]
            args_share.extend(args_ext)
            args_share.extend(file_names)
            npx(args=args_share,return_completed_process=True)
            
        print(f'{"免密分享码已生成" if generate_share_code and share else ('未生成免密分享码,仅保存配置文件' if generate_share_code else "网页加密完成,可在输出目录查看加密后的同名文件")}{",请妥善保存上面的免密分享码" if share else "和用于生成免密分享码的配置文件"}。')
        if share:
            os.remove(config)
        os.system('pause')
    if __name__ == '__main__':
        main()
    想要正常使用的话,需要创建dist文件夹,安装nodejs_wheel,或者使用我的项目文件:

    staticrypt_uv_py.zip
    (30.5 KB, 下载次数: 20, 售价: 5 CB吾爱币)
    2025-8-19 17:30 上传
    点击文件名下载附件

    运行截图:



    最后附上生成的加密网页截图:



    网页, 配置文件

  • medicon   

    主要修改内容:
    添加了 generate_password() 函数,用于生成指定长度的字母数字密码
    移除了手动输入密码的对话框
    添加了自动生成4位密码的功能
    添加了显示生成密码的信息框,让用户知道生成的密码
    在程序结束时也显示密码,方便用户记录
    [Python] 纯文本查看 复制代码
    from nodejs_wheel import npx,npm
    from tkinter.filedialog import askopenfilenames
    from tkinter.simpledialog import askstring
    from tkinter.messagebox import askyesno, showinfo
    import os,sys
    import random
    import string
    # 预定义的配置变量
    # 输出目录
    dist = 'dist/'
    # 是否显示生成分享码的选择对话框
    share_show = True
    # 是否生成分享码
    share = True
    def generate_password(length=4):
        """生成指定长度的字母数字密码"""
        characters = string.ascii_letters + string.digits
        return ''.join(random.choice(characters) for _ in range(length))
    def main():
        # 配置文件名
        config = dist+'config.json'
        # 选择要加密的网页
        file_names = askopenfilenames(
            title='选择要加密的网页(支持多选)',
            filetypes=[
                ['网页文件', '*.html'],
            ]
        )
        if not file_names:
            sys.exit()
        config = dist+os.path.basename(file_names[0])+'.json'
        # 检查Nodejs依赖
        if npm(['ls','staticrypt']):
            npm(['install','staticrypt'])
        print('所需的Nodejs依赖已安装。')
        # 界面显示的内容(可修改)
        args = [
            'staticrypt',
            '--remember','1',
            '-d',dist,
            '--template-button','解密',
            '--template-error','密码错误',
            '--template-placeholder','请输入密码',
            '--template-remember','24小时内访问无需密码',
            '--template-title','正在访问加密的网页',
            '--template-toggle-hide','隐藏明文',
            '--template-toggle-show','显示明文',
            '--template-instructions','无分享码或者分享码过期,可输入密码或者使用新的分享码打开。密码、分享码由网页生成者提供。',
            '-c',config,'--short'
        ]
        # 如果输出目录有上次的配置文件,证明没有生成免密分享码,需要询问是否只生成分享码
        generate_share_code = False
        if os.path.exists(config):
            generate_share_code = askyesno(
                title='发现同名配置文件',
                message='上次该文件没有生成免密分享码,是否生成?',
                detail='选择不加密网页,输入原密码可生成免密分享码;\n选择将加密网页,并二次确认是否生成免密分享码',
            )
       
        # 自动生成4位字母数字密码
        password = generate_password(4)
       
        # 显示生成的密码给用户
        showinfo(
            title='生成的密码',
            message=f'已自动生成密码: {password}\n\n请妥善保存此密码,后续需要使用它来访问加密的网页或生成分享码。'
        )
       
        if not generate_share_code:
            args_ext = ['-p',password]
            args.extend(args_ext)
            args.extend(file_names)
            npx(args=args,return_completed_process=True)
        if share_show:
            share = askyesno(
                title='删除配置文件',
                message='是否生成免密分享码并删除配置文件?',
                detail='选择将生成,并"删除"配置文件;\n选择不生成,同时"保存"配置文件',
            )
        if share:
            args_share = [
                'staticrypt','--share','--share-remember','--remember','1','--short','-c',config
            ]
            args_ext = ['-p',password]
            args_share.extend(args_ext)
            args_share.extend(file_names)
            npx(args=args_share,return_completed_process=True)
             
        print(f'{"免密分享码已生成" if generate_share_code and share else ('未生成免密分享码,仅保存配置文件' if generate_share_code else "网页加密完成,可在输出目录查看加密后的同名文件")}{",请妥善保存上面的免密分享码" if share else "和用于生成免密分享码的配置文件"}。')
        print(f'您的访问密码是: {password}')
        if share:
            os.remove(config)
        os.system('pause')
    if __name__ == '__main__':
        main()
    绵绵细雨   


    PythonPan 发表于 2025-8-24 19:09
    pip安装uv,然后uv run python main.py运行

    pip install uvloop
    Defaulting to user installation because normal site-packages is not writeable
    Collecting uvloop
      Downloading uvloop-0.21.0.tar.gz (2.5 MB)
         ---------------------------------------- 2.5/2.5 MB 9.7 kB/s eta 0:00:00
      Installing build dependencies ... done
      Getting requirements to build wheel ... error
      error: subprocess-exited-with-error
      × Getting requirements to build wheel did not run successfully.
      │ exit code: 1
      ╰─> [18 lines of output]
          Traceback (most recent call last):
            File "C:\Users\Administrator\AppData\Roaming\Python\Python311\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 389, in
              main()
            File "C:\Users\Administrator\AppData\Roaming\Python\Python311\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 373, in main
              json_out["return_val"] = hook(**hook_input["kwargs"])
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            File "C:\Users\Administrator\AppData\Roaming\Python\Python311\site-packages\pip\_vendor\pyproject_hooks\_in_process\_in_process.py", line 143, in get_requires_for_build_wheel
              return hook(config_settings)
                     ^^^^^^^^^^^^^^^^^^^^^
            File "C:\Users\Administrator\AppData\Local\Temp\pip-build-env-5dz59xri\overlay\Lib\site-packages\setuptools\build_meta.py", line 331, in get_requires_for_build_wheel
              return self._get_build_requires(config_settings, requirements=[])
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            File "C:\Users\Administrator\AppData\Local\Temp\pip-build-env-5dz59xri\overlay\Lib\site-packages\setuptools\build_meta.py", line 301, in _get_build_requires
              self.run_setup()
            File "C:\Users\Administrator\AppData\Local\Temp\pip-build-env-5dz59xri\overlay\Lib\site-packages\setuptools\build_meta.py", line 317, in run_setup
              exec(code, locals())
            File "", line 8, in
          RuntimeError: uvloop does not support Windows at the moment
          [end of output]
      note: This error originates from a subprocess, and is likely not a problem with pip.
    [notice] A new release of pip is available: 25.0.1 -> 25.2
    [notice] To update, run: python.exe -m pip install --upgrade pip
    error: subprocess-exited-with-error
    × Getting requirements to build wheel did not run successfully.
    │ exit code: 1
    ╰─> See above for output.
    note: This error originates from a subprocess, and is likely not a problem with pip.
    这个怎么解决
    PythonPan
    OP
      

    一天之内纯手写,思路很乱,也没用AI,所以略显简陋。如果需要增加什么功能或者修改什么,可以自己对着源码修改,我这个是纯自己使用,没有后续的维护计划,权当抛砖引玉。
    baili0811   

    有用,收藏了
    cdchj   

    感谢分享。
    skzhaixing   

    这个可以啊  不错的功能
    PythonPan
    OP
      


    medicon 发表于 2025-8-19 21:39
    主要修改内容:
    添加了 generate_password() 函数,用于生成指定长度的字母数字密码
    移除了手动输入密码 ...

    其实这个密码支持中文、甚至Unicode,只是密码输入框没法直接输入,但可以粘贴。
    wjlqz   

    最近写一些网页小工具,这下可以对代码加密了,太感谢了!
    caoxino   

    亲爱的楼主,能否把那些安装的库打包一下,写一下怎么安装怎么用,谢谢谢谢
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部