We've done this. I think that the best way would be to implement the
XWikiAuthService, XWikiRightService, and XWikiGroupService interfaces
(in the com.xpn.xwiki.user.api package) using a JAAS structure.
However, time constraints (plus the already robust XWiki.XWikiRights and
XWiki.XWikiGroups objects built into the database) led me to provide a
solution that subclassed com.xpn.xwiki.user.impl.XWikiAuthServiceImpl,
overriding only the checkPassword method (and adding a default
constructor that did some initialization of a client to the external
password lookup service).
Something like:
package com.timcoop.xwiki.user.impl;
import com.xpn.xwiki.user.impl.xwiki.XWikiAuthServiceImpl;
public class TimsCustomDatabaseAuthServiceImpl extends
XWikiAuthServiceImpl{
/* do be sure to throw in the Log initialization,
** which you can mimic from XWikiAuthServiceImpl
*/
public TimsCustomDatabaseAuthServiceImpl() throws XWikiException {
super();
/*
** set up the database connection or whatever
*/
}
protected boolean checkPassword(String username, String password,
XWikiContext context) throws XWikiException {
String uname =
username.substring(username.lastIndexOf('.') + 1);
XWikiRequest request = context.getRequest();
HttpSession session = request.getSession(false);
Principal principal = (Principal)
session.getAttribute("org.securityfilter.filter.SecurityRequestWrapper.P
RINCIPAL");
String principalName = null;
if(principal != null)
principalName = principal.getName();
/* did all the above so I could do this;
don't want to call the database unnecessarily
*/
if(principalName != null &&
principalName.equals(username))
return true;
return
password.equals(getUserPasswordFromTimsDatabase(uname));
}
}
With Eclipse, it's a snap, of course.
Once you've done that, add a line to your xwiki.cfg file:
xwiki.authentication.authclass=com.timcoop.xwiki.user.impl.TimsCustomDat
abaseAuthServiceImpl
and, of course, compile and put your code somewhere that the server can
deploy it...
If the database is not needed for anything more than verifying the
user's password, this should work for you just fine. If various user
attributes need to be gained from the database, you may need to do more,
but unless they control or otherwise affect rights within the wiki, you
will probably not have to implement the other two interfaces.
Also, the code that I included in the checkPassword method is crucial,
because the method is called every time any XWiki object or document
checks access rights, which is just about every time it tries to do
anything. This can amount to hundreds, or thousands(!) of times per
HTTP request (for example, the Main.AllDocs and search pages check view
access to every document that they may list, and many other operations
called by render operations do this also). If your database retrieval
happens to depend on some XWiki rights determination, of course, you're
in infinite-recursion land, so as the doctor says: don't do that.
One implication of this is that the password validation survives as long
as the session does, so that if the user changes the password from
another session, this one won't suddenly stop working. Since this is
pretty much the way we expect sessions to work, that's probably not a
problem. If you need it to behave differently, well, do that.
A last thought is that you can probably dispense with the added default
constructor, if you simply implement the user/password association in an
object that you persist with Hibernate, and all that database
initialization goes into the Hibernate configuration. I know very
little (effectively nothing) about that, however; others will have to
help you with that.
Oh yes, there is also the fact that you may actually be able to forget
everything else I've said above if it turns out that you can configure
Hibernate's database mapping of the XWiki.XWikiUsers object in the
user's profile page - or even just the password field - to point to your
custom database...
The user page will also need to be modified if you also want to handle
all the identity lifecycle activities (creation, deletion, password
changes) through the existing database's interfaces. In this case, the
user registration page will have to be modified or disabled.
Well, there's potentially a lot more to it, but I hope this is a useful
start.
brain[sic]
-----Original Message-----
From: groups(a)timkoop.com [mailto:groups@timkoop.com]
Sent: Thursday, November 02, 2006 11:45 AM
To: xwiki-users(a)objectweb.org
Subject: [xwiki-users] User authentication from an existing database
Hi everyone.
I'm looking to use XWiki for our corporate intranet. I would
like to authenticate users from our existing database, like
it says on this page:
http://www.xwiki.org/xwiki/bin/view/AdminGuide/Pluggable+Authe ntication
It says "Users can be authenticated against custom tables."
Can somebody tell me how to do this? Or do I need to write some custom
code?
Thanks.
Sorry if the answer is documented somewhere; I haven't been able to find
it.
--
Tim K