...
Tested in Fedora 10, OpenJDK 1.6.0, Tomcat 5.5.27, OpenCms7.0.5, CAS3.3.1, OpenLDAP 2.4.12.
Login Procedure
Module Parameters
Module parameters for authentication handler:
Code Block |
---|
Attribute: a expression to mapping the username to an LDAP attribute, such as uid=%u@langhua.cn or cn=Shi YusenAuthenticationHandler: cn.langhua.opencms.ldap.cas.CmsCasAuthenticationHandler AutoUserRoleName: not required. If you want the user can login OpenCms workplace by default, this parameter should be RoleWorkplaceUsers. CasUrl: not required, default is uid=u%https://localhost:8443/cas. AuthenTypeCasLoginUri: not required, the authenuri typeto ofCAS LDAP serverlogin, default value is simple/login. AuthenticationHandlerCasValidateUri: not required, the handleruri to authen the user's login, can be cn.langhua.opencms.ldap.cas.CmsCasAuthenticationHandler or cn.langhua.opencms.ldap.openldap.CmsLdapAuthenticationHandler CAS validate, default is /serviceValidate. CasLenientURL: not required, if set, this url will be used to validate CAS ticket, default is the LDAP onenull. AutoUserRoleNameCasLogoutUri: when a new user added according to the login servernot required, default is /logout. |
Module parameters for authorization handler:
Code Block |
---|
AuthenticationHandler: cn.langhua.opencms.ldap.cas.CmsCasAuthorizationHandler GroupSearchDN: required, the defaultgroup roledn typeto ofresolve thisOpenCms userOU. If emptynot set, thewill useruse willBaseDN. be onlyRoleSearchDN: inrequired, the role Userdn groupto withoutresolve anyOpenCms role. If BaseDN:not theset, basewill DNuse ofBaseDN. LDAP server,BaseDN: suchnot as dc=example,dc=com. No default value. CasLoginUri: the uri to CAS login, default is /loginrequired. AutoUserRoleName: not required. If you want the user can login OpenCms workplace by default, this parameter should be RoleWorkplaceUsers. CasUrl: the url to visit CAS servernot required, default is https://localhost:8443/cas. CasValidateUriCasLoginUri: not required, the uri to CAS validatelogin, default is /validatelogin. FilterCasValidateUri: not required, the filteruri to loginCAS LDAP servervalidate, default is (objectclass=*)/serviceValidate. ScopeCasLenientURL: thenot scoperequired, toif search LDAPset, defaultthis isurl subwill whichbe meansused searchto subtreevalidate fromCAS theticket, BaseDN.default URL: the URL of the LDAP server, ldap://localhost:389is null. UseCmsLoginWhenLDAPFailCasLogoutUri: When LDAP connection or login failed, whether using OpenCms login instead. Default value is true. |
You have to config your CAS server to use LDAP as the above parameters configed.
How to validate service ticket
I use CAS 1.0 protocal to validate service ticket in the login procedure.
Code Block |
---|
String ticket = CmsRequestUtil.getNotEmptyParameter(getRequest(), PARAM_TICKET); CmsModule ldapModule = OpenCms.getModuleManager().getModule("cn.langhua.opencms.ldap"); if (ldapModule != null) { String casUrl = ldapModule.getParameter("CasUrl", "https://localhost:8443/cas"); String loginUri = ldapModule.getParameter("CasLoginUri", "/login"); String validateUri = ldapModule.getParameter("CasValidateUri", "/validate"); String serviceUrl = getRequest().getRequestURL().toString(); String url = URLEncoder.encode(serviceUrl, "UTF-8"); if (ticket == null) { not required, default is /logout. |
Add a new validate servlet to CAS
Here I use /authzValidate as the new validate servlet uri for an example.
1. Add /authzValidate in $(cas_server)/WEB-INF/web.xml
Code Block |
---|
<!-- start service validate extensions -->
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/authzValidate</url-pattern>
</servlet-mapping>
<!-- end service validate extensions -->
|
2. Modify $(cas_server)/WEB-INF/cas-servlet.xml
Code Block |
---|
...
<!-- start service validate extensions -->
<prop
key="/authzValidate">
authzValidateController
</prop>
<!-- end service validate extensions -->
...
<!-- start service validate extensions -->
<bean id="authzValidateController" class="org.jasig.cas.web.ServiceValidateController"
p:validationSpecificationClass="org.jasig.cas.validation.Cas20WithoutProxyingValidationSpecification"
p:centralAuthenticationService-ref="centralAuthorizationService"
p:proxyHandler-ref="proxy20Handler"
p:argumentExtractor-ref="casArgumentExtractor" />
<!-- end service validate extensions -->
|
3. Modify $(cas_server)/WEB-INF/spring-configuration/applicationContext.xml
Code Block |
---|
<!-- CentralAuthorizationService, please note, this is authz --> <bean id="centralAuthorizationService" class="cn.langhua.cas.LDAPAuthzCASImpl" p:ticketGrantingTicketExpirationPolicy-ref="grantingTicketExpirationPolicy" p:serviceTicketExpirationPolicy-ref="serviceTicketExpirationPolicy" p:authenticationManager-ref="authenticationManager" p:ticketGrantingTicketUniqueTicketIdGenerator-ref="ticketGrantingTicketUniqueIdGenerator" p:ticketRegistry-ref="ticketRegistry" p:servicesManager-ref="servicesManager" getResponse().sendRedirect(casUrl + loginUri + "?service=" + url); } else { // there's a ticket, we should validate the ticket URL validateURL = new URL(casUrl + validateUri + "?" + PARAM_TICKET + "=" + ticket + "&" + PARAM_SERVICE + "=" + url); URLConnection conn = validateURL.openConnection(); InputStreamReader result = new InputStreamReader(conn.getInputStream(), "UTF-8"); BufferedReader reader = new BufferedReader(result); String oneline = reader.readLine(); if (CmsStringUtil.isNotEmpty(oneline) && oneline.equals("yes")) { // the ticket is true m_username = reader.readLine().trim(); m_password = "cas_login"; m_actionLogin = "true"; reader.close(); result.close(); } else { // the ticket is false, forward the request to cas login page reader.close(); result.close(); getResponse().sendRedirect(casUrl + loginUri + "?service=" + url); } } } |
/system/login/index.html
Please replace the /system/login/index.html with /system/modules/cn.langhua.opencms.ldap/login/index_cas.html, and then you'll use CAS login page to login your OpenCms.
Note: Your CAS server must have SSL configured properly or it will return an error. Also this version only works for 7.0.1 and only supports LDAP connection of no authentication.
Check the OpenCMS forums for details on integrating with 7.0.3
How to get the module and the source code
Download the module: http://sourceforge.net/project/showfiles.php?group_id=163225
The source code: http://opencms-ldap.svn.sourceforge.net/viewvc/opencms-ldap/OpenCms-7.0.1-CAS-3.1-OpenLDAP/;
...
p:persistentIdGenerator-ref="persistentIdGenerator"
p:uniqueTicketIdGeneratorsForService-ref="uniqueIdGeneratorsMap"
p:attributeRepository-ref="attributeRepository" />
|
4.Modify $(cas_server)/WEB-INF/deployerConfigContext.xml
Code Block |
---|
<bean id="attributeRepository"
class="cn.langhua.cas.services.persondir.support.ldap.LdapPersonAttributeDaoExtension">
<property name="baseDN"
value="o=langhua,c=cn" />
<!-- This query is used to find the entry for populating attributes. {0} will be replaced by the new Principal ID extracted from the ldap-->
<property name="query" value="(uid:caseExactmatch:={0})" />
<property name="contextSource" ref="contextSource" />
<property name="groupSearchDN" value="ou=users,ou=opencms,ou=applications,o=langhua,c=cn" />
<property name="roleSearchDN" value="ou=roles,ou=opencms,ou=applications,o=langhua,c=cn" />
<property name="authorType" value="member" />
<property name="ldapAttributesToPortalAttributes">
<map>
<!-- Mapping beetween LDAP entry's attributes (key) and Principal"s (value) -->
<entry key="groups" value="groups" />
<entry key="roles" value="roles" />
<entry key="uid" value="uid" />
<entry value="title" key="title"/>
<entry key="cn" value="Name"/>
<entry key="sn" value="sn"/>
</map>
</property>
</bean>
|
5. Modify $(cas_server)/WEB-INF/view/jsp/protocol/2.0/casServiceValidationSuccess.jsp
Code Block |
---|
<%@ page session="false" pageEncoding="UTF-8"
%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"
%><%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"
%><cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>${fn:escapeXml(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.id)}</cas:user>
<c:if
test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes) > 0}"> <cas:attributes>
<c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}"
varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes)}" step="1">
<cas:attribute>
<cas:name>${fn:escapeXml(attr.key)}</cas:name>
<cas:value>${fn:escapeXml(attr.value)}</cas:value>
</cas:attribute>
</c:forEach> </cas:attributes>
</c:if>
<c:if test="${not empty pgtIou}">
<cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
</c:if>
<c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
<cas:proxies>
<c:forEach var="proxy" items="${assertion.chainedAuthentications}" varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
<cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
</c:forEach>
</cas:proxies>
</c:if>
</cas:authenticationSuccess>
</cas:serviceResponse>
|
6. Sample of /authzValidate response
Code Block |
---|
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>shijh</cas:user>
<cas:attributes>
<cas:attribute>
<cas:name>uid</cas:name>
<cas:value>shijh</cas:value>
</cas:attribute>
<cas:attribute>
<cas:name>Name</cas:name>
<cas:value>石京海</cas:value>
</cas:attribute>
<cas:attribute>
<cas:name>sn</cas:name>
<cas:value>石京海</cas:value>
</cas:attribute>
<cas:attribute>
<cas:name>title</cas:name>
<cas:value>manager</cas:value>
</cas:attribute>
<cas:attribute>
<cas:name>roles</cas:name>
<cas:value>cn=RoleRootAdmins,ou=opencms,ou=roles,ou=applications,o=langhua,c=cn</cas:value>
</cas:attribute>
<cas:attribute>
<cas:name>distinguishedName</cas:name>
<cas:value>uid=shijh,ou=beijing,o=langhua,c=cn</cas:value>
</cas:attribute>
<cas:attribute>
<cas:name>groups</cas:name>
<cas:value>cn=Administrators,ou=opencms,ou=groups,ou=applications,o=langhua,c=cn</cas:value>
</cas:attribute>
</cas:attributes>
</cas:authenticationSuccess>
</cas:serviceResponse>
|
How to get the module and the source code
The source code of cn.langhua.cas is here.
Source code of OpenCms-LDAP module:
SVN:
http://www.langhua.cn/langhua/modules/ldap/
Username:anon
Password:anon
ViewVC:
http://www.langhua.cn/viewvc/svn/modules/ldap/
Shi Yusen/Beijing Langhua Ltd.
http://langhua.org/
http://langhua.biz/
http://www.langhua.cn/