求优化方案:无框架Web技术实现Windows文件夹加密工具
Hey there! Your current folder locker is a clever start, but as you noticed, renaming to a Control Panel GUID and relying on plaintext status files isn’t secure or standard. Let’s rebuild it to be more robust using just HTML/CSS/JS (plus PowerShell for safer system operations—way more powerful than Batch and better integrated with Windows security features).
Key Issues with Your Current Setup
First, let’s call out the main gaps we’ll fix:
- Weak Obfuscation: Renaming to
Control Panel.{GUID}is trivial to bypass—anyone can show hidden files/folders or directly navigate to the path in File Explorer. - Insecure Password Handling: Validating passwords client-side in JS means your password is exposed in plaintext in your code.
- Fragile State Tracking: A plain
status.txtfile can be deleted or modified easily, breaking your lock/unlock logic.
Step-by-Step Improved Implementation
1. Switch to HTA (HTML Application)
HTA lets you run HTML/CSS/JS as a desktop app with full access to Windows system features—perfect for your use case, no external frameworks needed. Save your main file with a .hta extension instead of .html.
2. Secure Folder Protection with PowerShell
Replace your Batch scripts with PowerShell commands that use proper Windows security features:
- Use NTFS Permissions to restrict folder access (not just hide it)
- Add optional EFS encryption for an extra layer of security
Here’s the lock script (Lock-Folder.ps1):
$folderPath = "MyFolder" $lockerPath = ".\Locker" # Create hidden, system-protected locker directory if (-not (Test-Path $lockerPath)) { New-Item -ItemType Directory -Path $lockerPath | Out-Null attrib +h +s $lockerPath } # Move target folder into locker and restrict permissions Move-Item -Path $folderPath -Destination $lockerPath -Force $acl = Get-Acl "$lockerPath\MyFolder" $acl.SetAccessRuleProtection($true, $false) # Remove all inherited permissions foreach ($rule in $acl.Access) { $acl.RemoveAccessRule($rule) | Out-Null } # Grant full access only to the current user $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule( $currentUser, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow" ) $acl.AddAccessRule($accessRule) Set-Acl "$lockerPath\MyFolder" $acl # Store encrypted lock state (prevents tampering) $stateHash = (Get-Date).ToString() + $folderPath | Get-FileHash -Algorithm SHA256 $stateHash.Hash | Out-File ".\lock-state.dat" -Encoding UTF8
And the unlock script (Unlock-Folder.ps1):
$lockerPath = ".\Locker" $targetPath = ".\MyFolder" # Restore permissions and move folder back $acl = Get-Acl "$lockerPath\MyFolder" $acl.SetAccessRuleProtection($false, $true) Set-Acl "$lockerPath\MyFolder" $acl Move-Item -Path "$lockerPath\MyFolder" -Destination $targetPath -Force # Remove lock state file Remove-Item ".\lock-state.dat" -Force # Open the unlocked folder Start-Process $targetPath
3. Secure Password Handling
Never store passwords in plaintext. Instead, store a SHA-256 hash of your password in a hidden file. When the user enters a password, hash it client-side and compare it to the stored hash.
First, generate your password hash once (run this in PowerShell):
"your-secure-password-here" | Get-FileHash -Algorithm SHA256 | Select-Object -ExpandProperty Hash | Out-File ".\password-hash.dat" -Encoding UTF8 attrib +h ".\password-hash.dat"
Then validate passwords in JS:
async function validatePassword(inputPassword) { const fso = new ActiveXObject("Scripting.FileSystemObject"); if (!fso.FileExists("password-hash.dat")) { alert("Password configuration missing!"); return false; } // Read stored hash const hashFile = fso.OpenTextFile("password-hash.dat", 1); const storedHash = hashFile.ReadLine().trim(); hashFile.Close(); // Hash input password (using CryptoJS for simplicity; use a pure JS SHA-256 if you skip external libs) const inputHash = CryptoJS.SHA256(inputPassword).toString().toUpperCase(); return inputHash === storedHash; }
Note: If you don’t want to use CryptoJS, you can find lightweight pure-JS SHA-256 implementations online—no frameworks required.
4. Robust State Tracking
Replace status.txt with the encrypted lock-state.dat file created in the PowerShell script. Check lock status like this:
function isFolderLocked() { const fso = new ActiveXObject("Scripting.FileSystemObject"); return fso.FileExists("lock-state.dat"); }
5. Full HTA Example
Here’s a complete HTA file tying everything together:
<!DOCTYPE html> <html> <head> <title>Secure Folder Locker</title> <hta:application id="FolderLocker" applicationname="FolderLocker" border="thin" caption="yes" showintaskbar="yes" singleinstance="yes" windowstate="normal" > <style> body { font-family: Arial; padding: 2rem; max-width: 400px; margin: 0 auto; } .button { padding: 0.8rem 1.5rem; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; margin-top: 1rem; } .lock-btn { background: #dc3545; color: white; } .unlock-btn { background: #28a745; color: white; } .error { color: #dc3545; margin-top: 1rem; display: none; } input { padding: 0.7rem; width: 100%; box-sizing: border-box; border-radius: 4px; border: 1px solid #ddd; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script> </head> <body> <h1>Secure Folder Locker</h1> <div id="lockSection" style="display: none;"> <p>Your folder is unlocked. Click below to lock it.</p> <button class="button lock-btn" onclick="lockFolder()">Lock Folder</button> </div> <div id="unlockSection" style="display: none;"> <p>Your folder is locked. Enter your password to unlock.</p> <input type="password" id="passwordInput" placeholder="Enter unlock password" /> <button class="button unlock-btn" onclick="unlockFolder()">Unlock Folder</button> <div class="error" id="errorMsg">Incorrect password!</div> </div> <script> // Set initial state on load window.onload = () => { isFolderLocked() ? document.getElementById('unlockSection').style.display = 'block' : document.getElementById('lockSection').style.display = 'block'; }; function isFolderLocked() { const fso = new ActiveXObject("Scripting.FileSystemObject"); return fso.FileExists("lock-state.dat"); } function runPowerScript(scriptPath) { const shell = new ActiveXObject("WScript.Shell"); // Run PowerShell silently shell.Run(`powershell -ExecutionPolicy Bypass -File "${scriptPath}"`, 0, true); } async function lockFolder() { runPowerScript("Lock-Folder.ps1"); document.getElementById('lockSection').style.display = 'none'; document.getElementById('unlockSection').style.display = 'block'; } async function unlockFolder() { const password = document.getElementById('passwordInput').value; const isValid = await validatePassword(password); if (isValid) { runPowerScript("Unlock-Folder.ps1"); document.getElementById('unlockSection').style.display = 'none'; document.getElementById('lockSection').style.display = 'block'; document.getElementById('errorMsg').style.display = 'none'; document.getElementById('passwordInput').value = ''; } else { document.getElementById('errorMsg').style.display = 'block'; } } async function validatePassword(inputPassword) { const fso = new ActiveXObject("Scripting.FileSystemObject"); if (!fso.FileExists("password-hash.dat")) { alert("Password configuration file not found!"); return false; } const hashFile = fso.OpenTextFile("password-hash.dat", 1); const storedHash = hashFile.ReadLine().trim(); hashFile.Close(); const inputHash = CryptoJS.SHA256(inputPassword).toString().toUpperCase(); return inputHash === storedHash; } </script> </body> </html>
Additional Tips
- Hide Backend Files: Set
attrib +h +son your PowerShell scripts, password hash, and lock state file to make them harder to find. - Add a Custom Icon: Place a
lock.icofile in the same directory and addicon="lock.ico"to thehta:applicationtag for a polished look. - Admin Privileges: If locking folders outside your user directory, add a PowerShell check to prompt for admin rights (use
Start-Process powershell -Verb RunAs).
内容的提问来源于stack exchange,提问作者Muhammed Asif

