|
Authentication
IntroductionNow you have your own WebDAV server, you'll probably want to add some security. WebDAV authentication is done using HTTP Basic or Digest authentiation (RFC2617). Although it's not very difficult to roll your own, SabreDAV does come with some tools to make it easy to implement. SabreDAV comes with a plugin that handles authentication for you. It ships with 2 backends, one to store usernames in a file and the other to store it in a SQLite or MySQL database. Both use HTTP Digest, if you want to support HTTP Basic, you should create your own Backend class, based on Sabre_DAV_Auth_Backend_Abstract. Using the PDO backendThe PDO backend can either use MySQL or SQLite databases. An example for the table creation can be found in the source in the examples/sql directory. http://code.google.com/p/sabredav/source/browse/#hg/examples/sql After you have created your Sabre_DAV_Server instance, add the plugin using the following code: $pdo = new PDO('sqlite:data/db.sqlite');
// or alternatively:
// $pdo = new PDO('mysql:dbname=sabredav','username','password');
// Throwing exceptions when PDO comes across an error:
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
// Creating the backend
$authBackend = new Sabre_DAV_Auth_Backend_PDO($pdo);
// Creating the plugin. We're assuming that the realm
// name is called 'SabreDAV'.
$authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,'SabreDAV');
// Adding the plugin to the server
$server->addPlugin($authPlugin);The SQL tableThe example scripts for the SQL tables automatically creates a user with the username admin and password admin. Change this! You might be confused by the digesta1 field. This field actually contains the hashed password. The password is stored in the following format: md5('username:realm:password');The username and password speak for themselves, but it's important to keep the realm in mind. This must be the very same realm you specified earlier when creating the Sabre_DAV_Auth_Plugin. If you choose to change the realm in the plugin, none of the existing passwords will work. Using the File backendThe Sabre_DAV_Auth_Backend_File backend uses a simple file to store usernames and passwords. The format of the file is identical to apache's htdigest file. If you have apache installed, there's a good chance you have a utility to create and modify these files. You can verify this by typing htdigest on the command line. If you don't have htdigest installed, the format is rather simple. Every user is on a single line (split by \n). Every line looks like: username:realm:digesta1 The username speaks for itself, the realm must be the exact same as the second argument of the Sabre_DAV_Auth_Plugin constructor, and the digest a1 is, just like with the PDO plugin the following hash: md5('username:realm:password');Creating your own authentication backendThis section has not fully been written yet. You should be able to pull this off though by looking at the correct classes. If you're going to add Digest authenticaton, use Sabre_DAV_Auth_Backend_AbstractDigest as your parent class, and the File and PDO classes as examples. If you're going to implement HTTP Basic, you must use Sabre_DAV_Auth_Backend_AbstractBasic as your parent class and implement the validateUserPass method. More information about the Sabre_HTTP_* classes can also be found in RawAuthentication. That document was the old recommended way to implement authentication. Webserver configurationMost webservers should allow passing through authentication headers out of the box, for a few this needs to be explicitly enabled though. Apache + (Fast)CGIIf you use PHP through CGI or FastCGI and Apache authentication headers are not passed through by default. You can enable this with the following mod_rewrite rule: <IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule> If you already had a mod_rewrite rule to map all urls to a server file, you might need to change this to something like: <IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* /server.php [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule> Note the /server.php. Make sure this reflects the correct location of your server file. IISIIS might not set HTTP_AUTHORIZATION automatically. According to the PHP manual, you can enable it. Quote from the manual: Also note that until PHP 4.3.3, HTTP Authentication did not work using Microsoft's IIS server with the CGI version of PHP due to a limitation of IIS. In order to get it to work in PHP 4.3.3+, you must edit your IIS configuration "Directory Security". Click on "Edit" and only check "Anonymous Access", all other fields should be left unchecked. Problems with Safe ModeIf 'safe mode' is enabled, PHP will automatically append a process id to authentication realms. This is problematic for Digest authentication, as it used the realm to determine the hash. The solution to this is to either turn off Safe Mode, or using Basic authentication instead of Digest. See the PHP manual for more information. Letting the webserver handle authenticationAuthentication can be directly handled by webservers as well. This approach can be useful if you want to use advanced authentication methods provided by Apache modules (for instance LDAP, Kerberos or SASL). The backend to support this is called Sabre_DAV_Auth_Backend_Apache, to use it add the plugin as follows: // Creating the backend $authBackend = new Sabre_DAV_Auth_Backend_Apache(); // Creating the plugin. The realm parameter is ignored by the backend $authPlugin = new Sabre_DAV_Auth_Plugin($authBackend,'SabreDAV'); // Adding the plugin to the server $server->addPlugin($authPlugin); | |
How do I get who is logged-in in my virtual file system? I would like to save this information to database.
Risto, if you wrote your own classes for your VFS, you should simply pass the username as a constructor, or otherwise.
Please ask followup questions on the mailing list
Saul,
HTTP authentication should still work with FastCGI. It has been tested with both Nginx, Lighttpd and Apache + FastCGI. If authentication doesn't work for you, it means you probably have a configuration problem.
If you find out what you need to configure to make it work, and you can tell me exactly what software you're using, I'd be happy to add it to the documentation.
Let me know you're findings, Evert
How can I first authenticate someone, then look up his/hers homedirectory in the database and then set that homedirectory as root? In my opinion this could be difficult because you first have to pass all information (authentication, directory structure, etc) to the server-object and then execute() it. Only at execution of the server authentication is done and then it is too late because the directory structure had to be set up already.
Thanks for the help!
Hi Robin,
This is probably not the proper forum for questions like this. Go the the mailing list (http://groups.google.com/group/sabredav-discuss) for questions like these.
The proper way to go about it (HTTP-wise) is to not alter the directory structure based on the user. Simply disallow where a user is not allowed to go.
If you do want to do this, you might be stuck creating either your own Directory or ObjectTree? class which always returns the proper information, based on a username.
Hi.
I set up everything and all is running fine until I add digest authentication. I left all reals as they are "SabreDAV", ie:
[..] $authPlugin = new Sabre_DAV_Auth_Plugin?($authBackend,'SabreDAV');
// Adding the plugin to the server $server->addPlugin($authPlugin);
but when I try to access the server, the requested realm is always "SabreDAV-10465"
A username and password are being requested by xxxxxxxxxxxxx. The site says: "SabreDAV-10465"
Why is that? I searched various source files and could not find anything. Your help would be highly appreciated.
Cheers, Ingo
Hi Ingo,
I'm not fully sure what does this, but I've heard problems like this before. This is basically your webserver doing this. I would guess you should be able to configure that, but if you can't you're basically unable to use any of the Digest auth plugins.
Let me know what server you're using and perhaps head over the mailing list.
Hi, sabredav works great for me. but is it possible to define shared and private folders? i mean i have users that would like to have a folder for their own files. thanks in advance.
Hi Moribert,
While this is perfectly possible, it is not functionality provided in the core. SabreDAV is primarily a WebDAV library. If you extend Sabre_DAV_FS you could only display (or give access to) certain folders based on your requirements.