天天看點

processmaker在與cas做SSO內建時需要做的修改

前言

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。

正文

  1. pm是用php實作的,是以要先下載下傳cas的php用戶端,可在此處下載下傳;
  2. php用戶端解壓後放在$pm/gulliver/thirdparty/下,才能在php代碼中引入cas庫;
  3. 修改$pm/workflow/engine/methods/login/authentication.php,在代碼最上面加入:
    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;
  4. 修改$pm/workflow/engine/xmlform/login/login.xml,在函數bsClick的最後一行加上:
    document.login.submit();
               
    這樣可以試pm原本的登入頁面自動送出,也就能自動跳轉到cas的登入頁面了。
  5. 修改$pm/rbac/engine/classes/model/RbacUsers.php,在verifyLogin()函數中将:替換為:即與步驟3中相對應;
  6. 修改$pm/workflow/engine/methods/login/login.php,在代碼最前面加入:
    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中登出。
  7. 為了實作cas登出功能,除了6,還要在$pm/workflow/engine/skinEngine/skinEngine.php的第391、394、663、666行,分别将“/login/login” 改為 “/login/login?logout=1”,與6中的修改配合實作。
  8. 就是需要在CAS server的資料源配置中引用pm的庫rb_workflow中的USERS表,配置的sql是“select USR_PASSWORD from USERS where USR_USERNAME=?”,passwordEncoder用MD5。

Extra

       如果隻是日常使用,上面的8條修改已經足夠了。但。。。

解決process的new web entry 與 CAS-SSO 使用者認證沖突的問題       

在使用process的new web entry時,需要填入使用者名和密碼,這是在RbacUsers.verify_login()函數中驗證的,但之前咱們已經在第5步修改了verify_login的代碼,從之前的使用者名/密碼改為僅看密碼是否等于CASAuthIsTrue來判斷了,就 會導緻在new web entry時候總報錯:密碼錯誤。 是以需要調整一下流程。

  1. 在$pm/rbca/engine/classes/model/RbacUsers.php中加入函數  noSSOVerifyLogin(即上面第5步中修改前的login函數):
    /**
       * 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 <[email protected]>
       * 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 特性)
  2. 修改$pm/gulliver/system/class.rbac.php,在其中加入一個函數 NoSSOVerifyLogin:
    /**
      * authentication of an user through of class RBAC_user
      *
      * checking that an user has right to start an applicaton
      *
      * @author Fernando Ontiveros Lira <[email protected]>
      * @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,來充當新函數了。
  3. new web entry使用的是pm的web service實作的login操作,首先修改$pm/workflow/engine/classes/class.wsBase.php中的login函數,将第三行的:
    $uid = $RBAC->VerifyLogin($userid , $password);
               
    改為:
    $uid = $RBAC->NoSSOVerifyLogin($userid , $password);
               

    這樣就實作了在new web entry時的内部驗證與SSO沖突的問題了。此類問題可能随着功能的深入還會有,之後再記錄。

繼續閱讀