processmaker是目前开源的最好的工作流系统,cas是知名的单点登录server。网络上关于这两个系统的集成文章很少,有价值的仅有一篇,http://forum.processmaker.com/viewtopic.php?f=9&t=930,但该文章中介绍的processmaker版本较低(修改的位置不对)和部分功能未实现。本文部分借鉴该文章,以pm2.5.0为例,主要介绍processmaker在与cas集成时要做的工作,所以cas的相关配置请移步http://www.blogjava.net/tufanshu/archive/2011/01/21/343290.html。
require_once ("CAS-1.3.2/CAS.php");
// Uncomment to enable./ debugging
phpCAS::setDebug();
// version, host, port, context, session
phpCAS::client(CAS_VERSION_2_0, "localhost", 8443, 'cas', false); //我的cas server访问地址是:https://localhost:443/cas
phpCAS::setNoCasServerValidation();
phpCAS::forceAuthentication();
// logout if desired
if (isset($_REQUEST['logout'])) {
phpCAS::logout();
}
if ( phpCAS::isAuthenticated() == true )
$casAuth = CASAuthIsTrue;
$_POST['form']['USR_USERNAME'] = phpCAS::getUser();
$_POST['form']['USR_PASSWORD'] = $casAuth;
这样可以使pm原本的登录认证操作转移到cas里进行,在登录成功后统一将password设置为True;document.login.submit();
这样可以试pm原本的登录页面自动提交,也就能自动跳转到cas的登录页面了。//if ( $aFields['USR_PASSWORD'] == md5 ($sPassword ) || 'md5:'.$aFields['USR_PASSWORD'] === $sPassword) {
替换为:if ( $sPassword == CASAuthIsTrue) {
即与步骤3中相对应;require_once ("CAS-1.3.2/CAS.php");
phpCAS::client(CAS_VERSION_2_0, 'localhost', 8443, 'cas', false);
// logout if desired
if (isset($_REQUEST['logout'])) {
phpCAS::logout();
}
这是为了处理用户在退出pm时也能从cas中退出登录。 /**
* Autentificacion derb un usuario a traves de la clase RBAC_user
*
* verifica que un usuario tiene derechos de iniciar una aplicacion
*
* @author Fernando Ontiveros Lira <fernando@colosa.com>
* access public
* Function verifyLogin
*
* @param string $strUser UserId (login) de usuario
* @param string $strPass Password
* @return
* -1: no existe usuario
* -2: password errado
* -3: usuario inactivo
* -4: usuario vencido
* n : uid de usuario
*/
function noSSOVerifyLogin($sUsername, $sPassword )
{
//invalid user
if ( $sUsername == '' ) return -1;
//invalid password
if ( $sPassword == '' ) return -2;
$con = Propel::getConnection(RbacUsersPeer::DATABASE_NAME);
try {
$c = new Criteria( 'rbac' );
$c->add ( RbacUsersPeer::USR_USERNAME, $sUsername );
$rs = RbacUsersPeer::doSelect( $c );
if ( is_array($rs) && isset( $rs[0] ) && is_object($rs[0]) && get_class ( $rs[0] ) == 'RbacUsers' ) {
$aFields = $rs[0]->toArray(BasePeer::TYPE_FIELDNAME);
//verify password with md5, and md5 format
//if ( $aFields['USR_PASSWORD'] == md5 ($sPassword ) ) {
if ( $aFields['USR_PASSWORD'] == md5 ($sPassword ) || 'md5:'.$aFields['USR_PASSWORD'] === $sPassword) {
if ($aFields['USR_DUE_DATE'] < date('Y-m-d') )
return -4;
if ($aFields['USR_STATUS'] != 1 )
return -3;
return $aFields['USR_UID'];
}
else
return -2;
}
else {
return -1;
}
}
catch (Exception $oError) {
throw($oError);
}
return -1;
}
这样就是增加了一个函数来完成使用传统用户名/密码方式来认证的渠道(因为跟cas用的都是同一个数据源,所以这类查询操作不会破坏 SSO 特性) /**
* authentication of an user through of class RBAC_user
*
* checking that an user has right to start an applicaton
*
* @author Fernando Ontiveros Lira <fernando@colosa.com>
* @access public
* @param string $strUser UserId (login) an user
* @param string $strPass Password
* @return
* -1: no user
* -2: wrong password
* -3: inactive usuario
* -4: due date
* -5: invalid authentication source ( **new )
* n : uid of user
*/
function NoSSOVerifyLogin( $strUser, $strPass)
{
if ( strlen($strPass) == 0) return -2;
//check if the user exists in the table RB_WORKFLOW.USERS
$this->initRBAC();
//if the user exists, the VerifyUser function will return the user properties
if ( $this->userObj->verifyUser($strUser) == 0 ) {
//here we are checking if the automatic user Register is enabled, ioc return -1
$res = $this->checkAutomaticRegister( $strUser, $strPass);
if ( $res == 1 )
$this->userObj->verifyUser($strUser);
else
return $res;
}
//default values
$sAuthType = 'mysql';
if ( isset($this->userObj->fields['USR_AUTH_TYPE']) ) $sAuthType = strtolower ( $this->userObj->fields['USR_AUTH_TYPE'] );
//hook for RBAC plugins
if ( $sAuthType != 'mysql' && $sAuthType != '' ) {
$sAuthSource = $this->userObj->fields['UID_AUTH_SOURCE'];
$sAuthUserDn = $this->userObj->fields['USR_AUTH_USER_DN'];
$res = $this->VerifyWithOtherAuthenticationSource( $sAuthType, $sAuthSource, $this->userObj->fields, $sAuthUserDn, $strPass);
return $res;
}
else {
$this->userObj->reuseUserFields = true;
$res = $this->userObj->NoSSOVerifyLogin($strUser, $strPass);
return $res;
}
}
即在函数执行的最后阶段,只把login函数最后的userObj->VerifyLogin改为userObj->NoSSOVerifyLogin,来充当新函数了。$uid = $RBAC->VerifyLogin($userid , $password);
改为:$uid = $RBAC->NoSSOVerifyLogin($userid , $password);