如何在Vercel上为静态网站设置密码保护(全站或指定目录)
Hey there! Let's break down how to add password protection to your static Vercel site—since you just need a barrier against crawlers and casual visitors (not top-tier security), we've got straightforward approaches for both your use cases.
We've got two options here, depending on how "secure" you want the barrier to be:
Option 1: Client-Side JavaScript (Super Simple)
This is the easiest fix for pure HTML/CSS sites—add a small script to every page's <head> that checks for a valid password before loading content. Crawlers won't execute the JS, so they'll hit a blank/access denied page, and casual users just need to enter the password once (we'll add an expiry so they don't have to re-enter every time).
Add this code to the very top of your <head> tag in all HTML files:
<script> const CORRECT_PASSWORD = 'your-custom-password'; // Replace with your password const AUTH_TOKEN = 'site_access_granted'; const EXPIRY_MS = 86400000; // 1 day in milliseconds // Check if user is already authenticated const storedToken = localStorage.getItem(AUTH_TOKEN); const storedExpiry = localStorage.getItem(`${AUTH_TOKEN}_expiry`); if (!storedToken || Date.now() > storedExpiry) { const inputPassword = prompt('Please enter the access password:'); if (inputPassword !== CORRECT_PASSWORD) { // Block access if password is wrong document.body.innerHTML = '<h1>Access Denied</h1><p>Invalid password.</p>'; return; } // Store auth token with expiry localStorage.setItem(AUTH_TOKEN, 'true'); localStorage.setItem(`${AUTH_TOKEN}_expiry`, Date.now() + EXPIRY_MS); } </script>
Note: The password is visible in the page source, so this is only for hiding content from non-technical users and crawlers—not for sensitive data.
Option 2: Vercel Edge Middleware (More Secure)
If you want a server-side check that hides the password from client-side code, use Vercel's Edge Middleware. This triggers a browser-native login prompt (HTTP Basic Auth) that crawlers can't bypass easily.
- Create a file named
middleware.jsin your project root:
import { NextResponse } from 'next/server'; export function middleware(request) { // Generate your own Basic Auth string: use `btoa("username:password")` in your browser console const VALID_AUTH = 'Basic dXNlcjp5b3VyLXBhc3N3b3Jk'; // Replace with your base64-encoded credentials const authHeader = request.headers.get('Authorization'); if (authHeader !== VALID_AUTH) { return new NextResponse('Unauthorized', { status: 401, headers: { 'WWW-Authenticate': 'Basic' }, }); } return NextResponse.next(); } // Match all paths on your site export const config = { matcher: '/:path*', };
- Deploy your site to Vercel—they'll automatically detect and run the middleware.
For locking down only a subdirectory (e.g., /secret/), adjust the above methods to target just that path:
Option 1: Client-Side JavaScript (Targeted)
Modify the earlier script to only trigger when the user is in your protected directory:
<script> const CORRECT_PASSWORD = 'your-secret-directory-password'; const AUTH_TOKEN = 'secret_dir_access'; const EXPIRY_MS = 86400000; const PROTECTED_PATH = '/secret/'; // Replace with your directory // Only check auth if user is in the protected path if (window.location.pathname.startsWith(PROTECTED_PATH)) { const storedToken = localStorage.getItem(AUTH_TOKEN); const storedExpiry = localStorage.getItem(`${AUTH_TOKEN}_expiry`); if (!storedToken || Date.now() > storedExpiry) { const inputPassword = prompt('Please enter the access password:'); if (inputPassword !== CORRECT_PASSWORD) { document.body.innerHTML = '<h1>Access Denied</h1><p>Invalid password for this directory.</p>'; return; } localStorage.setItem(AUTH_TOKEN, 'true'); localStorage.setItem(`${AUTH_TOKEN}_expiry`, Date.now() + EXPIRY_MS); } } </script>
Add this to all pages' <head>—it will only prompt for a password when accessing paths starting with /secret/.
Option 2: Vercel Edge Middleware (Targeted)
Update the middleware's matcher to only target your protected directory:
import { NextResponse } from 'next/server'; export function middleware(request) { const VALID_AUTH = 'Basic dXNlcjp5b3VyLXBhc3N3b3Jk'; // Replace with your credentials const authHeader = request.headers.get('Authorization'); if (authHeader !== VALID_AUTH) { return new NextResponse('Unauthorized', { status: 401, headers: { 'WWW-Authenticate': 'Basic' }, }); } return NextResponse.next(); } // Only match paths in your protected directory export const config = { matcher: '/secret/:path*', // Replace with your directory };
Deploy this, and only visitors to /secret/ and its subpages will see the login prompt.
内容的提问来源于stack exchange,提问作者jakey_dev

