I was able to do this by:
- Creating a directory structure on the file system that is protected by .htaccess.
- Adding a custom field to any page that I want to protect that specifies which directory is used to protect it.
- Modifying the page.php template to restrict access to the page depending on whether the user has access to the directory specified by the custom field.
The specific steps are as follows:
- Create a directory "groups" inside the wp-content directory.
Create wp-content/groups/index.php with the following content:
<?php
require( dirname(__FILE__) . '/../../wp-load.php' );
class CASGroupAuth {
static function authenticate(){
$groups = @$_SESSION['cas-groups'];
if ( !$groups ) $groups = array();
$groupdir = basename(dirname($_SERVER['PHP_SELF']));
$groups[$groupdir] = true;
$_SESSION['cas-groups'] = $groups;
if (!@$_GET['redirect_to'] ){
die("You didn't provide a redirect");
}
header('Location: '.$_GET['redirect_to']);
exit;
}
}
CASGroupAuth::authenticate();
- Create a subdirectory "mygroup" inside the "groups" directory.
Create a symbolic link to the groups/index.php within the mygroups directory. I.e.
$ cd mygroup
$ ln -s ../index.php index.php
Add an .htaccess file to your groups/mygroup directory with the appropriate access restrictions. In my case I was using the CAS apache module, so my .htaccess file looked like:
AuthType CAS
require sfu-user shannah !my-maillist
Modify the the page.php template in my theme (i.e. inside wp-content/themes/mytheme/) to be:
<?php if (have_posts()) : the_post();
$group = get_post_meta(get_the_ID(), 'cas-group', true);
if ( trim($group) ){
$group = trim($group);
$existingGroups = @$_SESSION['cas-groups'];
if ( !$existingGroups or !@$existingGroups[$group] ){
nocache_headers();
header('HTTP1.1 302 Moved Temporarily');
header('Location: ' . get_settings('siteurl') . '/wp-content/groups/'.basename($group).'/index.php?redirect_to='.urlencode($_SERVER['REQUEST_URI']));
header('Status: 302 Moved Temporarily');
exit;
}
}
?>
<?php get_header(); ?>
<div id="content" class="narrowcolumn">
<div id="PageTitle"><!-- TemplateBeginEditable name="PageTitle" --><?php the_title(); ?><!-- TemplateEndEditable --></div>
<div class="post" id="post-<?php the_ID(); ?>">
<div class="entry">
<?php the_content('<p class="serif">Read the rest of this page »</p>'); ?>
</div>
</div>
<?php edit_post_link('Edit this entry.', '<p>', '</p>'); ?>
</div>
<?php get_footer(); ?>
<?php endif; ?>
The important part of this is the section at the top, as the code the checks the cas-groups custom field and redirects the user, needs to run before any output has been sent to the browser. To do this, I rearranged where the position of the if (has_posts()) statement to wrap the entire page rather than just the content - as it is in the default template.
At this point, if you add a custom field to any page of the wordpress site with name "cas-group" and value "mygroup", then access to that page will be properly limited to users who have access to your groups/mygroup directory based on the rules in its .htaccess file.
If you want to have different groups, you can just make a copy of the mygroup directory and modify the .htaccess file restrictions inside it.