| 开发者 | redwoodcity |
|---|---|
| 更新时间 | 2026年7月30日 01:26 |
| PHP版本: | 7.4 及以上 |
| WordPress版本: | 7.0 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
.htaccess file inside your uploads directory (using WordPress's own marker mechanism, so rules from other plugins are preserved). Requests for existing files are rewritten to WordPress itself, which bootstraps normally; the plugin then verifies the visitor is logged in and streams the file. No WordPress core file is ever loaded directly. Deactivating or uninstalling the plugin removes the rules, and your files are served normally again.
Features
.htaccess file in the uploads directory.htaccess files. The built-in live test will tell you immediately whether your server is compatible.
For developers
The final access decision can be filtered:
add_filter( 'medifence_allow_access', function ( $allowed, $file_path ) { // Example: always allow files inside uploads/public/. if ( false !== strpos( $file_path, '/uploads/public/' ) ) { return true; } return $allowed; }, 10, 2 );
medifence folder to /wp-content/plugins/, or install it from the Plugins screen..htaccess rules are written automatically.No. Existing URLs in posts, themes, and the database keep working exactly as before. Logged-in visitors see no difference at all.
The settings screen runs a live test: it creates a temporary file, requests it over HTTP without any session cookie, deletes it, and reports the status code. If your server configuration prevents the rules from working, you will see it there — not months later.
No. The plugin relies on .htaccess rewrite rules, which nginx does not support. You would need an equivalent rule in your nginx configuration, which is outside what a plugin can safely manage.
The rules are removed from the .htaccess file and all files are served normally again. Uninstalling additionally deletes the plugin's settings.
Medifence detects this and shows a warning on your admin screens. One click on "Regenerate .htaccess rules" restores them. A daily scheduled check also rewrites the rules on its own, so the protection comes back even if nobody logs in; you can turn that off in the settings.
Switch on the email notification in the settings. The daily check then sends one message when it finds that anonymous visitors can reach your files, and one more when the protection works again. It is sent only when the verdict changes, so a problem that persists does not fill your inbox, and a live test that could not reach the site at all is never reported as a failure. Use "Send a test email" first to confirm that this site can send mail at all.
Yes, if the email notification is on. The live test answers "do the rules work", and a widened scope leaves that answer green — the rules work exactly as configured, and it is the configuration that changed. So the daily check also counts how many files a logged-out visitor can open, and writes to you when that number grows. A number that falls is never reported: locking more files down is not news.
The message names a few of the files and links to the Audit tab, which lists all of them with the reason for each. The settings tab records which administrator last changed the protection. The daily count examines the newest 500 attachments; the medifence_exposure_limit filter changes that.
Yes, one file: the .htaccess inside your uploads directory. The plugin uses WordPress's insert_with_markers() function, which only touches its own marked block and preserves everything else. The block is removed on deactivation and uninstall.
No. The live test sends one HTTP request to your own site. Nothing is sent anywhere else.
Nothing about your visitors. The optional access log records the file path, what happened to it, and when — no IP addresses, no user agents, and no user names. It is off unless you switch it on, keeps at most 200 files for 30 days, and can be cleared with one click. The settings history is the one place a person is named, and only an administrator of your own site: when the settings that decide access change, it records which user account made the change. That is the point of it — a protection that was widened should be traceable. It keeps the last 50 changes and can be cleared with one click.
Switch on the access log in the settings, then look at the Access log tab. It counts per file what Medifence did: blocked the request, served the placeholder, sent the visitor to the login screen, accepted a share link — or refused one, because it had expired, been revoked, or been used up, with wrong passwords counted separately. A file that is blocked over and over is usually one your theme or another plugin needs for everyone — exclude its extension or its folder.
The list can be downloaded as CSV from the same tab — one row per file, with one column per event — or produced on the command line with wp medifence log --format=csv.
Protected files are served through PHP, which adds overhead compared to direct file delivery. To keep this small, the plugin sends ETag headers so browsers of logged-in users cache files locally, and repeat requests are answered with an empty 304 response. Files with excluded extensions bypass PHP entirely.
Files that were served before the protection was active — or while their folder or extension was excluded — may still sit in a server-side or CDN cache, and that copy is served without ever reaching WordPress. Medifence sends Cache-Control: private on everything it delivers itself, so protected files are never stored in a shared cache; the stale copy disappears once the cache entry expires, or immediately if you purge the cache. Verify with a fresh query string (for example ?x=1), which bypasses most caches.
No — and the plugin now says so rather than leaving you to find out. When your media URLs point at another host, requests for those files never reach this server: the uploads .htaccess is not on the way, and Medifence is never asked who may open them. Everything else keeps looking healthy, which is what makes this worth naming — the rules are in place, and the live test requests a file from this site and passes.
The status tab and Site Health name the host whenever the media URLs point elsewhere. Protect the files where they are actually served from, or serve the uploads directory from this site again. A CDN that caches your site as a whole is fine, as long as the media URLs still point at your domain; if your setup rewrites the URLs but the files do pass through WordPress after all, correct the verdict with the medifence_external_media filter.
Yes. Put each tier's files in its own folder and give that folder its own capability under "Folders that need more than a login" on the settings tab. A logged-in visitor without that capability is refused exactly as a logged-out one is.
The most specific folder decides, so a rule on members/gold is applied ahead of one on members. Folder rules can only narrow access — they never let in someone who already failed the site-wide capability — and a share link still works for the one file it was issued for. The file inspector names the capability a given file requires, and which roles have it.
Yes. Choose the "Follow the post each file is attached to" scope. A file attached to a published post is served to everyone, exactly as before the plugin was active; a file attached to a private, draft, or password-protected post requires a login. Files that belong to no post remain protected, and generated image sizes follow their original — a thumbnail is never more public than the full image.
Yes. Tick the generated sizes that may be public under "Image sizes anyone may see" on the settings tab. Everything else inside the protected scope, including the original file and the -scaled copy WordPress makes of a large upload, keeps requiring a login.
Which size a file is comes from what WordPress recorded when it generated it, not from the numbers in the file name, so a size that does not crop cannot slip through a coincidental -1024x1024 match. A file whose size WordPress has no record of is treated as protected.
This can only open files the scope would otherwise protect. An excluded extension or folder is decided first — those files are delivered by your web server and are public regardless — and a per-file exception still overrides everything. A published size is still delivered by WordPress, so it is no faster than a protected file.
Yes. Set "When access is denied" to "Send visitors to the login screen, then back to the file". After logging in they land on the file they originally asked for. The redirect applies only when the browser navigates to the file directly — an <img> or a video embedded in a page still receives the status code, so your pages never end up showing a login form where an image should be.
The login screen also names the file they were opening, above the form, so the redirect reads as a closed door rather than as a site that lost their click. Only the name is shown, never the folder it sits in.
Yes. Under "Placeholder image" on the settings tab, either choose an image of your own from the media library, or tick "Use the built-in image when no attachment is chosen" — a grey padlock that ships with the plugin, with no text on it, so it reads the same in every language. Denied image requests then receive that picture instead of a status code, and the layout of the page survives. The original file is never served. This applies to images only; other file types still get the status code. If a placeholder attachment you chose is deleted later, the built-in image stands in for it, provided the tick box is on.
No. Use "Pause the protection" on the Protection status tab: every file is served as if the plugin were inactive, but the .htaccess rules stay in place and the protection resumes automatically after the time you chose — 5 minutes up to 1 hour, so it cannot stay off by accident. While the pause lasts, responses carry an X-Medifence: paused header, a warning shows on every admin screen, and the email notification does not report the pause as a failure. Also available as wp medifence pause and wp medifence resume.
They are protected by the same rules — the scope works on paths, not on the database — but until now nothing reported on them, because the audit walks the media library. "Scan the uploads directory" on the Audit tab walks the directory instead and lists the files no attachment points at which a logged-out visitor can still open: an export another plugin left behind, a leftover from a migration, something copied in over FTP.
Generated image sizes, the scaled copy of a large upload, and edited versions are resolved back to their original, so they are not reported as strays. Also available as wp medifence stray.
Yes. "Download the settings" on the settings tab writes a JSON file, and "Read a settings file" on the other site reads it back. Only the settings travel — share links, the signing key, the access log, and per-file exceptions belong to one site and are never exported.
An imported file is not applied on the spot. It fills in the form as an unsaved change and reports what it would do to that library, so a scope that made sense on staging cannot quietly expose files on the live site. Press save once the effect looks right. On the command line, wp medifence export --file=medifence.json and wp medifence import medifence.json do the same, and --dry-run reports the effect without saving.
Use "Preview the effect" next to the save button. It applies the values currently in the form to your media library without saving them, and reports which files would change side — the ones that would stop being protected first, since that is the direction that matters. Your edits stay in the form, so you can then save them or discard them. Nothing is written until you press save.
Set "When access is denied" to "Send visitors to a page of your own" and pick a published page — a membership page, a contact form, whatever explains how to get access. The file they tried to open is added to the URL as mf_from, and the [medifence_requested_file] shortcode prints its name, so the page can say "You tried to open [medifence_requested_file]" without any PHP. Opened directly, with no file behind it, the shortcode prints nothing — so write the sentence to still read sensibly then.
The same rule as the login redirect applies: it only happens when someone opens the file in their browser. An image or a video embedded in a page still receives the status code, so your pages never show a membership page where a picture should be. If the chosen page is later unpublished or trashed, denied visitors quietly fall back to the status code rather than being sent into a 404.
From the list itself. Tick the ones that should not be open and press "Set the selected files to always protected" — that stores a per-file exception without touching the protection scope, so nothing else moves. The library is scanned again straight afterwards, so whatever is still listed is still reachable. Some files cannot be closed this way, and are reported separately. A per-file exception is decided in PHP, so it only works for files the rules actually route through WordPress. A file your web server delivers itself — because its extension is excluded, its folder is excluded, or the scope is limited to other paths — never reaches the plugin at all, and only a change to the scope closes it.
Because the post links to files the protection keeps closed: you are logged in and see them, a visitor is not and does not. It is the one misconfiguration this plugin can create, and it looks perfectly fine to whoever wrote the post. Publishing a post now checks that post for such files and names them in a notice, with a link back to the post — no scan to remember, and nothing is blocked: the post is saved either way. Since the block editor saves in the background, the notice appears on the next admin screen rather than the instant you press publish. A post whose files are all reachable says nothing at all. To review the whole site instead, use "Scan published content" on the Audit tab. The fix is either to widen the protection for those files (an exception, an excluded folder, or the "follow the parent post" scope) or to use a public copy in the post — the audit names each file so the choice is per file.
Use the file inspector on the Protection status tab, or the Audit tab to see all of them at once — it applies your settings to the whole library and lists every file a logged-out visitor can open, with the reason for each.
For a single file: Paste the file's URL (or enter its attachment ID or path) and it reports whether a logged-out visitor can reach it, naming the setting that decided — an excluded extension, an excluded path, a scope that does not cover it, or the status of the post it is attached to. The same check is available from the command line as wp medifence inspect <file>.
Select the file in the media library and use the bulk action "Medifence: always public" or "Medifence: always protected"; the same choice is on the file's own edit screen. That one file then ignores the protection scope, and generated image sizes follow their original. Every exception is listed on the Audit tab and can be reset there. One limit is worth knowing: "always protected" only works for files that reach Medifence at all. If the file has an excluded extension, or sits in an excluded folder, your web server delivers it directly and no plugin is asked. The file inspector says so when it happens.
Yes. On the settings screen, or from the "Share link" action in the media library, create a share link for that file and choose how long it stays valid. The link is the file's normal URL plus a signature, so it works for that one file only and stops working when it expires. You can also limit a link to a number of downloads — one, for a file that should be fetched exactly once — and add a note recording who it was issued to. Revalidating a cached file and seeking inside a video are not counted, so a one-download link is not spent halfway through a video. Every active link is listed on the settings screen with its expiry, how often it was downloaded, and when it was last used; each one can be revoked on its own. The list can be searched by file name or note and filtered to what expires within a day, what has one download left, or what carries a password, with pages of 50. "Revoke all share links" additionally replaces the signing key, invalidating everything issued so far at once.
Select them in the media library and choose the bulk action "Medifence: create share links". The lifetime, the download limit, and the note are asked once and applied to every link — so a note like the client's name ends up on all of them — and the links are then shown together, with a box holding all of them one per line for copying into a single message. Each link still covers its own file alone, and the download limit applies to each link separately rather than to the set. Up to 25 files per request. Files whose file is missing on disk are named rather than silently dropped. The whole set can be emailed from that result box, as one message listing every link with its file name and expiry — the recipient is one person, so twenty separate mails would be worse than the paste this replaces. If any of the links has been revoked between issuing and sending, nothing is sent at all.
[medifence_requested_file] shortcode prints the same name — so the page can say "You tried to open report.pdf" without writing any PHP.medifence_external_media filter corrects the verdict for a setup where the files do pass through this site after all.wp medifence status --format=json and wp medifence inspect --format=json print the full report as one JSON object, for deployment scripts and CI that so far had to parse the human-readable table.audit and stray already offered machine-readable listings; their output is untouched.[medifence_files path="members/gold"] lists the files of that uploads folder — but only the ones the visitor viewing the page could actually download, decided by the same rules as the delivery itself.medifence field with the verdict, the reason, and a description. It is returned to administrators only; everyone else receives null — which files are reachable is itself information.wp medifence share --password=....-scaled copy of a large upload are never among them.wp medifence audit now covers the whole library by default; pass --limit to stop early.members/gold is applied ahead of one on members.medifence_exposure_limit filter changes that.wp medifence stray, which covers the whole directory and can write the list to CSV.wp medifence history, with --clear.mf_from, so the page can name what was behind the door.wp medifence export and wp medifence import <file>, with --dry-run.paused value of the X-Medifence header and the pause and resume commands, both introduced in 1.18.0.X-Medifence: paused header, and the email notification does not report the pause as a failure.wp medifence pause --minutes=15 and wp medifence resume.wp medifence override <id> --set=public|protected|default.wp medifence log, with --clear.wp medifence audit, which covers the entire library and can write the list to CSV.wp medifence share accepts --uses and --label.wp medifence inspect <file>.wp medifence status, rewrite, remove, verify, and share.