公司需要使用SugarCRM且与其他系统集成,但是又需要使用cas单点登录。所以必须修改SugarCRM源代码,经过多次尝试,找到相对比较靠谱的方法,记录如下:
- 修改config.php
在最后面加上如下这句
'authenticationClass' => 'CASAuthenticate',
这句话的意思应该是让自定义的CASAuthenticate类全面接管授权工作
- 修改index.php
增加如下语句:
因为我下载的是6.1.2所以无需增加
require_once('modules/Users/authentication/AuthenticationController.php');$authController = new AuthenticationController((!empty($GLOBALS['sugar_config']['authenticationClass'])? $GLOBALS['sugar_config']['authenticationClass'] : 'SugarAuthenticate'));
- 创建授权类文件
创建如下目录
SugarCE/modules/Users/authentication/CASAuthenticate
建立如下两个文件:
CASAuthenticate.php
<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once('modules/Users/authentication/SugarAuthenticate/SugarAuthenticate.php');
require_once('CAS.php');
/********************************************************************
* Module that allows Sugar to perform user authentication using
* CAS.
*********************************************************************/
class CASAuthenticate extends SugarAuthenticate {
var $userAuthenticateClass = 'CASAuthenticateUser';
var $authenticationDir = 'CASAuthenticate';
function CASAuthenticate(){
parent::SugarAuthenticate();
// require_once('modules/Users/authentication/'. $this->authenticationDir . '/'. $this->userAuthenticateClass . '.php');
// $this->userAuthenticate = new $this->userAuthenticateClass();
$this->doCASAuth();
}
function doCASAuth(){
@session_start();
// Don't try to login if the user is logging out
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'Logout') {
echo "logout xxxxxxx";
$this->logout();
}
// If the user is already authenticated, do this.
elseif (isset($_SESSION['authenticated_user_id']) ) {
$this->sessionAuthenticate();
return;
}
// Try to log the user in via SSO
else {
if ($this->userAuthenticate->loadUserOnLogin() == true) {
parent::postLoginAuthenticate();
}
else {
die(); //I should redirect here. I'm not sure on the syntax -- sorry.
} //end nested else.
} // end top else.
} //end doCASAuth()
function sessionAuthenticate(){
global $module, $action, $allowed_actions;
$authenticated = false;
$allowed_actions = array ("Authenticate", "Login"); // these are actions where the user/server keys aren't compared
if (isset ($_SESSION['authenticated_user_id'])) {
$GLOBALS['log']->debug("We have an authenticated user id: ".$_SESSION["authenticated_user_id"]);
$authenticated = $this->postSessionAuthenticate();
} else
if (isset ($action) && isset ($module) && $action == "Authenticate" && $module == "Users") {
$GLOBALS['log']->debug("We are NOT authenticating user now. CAS will redirect.");
}
return $authenticated;
} //end sessionAuthenticate()
function postSessionAuthenticate(){
global $action, $allowed_actions, $sugar_config;
$_SESSION['userTime']['last'] = time();
$user_unique_key = (isset ($_SESSION['unique_key'])) ? $_SESSION['unique_key'] : '';
$server_unique_key = (isset ($sugar_config['unique_key'])) ? $sugar_config['unique_key'] : '';
//CHECK IF USER IS CROSSING SITES
if (($user_unique_key != $server_unique_key) && (!in_array($action, $allowed_actions)) && (!isset ($_SESSION['login_error']))) {
session_destroy();
$post_login_nav = '';
if (!empty ($record) && !empty ($action) && !empty ($module)) {
$post_login_nav = "&login_module=".$module."&login_action=".$action."&login_record=".$record;
}
$GLOBALS['log']->debug('Destroying Session User has crossed Sites');
//header("Location: index.php?action=Login&module=Users".$post_login_nav);
sugar_cleanup(true);
die();
}
if (!$this->userAuthenticate->loadUserOnSession($_SESSION['authenticated_user_id'])) {
session_destroy();
//header("Location: index.php?action=Login&module=Users");
$GLOBALS['log']->debug('Current user session does not exist redirecting to login');
sugar_cleanup(true);
die();
}
$GLOBALS['log']->debug('Current user is: '.$GLOBALS['current_user']->user_name);
return true;
}//end postSessionAuthenticate()
function logout() {
phpCAS::setDebug();
phpCAS::client(SAML_VERSION_1_1,'xxx.xxx.xxx',xxx,'Context',false);//CAS服务端的地址,端口号,与上下文
phpCAS::setNoCasServerValidation();
phpCAS::logout();
}
}//end CASAuthenticate class
CASAuthenticateUser.php
<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once('modules/Users/authentication/SugarAuthenticate/SugarAuthenticateUser.php');
require_once('CAS.php');
class CASAuthenticateUser extends SugarAuthenticateUser {
/********************************************************************************
* This is called when a user logs in
*
* @param STRING $name
* @param STRING $password
* @return boolean
********************************************************************************/
function loadUserOnLogin() {
$name=$this->authUser();
if(empty($name)){
return false;
}
else{
$GLOBALS['log']->debug("Starting user load for ". $name);
$this->loadUserOnSession($user_id);
return true;
}
}//end loadUserOnlogin()
/**********************************************************************************************************************
* Attempt to authenticate the user via CAS SSO
***********************************************************************************************************************/
function authUser() {
phpCAS::setDebug();
phpCAS::client(SAML_VERSION_1_1,'xxx.xxx.xxx',xxx,'Context',false);//CAS服务端的地址,端口号,与上下文
phpCAS::setNoCasServerValidation();
phpCAS::forceAuthentication();
$authenticated = phpCAS::isAuthenticated();
if ($authenticated)
{
$user_name = phpCAS::getUser();
$query = "SELECT * from users where user_name='$user_name' and deleted=0";
$result =$GLOBALS['db']->limitQuery($query,0,1,false);
$row = $GLOBALS['db']->fetchByAssoc($result);
if (!empty ($row))
{
$_SESSION['authenticated_user_id'] = $row['id'];
}
else // row in Sugar DB was empty, even though user is in CAS.
{ $user_id=$this->createSugarUser($name);
$_SESSION['authenticated_user_id'] = $userid;
return;
}
$_SESSION['login_user_name'] = $user_name;
$_REQUEST['user_password'] = 'foobar';
$action = 'Authenticate';
$module = 'Users';
$_REQUEST['action'] = 'Authenticate';
$_REQUEST['module'] = 'Users';
$_REQUEST['return_module'] = 'Users';
$_REQUEST['action_module'] = 'Login';
return $user_name; // SSO authentication was successful
}
else // not authenticated in CAS.
{
return;
}
}//end authenticateSSO();
function createSugarUser($name) {
$user = new User();
$user->user_name = $name;
$user->employee_status = 'Active';
$user->status = 'Active';
$user->is_admin = 0;
if ($name =='admin'){
$user->is_admin = 1;
}
$user->save();
// Force the user to go to the home screen
$_REQUEST['action'] = 'index';
$_REQUEST['module'] = 'Home';
// Return the user's GUID
return $user->id;
}//createSugarUser
/************************************************************************************************************/
/************************************************************************************************************/
}//End CASAuthenticateUSer class.
?>
修改login.php
将原来的
$sugar_smarty->display('modules/Users/login.tpl');
为
if($sugar_config["authenticationClass"] == "CASAuthenticate"){
header('Location: index.php?module=Home&action=index');
}
else {
$sugar_smarty->display('modules/Users/login.tpl');
}