Using Drupal to build pages with links to images and media is easy enough. And restricting access to the pages is easy enough. But...

What prevents unauthorized access directly to those media files, if a user knows the right URL?

More verbosely: Let's say I'm letting administrators upload files. Then presenting those files in a node which only some roles can access. Now my node links to an image in my uploaded files directory, what prevents an unauthorized user from typing the image URL without ever visiting the node?

I hope I'm making this clear, and I apologize if this is a FAQ, I've been unable to find an anwer.

I'm considering putting all the protected media files in a directory apache does not serve. Then creating a simple drupal module with a restricted menu item. And that menu item's callback uses file_transfer() to send the file. That way, the user can only get to the file if they have access to my menu item. But won't that cause a lot of unnecessary overhead?

Thanks for any help.

-Dave
www.yogadex.org/new

Comments

ymcp’s picture

Have you tried using administer -> settings -> download method = "private"? I have no idea what it does, but the help text looks promising:

"If you want any sort of access control on the downloading of files, this needs to be set to private..."

Dave Cohen’s picture

Yes, I've seen it. And that's helping me get on track. But it doesn't offer everything I need for my current project.

I'm thinking of adding new kind of file upload to flexinode. The existing one simply saves the incoming file to 'files' and flexinode implements flexinode_file_download such that the file can be downloaded by all users (if I understand it correctly).

My new flexinode object would behave differently. When adding the field to a flexinode type, the administrator would

  • Choose a directory where the file would be saved
  • Associate a premission with the file. Only users with that permission would be able to view the file

So as a simple example, let's say I define a node with two files - a preview image, and a video. I could allow users with 'view images' permission to see the preview, and only users with 'download video' permission to actually see the video.

When I get around to implementing something like this, I'll share it with the community.

edg’s picture

This is something that I've been trying to work out for the last couple of hours or so. My image files are large so I want to (1) restrict access to authorised users only, and (2) show anonymous users the low-res version.

I've found the image module relatively easy to set up (I'm pleased with the way it looks and functions) but as I am using friendly URLs (mysite.com/image) it's not that difficult to access these large files and I worry about my bandwidth bill.

On a related subject, still not sure what style sheet is controlling the CSS settings for the image module. There are classes like "count" (for the number of images in a gallery) and "last" (for the date for the last update). I created new styles in the image.css because I couldn't find these styles in that css file, which sorted it out, but surprised that they didn't exist already in the misc/drupal.css or the pushbutton theme (which is the one I'm using).

impulsive’s picture

Any updates about this subject? :-)
I am trying to setup my first site with Drupal after
trying several CMS systems. It is quite good, but
I find it weird that you can restrict access to
all kind of nodes etc. And file downloading can be
made private in the settings screen.
But when you copy the link of the image, there
is no authorization check!

Best regards,

Hiu-Hong

Dave Cohen’s picture

The update is essentially this: there's nothing inherently wrong with drupal regarding this. But beware that the image module, and possibly others, are not safe if you really want to protect all files.

The image module is a great example to follow if you want to allow file uploads with your own nodes. With the exception of this one function:

/**
 * implement hook_file_download
 */
function image_file_download($file) {
  $size = image_get_info(file_create_path($file));
  if ($size) {
    $headers = array('Content-Type: ' . $size['mime_type']);
    return $headers;
  }
}

The problem is this allows anyone to download any image file.

In your secure module, do something more like this:

function example_file_download($file) {
  $result = db_fetch_object(db_query("SELECT f.*, n.type FROM {files} f LEFT JOIN {node} n ON f.nid=n.nid WHERE f.filepath='%s'", $file));
  if ($result->type =='example-node-type' && user_access('download example files')) {
    // only allow download if its our node, and the user has privelege
    $headers = array('Content-Type: ' . $result->filemime);
    return $headers;
  }
  else {
    // otherwise, its some other modules responibility
    return -1;
  }
}

(Warning: not tested code)

The real caveat is this: you can write a well-behaved module that only allows downloads to the right users. But, if the files are images, and the image module is enabled, all users will be able to download them.

samloo’s picture

I'd like to know if there is any code sample that works with "simple access" module's access control? I use SA to control content nodes' access permission and I want to treat the file permission the same as its containing node's permission.

Thanks.

anner’s picture

If I disable the image module, I can still view the images without being logged in. Any ideas why?

pamphile’s picture

i'm also trying to do this for uploaded files

Have you tried node privacy by role on files ?
http://drupal.org/project/node_privacy_byrole

Marcel
Business Letters
YP.BZ - Yellow Page Dot Business

Dave Cohen’s picture

I have not used that module. Are you saying it solves the problem, or does not?

The upload module may have the same problem as the image module. It may allow any user with view uploaded files permission to view all files. If you want more control than that, you'd have to replace it's file download hook with one of your own.

I've often thought of writing a more sophisticated upload module that would allow this sort of control, but I don't know when I'd have time. I know a lot of other Drupallers think about it too.

pamphile’s picture

Try the secure site module...

The problem with the secure site module is that the entire site will be secured, including images and files.

At least it's worth trying.

marcel
http://01webmasters.com

Rosamunda’s picture

What if you want all nodes and files to be public and freely accessible, BUT just some of those to be private?

Heine’s picture

Filemanager + Attachment (both in cvs unfortunately), tie file download to node access permissions so in combination with a node access module such as, nodeprivacy by role, taxonomy access control, tac lite or simple access, you can achieve this.

--
The Manual | Troubleshooting FAQ | Tips for posting | Make Backups! | Consider creating a Test site.