公司需要使用SugarCRM且与其他系统集成,但是又需要使用cas单点登录。所以必须修改SugarCRM源代码,经过多次尝试,找到相对比较靠谱的方法,记录如下:
在最后面加上如下这句
'authenticationClass' => 'CASAuthenticate',
这句话的意思应该是让自定义的CASAuthenticate类全面接管授权工作
增加如下语句:
因为我下载的是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'
);
}