XWiki对于认证用户支持多种不同的身份认证机制
XWiki目前同一时间只允许启用一种认证方法。这可能在将来得到改善。
还要注意的是XWiki需要cookie被启用,来跟踪你的会话。
表单认证是默认的方式。它需要用户和口令。
XWIki支持html基本认证。基本认证是一种用来允许Web浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。你可以通过以下URL scheme得到XWiki服务器的html基本认证:
http://username:password@mywiki.xwiki.com/xwiki/bin/view/Main/WebHome?basicauth=1
请注意,如果你使用HTTP协议会将你的密码以明文通过网络发送,这非常不安全。当使用基本身份认证时,你应该确保你的wiki使用HTTPS
验证委托给Servlet容器。如果认证失败,就退到标准XWiki身份验证。
要配置XWiki使用它,请指定:
xwiki.authentication.authclass=com.xpn.xwiki.user.impl.xwiki.AppServerTrustedAuthServiceImpl
对于用户需要实际创建,而不仅仅是设置为context user ,你必须在xwiki.cfg配置文件中设置(如果该属性不存在,则自己创建):
xwiki.authentication.createuser=empty
请参阅Social Login Application.
如果你要使用LDAP Admin Extension(LDAP后台管理扩展程序,它会让你更容易配置LDAP), 那么你只需要在xwiki.cfg去掉xwiki.authentication.authclass属性注释。使用LDAP扩展程序修改内容无需重启,不像xwiki.cfg,编辑完需要重启服务器。
为了启用LDAP支持,你必须更改WEB-INF/xwiki.cfg的身份认证方法,如下:
#-# LDAP authentication service
#-# Turn LDAP authentication on - otherwise only XWiki authentication
#-# - 0: disable
#-# - 1: enable
#-# The default is 1
你可以在xwiki.cfg文件填写以下属性,设置LDAP配置:
#-# LDAP Server (Active Directory, eDirectory, OpenLDAP, etc.)
xwiki.authentication.ldap.server=127.0.0.1
xwiki.authentication.ldap.port=389
#-# LDAP login, empty = anonymous access, otherwise specify full dn
#-# {0} is replaced with the user name, {1} with the password
xwiki.authentication.ldap.bind_DN=cn={0},department=USER,department=INFORMATIK,department=1230,o=MP
xwiki.authentication.ldap.bind_pass={1}
#-# The Base DN used in LDAP searches
xwiki.authentication.ldap.base_DN=
#-# LDAP query to search the user in the LDAP database (in case a static admin user is provided in
#-# xwiki.authentication.ldap.bind_DN)
#-# {0} is replaced with the user uid field name and {1} with the user name
#-# The default is ({0}={1})
#-# Only members of the following group can authenticate.
#-# The following kind of groups are supported:
#-# * LDAP static groups (users/subgroups are listed statically in the group object)
#-# * Since 3.3M1 LDAP organization units (users/subgroups are sub object of the provided organization unit)
#-# * Since 3.3M1 LDAP filter (users/groups are object found in a search with the provided filter)
#-# Since 1.5RC1, XWikiLDAPAuthServiceImpl
#-# Only users not member of the following group can authenticate.
#-# The following kind of groups are supported:
#-# * LDAP static groups (users/subgroups are listed statically in the group object)
#-# * Since 3.3M1 LDAP organization units (users/subgroups are sub object of the provided organization unit)
#-# * Since 3.3M1 LDAP filter (users/groups are object found in a search with the provided filter)
#-# Specifies the LDAP attribute containing the identifier to be used as the XWiki name
#-# The default is cn
#-# Since 1.5M1, XWikiLDAPAuthServiceImpl
#-# The potential LDAP groups classes. Separated by commas.
#-# Since 1.5M1, XWikiLDAPAuthServiceImpl
#-# The potential names of the LDAP groups fields containings the members. Separated by commas.
#-# retrieve the following fields from LDAP and store them in the XWiki user object (xwiki-attribute=ldap-attribute)
xwiki.authentication.ldap.fields_mapping=last_name=sn,first_name=givenName,email=mail
#-# Since 1.3M2, XWikiLDAPAuthServiceImpl
#-# On every login update the mapped attributes from LDAP to XWiki otherwise this happens only once when the XWiki
#-# account is created.
#-# - 0: only when creating user
#-# - 1: at each authentication
#-# The default is 0
xwiki.authentication.ldap.update_user=1
#-# Since 1.3M2, XWikiLDAPAuthServiceImpl
#-# Maps XWiki groups to LDAP groups, separator is "|".
#-# The following kind of groups are supported:
#-# * LDAP static groups (users/subgroups are listed statically in the group object)
#-# * Since 3.3M1 LDAP organization units (users/subgroups are sub object of the provided organization unit)
#-# * Since 3.3M1 LDAP filter (users/groups are object found in a search with the provided filter),
#-# | character in the filter need to be escaped with backslash ().
#-#
#-# Here is an example:
#-# Since 1.3M2, XWikiLDAPAuthServiceImpl
#-# Time in s after which the list of members in a group is refreshed from LDAP
#-# The default is 21600 (6 hours)
#-# Since 1.3M2, XWikiLDAPAuthServiceImpl
#-# - create : synchronize group membership only when the user is first created
#-# - always: synchronize on every login
#-# The default is always
#-# Since 7.2M3, XWikiLDAPAuthServiceImpl
#-# Indicate groups members should be resolved in case they are subgroups.
#-# Doing so can be very expensive so it should be disabled if you know there is no subgroups
#-# (or if you don't care about them).
#-# If the group is actually a filter it will always be resolved since it does not make sense left alone.
#-# - 0: disable
#-# - 1: enable
#-# The default is 1
#-# Since 1.3M2, XWikiLDAPAuthServiceImpl
#-# If ldap authentication fails for any reason, try XWiki DB authentication with the same credentials
#-# - 0: disable
#-# - 1: enable
#-# The default is 0
xwiki.authentication.ldap.trylocal=1
#-# Since 1.3M2, XWikiLDAPAuthServiceImpl
#-# SSL connection to LDAP server
#-# - 0: normal
#-# - 1: SSL
#-# The default is 0
#-# Since 1.3M2, XWikiLDAPAuthServiceImpl
#-# The keystore file to use in SSL connection
#-# Since 1.5M1, XWikiLDAPAuthServiceImpl
#-# The java secure provider used in SSL connection
#-# The default is com.sun.net.ssl.internal.ssl.Provider
#-# Bypass standard LDAP bind validation by doing a direct password comparison.
#-# If you don't know what you do, don't use that. It's covering very rare and bad use cases.
#-# - 0: disable
#-# - 1: enable
#-# The default is 0
#-# Since 1.5M1, XWikiLDAPAuthServiceImpl
#-# Specifies the LDAP attribute containing the password to be used "when xwiki.authentication.ldap.validate_password"
#-# is set to 1
#-# Since 4.3M1, XWikiLDAPAuthServiceImpl
#-# The maximum number of milliseconds the client waits for any operation under these constraints to complete.
#-# The default is 1000
#-# Since 6.3M1, XWikiLDAPAuthServiceImpl
#-# The maximum number of search results to be returned from a search operation.
#-# The default is 1000
你也可以在XWiki.XWikiPreferences页面选择对象编辑器设置了LDAP配置。只需更换xwiki.authentication.ldap.为ldap_。如:xwiki.authentication.ldap.base_DN改为ldap_base_DN。
出于测试目的,你不妨省略“ldap.fields_mapping”域,来先测试认证,然后再添加它来获得正确映射。
下面是一些LDAP客户端来检查你的配置:
扩展:
基于Java和开源:
仅适用于Windows:
请参阅LDAP configuration uses cases 查看一些详细的案例。
查看日志文档。
具体跟踪LDAP的packages:com.xpn.xwiki.plugin.ldap和com.xpn.xwiki.user.impl.LDAP。
从XWiki 4.2开始,我们在后台管理页面增加Logging UI,它允许在运行中直接从UI页面启动日志,而不需要重新启动wiki。
在XWiki 3.4你需要添加以下内容放在WEB-INF/classes/logback.xml:
<!-- LDAP debugging -->
<logger name="com.xpn.xwiki.plugin.ldap" level="trace"/>
<logger name="com.xpn.xwiki.user.impl.LDAP" level="trace"/>
在3.1之前,要添加以下内容到log4j的配置文件:
log4j.logger.com.xpn.xwiki.plugin.ldap=trace
log4j.logger.com.xpn.xwiki.user.impl.LDAP=trace
允许引入任何现有的认证机制,例如SiteMinder等。要配置自定义认证要做到以下几点:
xwiki.authentication.authclass = com.acme.MyCustomAuthenticationService
你可以在sandbox 或者 extensions找到各种认证程序的例子。
这里有针对Oracle的SSO认证实现的自定义认证类的教程
请注意,你还可以通过实现XWikiRightService接口来实现自己的权限管理服务:
xwiki.authentication.rightsclass = com.acme.MyCustomRightsService
群组(Group)服务通过实现XWikiGroupService:
xwiki.authentication.groupclass = com.acme.MyCustomGroupService
首先,指定要使用的Groovy身份认证:
xwiki.authentication.authclass = com.xpn.xwiki.user.impl.xwiki.GroovyAuthServiceImpl
然后添加其他配置参数来指定认证的wiki页面:
xwiki.authentication.groovy.pagename = MySpace.MyPage
然后把一些Groovy代码放在一个wiki页面,该页面返回XWikiAuthService对象。
你可以设置这些参数:
xwiki.authentication.param_name=param_value
名称 | 可选 | 容许值 | 默认值 | 描述 |
|---|---|---|---|---|
encryptionKey | No(1) | ? | n/a | 设置加密密钥用于创建一个密钥,该密钥被传递给Cipher对象用于cookie值的加密和解密过程 |
validationKey | No(2) | ? | n/a | 设置校验key用于生成散列值;该散列值被存储与cookie和用于验证该cookie有没被篡改。 |
cookiedomains | Yes | String | Server host name | 表示的是cookie所在的域。只有当你想跨域分享Cookie时使用,否则应被注释 |
cookielife | Yes | Number | 14 | cookies失效天数 |
cookiepath | Yes | String | / | 表示哪些路径下的文件有权限读取该cookie;如果在你Web服务器还有其他应用上运行,这应该被设置为/xwiki |
default_page | Yes | String | /bin/view/ Main/WebHome | 如果没有设置xredirect参数,默认重定向的页面 |
encryptionalgorithm | Yes | ? | ? | 设置算法用于加密和解密cookies |
encryptionmode | Yes | ? | ? | 设置加密模式用于加密和解密cookies |
encryptionpadding | Yes | ? | ? | 设置加密填充用于加密和解密cookies |
errorpage | Yes | String | /bin/loginerror/ XWiki/XWikiLogin | 如果有错误的登录时,页面重定向 |
loginpage | Yes | String | /bin/login/ XWiki/XWikiLogin | 当未登录时,页面重定向 |
loginsubmitpage | Yes | String | /loginsubmit/ XWiki/XWikiLogin | 当登录时,接受用户名密码post的url |
logoutpage | Yes | String | /bin/logout/ XWiki/XWikiLogout | 注销后,页面重定向 |
realmname | Yes | String | XWiki | 设置领域名 |
protection | Yes | all, validation, encryption, none | all | “记住我”功能的保护级别 |
unauthorized_code | Yes | Number | 401 | 当登录失败时HTTP返回状态码 |
useip | Yes | true / false | true | 当加密cookie数据时指定使用的IP地址;如果IP地址更变后,需要重新登录 |
此实现SSO目前正在审查: http://jira.xwiki.org/jira/browse/XWIKI-2496。
以下是Apache mod_auth_kerb的一个例子,在Linux服务器通过HTTP Negotiate来轻松实现XWiki用户的认证。这个例子假设你已经有一个工作的Apache2 HTTPD和Apache Tomcat 安装有mod_jk。
首先,你需要在Web服务器创建一个主体和密钥表:
kadmin> addprinc -randkey HTTP/wiki.example.com
kadmin> ktadd -k /etc/apache2/ssl/wiki.keytab HTTP/wiki.example.com
kadmin> quit
确保密钥表有正确的权限和所有权:
chown www-data:www-data /etc/apache2/ssl/wiki.keytab
chmod 400 /etc/apache2/ssl/wiki.keytab
在Linux安装mod_auth_kerb。在Debian或Ubuntu,需要运行:
aptitude install libapache2-mod-auth-kerb
当然,每个Linux发行版的安装过程会有所不同。
如果你的XWiki是安装在apache httpd下,以下内容要添加到虚拟主机配置
<Location /xwiki/>
AuthType Kerberos
AuthName "Kerberos Login"
KrbAuthRealms EXAMPLE.COM
Krb5Keytab "/etc/apache2/ssl/wiki.keytab"
KrbMethodK5Passwd off
KrbMethodNegotiate on
KrbSaveCredentials on
require valid-user
</Location>
确保Apache Tomcat使用的是由Apache HTTPD 进行身份验证,在connector description (Apache Tomcat的server.xml文件里)设置"tomcatAuthentication"属性:
<Connector port="8009" address="127.0.0.1" enableLookups="false" tomcatAuthentication="false" redirectPort="8443" protocol="AJP/1.3" />
把authkerb.jar放在WEB-INF/lib目录下
Xwiki使用这个认证模式通过在#WEB-INF/lib/xwiki.cfg文件修改"xwiki.authentication.authclass"属性。
xwiki.authentication.authclass=com.xpn.xwiki.user.impl.xwiki.AppServerTrustedKerberosAuthServiceImpl
如果你使用Firefox,不要忘了在HTTP Negotiate下about:config的"network.negotiate-auth.trusted-uris"属性设置XWiki URL的白名单。此属性的值包括:https:// 开头的所有安全连接或example.com的所有example.com子域。
当我使用JBoss的SPNEGO(Kerberos集成LDAP),我更改了XWikiLDAPAuthServiceImpl代码,使之能够检测SSO用户。接着我使用的是LDAP同步功能,以确保用户是最新的。该组合导致在xwiki自动登录和在Active Directory服务器控制用户权限。我希望用户能采纳此代码,或者你可以将它用于自己的项目。
LDAP的配置:
xwiki.authentication.authclass=com.wiki.sso.SSOLdapAuthenicationImpl
xwiki.authentication.ldap=1
xwiki.authentication.ldap.server=<ad-server>
xwiki.authentication.ldap.port=389
xwiki.authentication.ldap.base_DN=<OU=Users,...............>
#use a fixed user to attach to the ldap database,
#the password is not provided with the SSOLdapAuthenicationImpl
xwiki.authentication.ldap.bind_DN=<domain>\<user>
xwiki.authentication.ldap.bind_pass=<password>
#Microsoft AD configuration
xwiki.authentication.ldap.UID_attr=sAMAccountName
xwiki.authentication.ldap.fields_mapping=name=sAMAccountName,last_name=sn,first_name=givenName,fullname=displayName,mail=mail,ldap_dn=dn
xwiki.authentication.ldap.group_memberfields=member,uniqueMember
#LDAP group mapping
xwiki.authentication.ldap.group_mapping=XWiki.XWikiAdminGroup=CN=WIKI_Admin,............|\
XWiki.XWikiAllGroup=CN=WIKI\_User,...........java代码:
package com.wiki.sso;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.user.api.XWikiUser;
import com.xpn.xwiki.user.impl.LDAP.XWikiLDAPAuthServiceImpl;
import java.security.Principal;
public class SSOLdapAuthenicationImpl extends XWikiLDAPAuthServiceImpl {
/**
* Logging tool.
*/
private static final Log LOG = LogFactory.getLog(SSOLdapAuthenicationImpl.class);
public XWikiUser checkAuth(XWikiContext context) throws XWikiException {
String user = getRemoteUser(context);
if ((user != null) || !user.equals("")) {
if (LOG.isInfoEnabled())
LOG.info("Launching create user for " + user);
if ( authenticate(user, context) != null ) {
if (LOG.isInfoEnabled())
LOG.info("Create user done for " + user);
user = "XWiki." + user;
context.setUser(user);
System.out.println("User is set to:" + user);
return new XWikiUser(user);
} else {
LOG.error( "User " + user + " can't be authenticated against ldap" );
}
}
return super.checkAuth(context);
}
/**
* We cannot authenticate locally since we need to trust the app server for
* authentication
*
* @param username
* @param password
* @param context
* @return
* @throws XWikiException
*/
public XWikiUser checkAuth(String username, String password,
String rememberme, XWikiContext context) throws XWikiException {
String user = getRemoteUser(context);
if ((user == null) || user.equals("")) {
return super.checkAuth(username, password, rememberme, context);
}
return checkAuth(context);
}
private String getRemoteUser(XWikiContext context) {
String userName = context.getRequest().getHttpServletRequest()
.getRemoteUser();
if (userName != null) {
// only take the front of the username@domain
String[] elements = userName.split("@", 2);
userName = elements[0];
}
return userName;
}
public Principal authenticate(String login, XWikiContext context) throws XWikiException
{
if (LOG.isTraceEnabled()) {
LOG.trace("Starting LDAP authentication");
}
/*
* TODO: Put the next 4 following "if" in common with XWikiAuthService to ensure coherence This method was
* returning null on failure so I preserved that behaviour, while adding the exact error messages to the context
* given as argument. However, the right way to do this would probably be to throw XWikiException-s.
*/
if (login == null) {
// If we can't find the username field then we are probably on the login screen
if (LOG.isDebugEnabled()) {
LOG.debug("The provided user is null."
+ " We don't try to authenticate, it probably means the user is in non logged mode.");
}
return null;
}
// Check for empty usernames
if (login.equals("")) {
context.put("message", "nousername");
if (LOG.isDebugEnabled()) {
LOG.debug("LDAP authentication failed: login empty");
}
return null;
}
// If we have the context then we are using direct mode
// then we should specify the database
// This is needed for virtual mode to work
Principal principal = null;
// Try authentication against ldap
principal = ldapAuthenticate(login, "", context);
if (LOG.isDebugEnabled()) {
if (principal != null) {
LOG.debug("LDAP authentication succeed with principal [" + principal.getName() + "]");
} else {
LOG.debug("LDAP authentication failed for user [" + login + "]");
}
}
return principal;
}
}