如何对Plugin Builder开发的Python版QGIS插件做代码混淆与授权保护?
Viable Tools & Workflows
1. PyArmor (Fixed for QGIS Compatibility)
PyArmor can work with QGIS if you avoid obfuscating plugin entry points and adjust configuration:
Step-by-Step Setup
- Isolate Core Logic: Move all critical, proprietary code into a separate submodule (e.g.,
./core/), leaving plugin entry files (__init__.py,plugin.py) unobfuscated. These entry points handle QGIS API interactions and license checks. - Obfuscate Core Modules:
Use PyArmor in a virtual environment matching your QGIS Python version. Run:
Thepyarmor obfuscate --recursive --exclude="__init__.py" ./core/--exactflag preserves the original module structure to prevent import issues:pyarmor obfuscate --exact ./core/core_functions.py - Resolve
__pyarmor__NameError:- Ensure obfuscated modules are placed in the correct plugin directory. Add the obfuscated path to the Python sys.path in your entry point:
import sys sys.path.append("./core") # Path to obfuscated modules - Do not obfuscate modules that directly call QGIS API functions (e.g., those importing
qgis.coreorqgis.gui), as this breaks QGIS's module loading.
- Ensure obfuscated modules are placed in the correct plugin directory. Add the obfuscated path to the Python sys.path in your entry point:
- Add License Enforcement:
Generate a machine-bound license with an expiry date:
Verify the license in your unobfuscated entry point:pyarmor licenses --bind-disk "C:" --expired 2025-12-31 my_licensefrom pyarmor_runtime_xxxx import pyarmor # Replace xxxx with your PyArmor version if not pyarmor.verify_license(): raise RuntimeError("Invalid or expired license. Plugin cannot start.")
2. Nuitka (Compile to Binary)
Nuitka compiles Python code to C, producing standalone binaries that are harder to reverse-engineer:
Step-by-Step Setup
- Compile Core Modules:
Install Nuitka and compile your core logic into a shared library:nuitka --module ./core/core_functions.py --output-dir=compiled - Integrate with Plugin:
Replace the original.pycore files with the compiled.pyd(Windows) or.so(Linux/macOS) file. Ensure the binary matches the target OS and QGIS Python version. - License Locking:
Implement a local license check tied to the user's machine ID (e.g., disk serial, MAC address). Use symmetric encryption to store the license key:import hashlib import uuid def get_machine_id(): return str(uuid.getnode()) # Get MAC address def validate_license(license_key): salt = "your_unique_salt" expected_key = hashlib.sha256((get_machine_id() + salt).encode()).hexdigest() return license_key == expected_key
Alternative Authorization Mechanisms
- Machine-Bound Local Licenses: Generate license keys tied to hardware identifiers, stored locally in an encrypted file. The plugin checks this file on startup.
- Token-Based Online Auth: Implement a minimal backend API that validates license keys. The plugin fetches a short-lived token on startup and caches it, only revalidating when the token expires.
- Feature Gating: Split plugin functionality into modules. Use license checks to unlock specific features (e.g., advanced analysis tools) based on the user's license tier.
内容的提问来源于stack exchange,提问作者unbutu
相关产品推荐
相关产品推荐

