CAS客户端整合(二) Zabbix

Zabbix是一个强大的服务器/交换机监控应用,有zabbix-server, zabbix-client, zabbix-web 三部分。zabbix-web管理端是用php写的。

前文参考:CAS客户端整合(一) Discuz!

登录流程

修改代码前例行先确定登录流程

原登录过程

Zabbix的登录流程跟 Discuz 类似。系统从 cookie/session 中读取用户会话id,如果用户为 guest ,只提供部分页面访问。需要访问受限资源,需要再登录

CAS登录过程

Zabbix通过cas登录也跟Discuz几乎一样,不过这次保留了zabbix的cookie判断

代码修改

引入cas-php-client

CAS客户端路径/local/cas,新建/local/cas/CasClient.php:

phpCAS::client ( CAS_VERSION_2_0, CAS_SERVER_HOST, CAS_SERVER_PORT, CAS_SERVER_PATH );

// no SSL validation for the CAS server
phpCAS::setNoCasServerValidation ();
phpCAS::handleLogoutRequests();
/**
 * 关闭url携带ticket参数,防止重复认证导致 ticket not recognized
 * @see [https://www.cnblogs.com/next-door-boy/p/3372522.html]
 */
phpCAS::$_PHPCAS_CLIENT->setNoClearTicketsFromUrl ();

/include/config.inc.php中导入

// cas client
require_once dirname(__FILE__).‘/../local/cas/CasClient.php‘;
// zabbix 核心
require_once dirname(__FILE__).‘/classes/core/Z.php‘;

Zabbix 登录

Zabbix的用户登录验证统一接口/include/class/user/CWebUser::checkAuthentication.这里是主要的登录逻辑。zabbix从cookie中获取zbxsessionid,然后比对是否有效sessionid。如果是有效用户我们直接允许。如果是guest用户或没有 sessionid 则检查cas是否已登录,如果已登录则初始化用户信息(代码在下一步介绍)。

public static function checkAuthentication($sessionId) {
    try {
        if ($sessionId !== null) {
            self::$data = API::User()->checkAuthentication([$sessionId]);
            /*
             * login as guest
             * cas authentication.
             */
            if (self::$data[‘alias‘] == ZBX_GUEST_USER && phpCAS::isAuthenticated()) {
                $sessionId = login_via_cas(phpCAS::getUser());
                self::setSessionCookie($sessionId);
                return $sessionId;
            }
        }

        if ($sessionId === null || empty(self::$data)) {
            /*
             * cas authentication.
             */
            if (phpCAS::isAuthenticated()) {
                $sessionId = login_via_cas(phpCAS::getUser());
                self::setSessionCookie($sessionId);
                return $sessionId;
            }
            self::setDefault();
            self::$data = API::User()->login([
                ‘user‘ => ZBX_GUEST_USER,
                ‘password‘ => ‘‘,
                ‘userData‘ => true
            ]);

            if (empty(self::$data)) {
                clear_messages(1);
                throw new Exception();
            }
            $sessionId = self::$data[‘sessionid‘];
        }

        if (self::$data[‘gui_access‘] == GROUP_GUI_ACCESS_DISABLED) {
            throw new Exception();
        }

        self::setSessionCookie($sessionId);

        return $sessionId;
    }
    catch (Exception $e) {
        self::setDefault();
        return false;
    }
}

初始化用户信息

根据用户名初始化用户信息,代码从/include/class/api/services/CUser::login() 方法修改而来

    /**
 * Login from cas
 * init user info.
 * @param $name
 * @author Carl
 */
function login_via_cas($name) {
    $userInfo = DBfetch(DBselect(
        ‘SELECT u.userid,u.attempt_failed,u.attempt_clock,u.attempt_ip‘.
        ‘ FROM users u‘.
        ‘ WHERE u.alias=‘.zbx_dbstr($name)
    ));
    if (!$userInfo) {
        //CUser::exception(ZBX_API_ERROR_PARAMETERS, _(‘Login name or password is incorrect.‘));
    }
    // check if user is blocked
    if ($userInfo[‘attempt_failed‘] >= ZBX_LOGIN_ATTEMPTS) {
        if ((time() - $userInfo[‘attempt_clock‘]) < ZBX_LOGIN_BLOCK) {
            //CUser::exception(ZBX_API_ERROR_PARAMETERS, _s(‘Account is blocked for %s seconds‘, (ZBX_LOGIN_BLOCK - (time() - $userInfo[‘attempt_clock‘]))));
        }
        DBexecute(‘UPDATE users SET attempt_clock=‘.time().‘ WHERE alias=‘.zbx_dbstr($name));
    }
    // check system permissions
    if (!check_perm2system($userInfo[‘userid‘])) {
        //CUser::exception(ZBX_API_ERROR_PARAMETERS, _(‘No permissions for system access.‘));
    }
    $dbAccess = DBfetch(DBselect(
        ‘SELECT MAX(g.gui_access) AS gui_access‘.
        ‘ FROM usrgrp g,users_groups ug‘.
        ‘ WHERE ug.userid=‘.zbx_dbstr($userInfo[‘userid‘]).
        ‘ AND g.usrgrpid=ug.usrgrpid‘
    ));

    if (zbx_empty($dbAccess[‘gui_access‘])) {
        $guiAccess = GROUP_GUI_ACCESS_SYSTEM;
    }
    else {
        $guiAccess = $dbAccess[‘gui_access‘];
    }
    // start session
    $sessionid = md5(time().$name.rand(0, 10000000));
    DBexecute(‘INSERT INTO sessions (sessionid,userid,lastaccess,status)‘.
        ‘ VALUES (‘.zbx_dbstr($sessionid).‘,‘.zbx_dbstr($userInfo[‘userid‘]).‘,‘.time().‘,‘.ZBX_SESSION_ACTIVE.‘)‘
    );
    $userid = $userInfo[‘userid‘];
    $userData = DBfetch(DBselect(
        ‘SELECT u.userid,u.alias,u.name,u.surname,u.url,u.autologin,u.autologout,u.lang,u.refresh,u.type,‘.
        ‘ u.theme,u.attempt_failed,u.attempt_ip,u.attempt_clock,u.rows_per_page‘.
        ‘ FROM users u‘.
        ‘ WHERE u.userid=‘.zbx_dbstr($userid)
    ));

    $userData[‘debug_mode‘] = (bool) DBfetch(DBselect(
        ‘SELECT ug.userid‘.
        ‘ FROM usrgrp g,users_groups ug‘.
        ‘ WHERE ug.userid=‘.zbx_dbstr($userid).
        ‘ AND g.usrgrpid=ug.usrgrpid‘.
        ‘ AND g.debug_mode=‘.GROUP_DEBUG_MODE_ENABLED
    ));

    $userData[‘userip‘] = (isset($_SERVER[‘HTTP_X_FORWARDED_FOR‘]) && $_SERVER[‘HTTP_X_FORWARDED_FOR‘])
        ? $_SERVER[‘HTTP_X_FORWARDED_FOR‘]
        : $_SERVER[‘REMOTE_ADDR‘];
    $userData[‘sessionid‘] = $sessionid;
    $userData[‘gui_access‘] = $guiAccess;

    if ($userInfo[‘attempt_failed‘]) {
        DBexecute(‘UPDATE users SET attempt_failed=0 WHERE userid=‘.zbx_dbstr($userInfo[‘userid‘]));
    }
    CWebUser::$data = CUser::$userData = $userData;
    return $sessionid;
}

登出

分析代码发现zabbix的登出全部转到 index.php 中处理。修改logout这一段

// VAR  TYPE    OPTIONAL    FLAGS   VALIDATION  EXCEPTION
$fields = [
    ‘name‘ =>       [T_ZBX_STR, O_NO,   null,   null,       ‘isset({enter})‘, _(‘Username‘)],
    ‘password‘ =>   [T_ZBX_STR, O_OPT, null,    null,           ‘isset({enter})‘],
    ‘sessionid‘ =>  [T_ZBX_STR, O_OPT, null,    null,           null],
    ‘reconnect‘ =>  [T_ZBX_INT, O_OPT, P_SYS|P_ACT, BETWEEN(0, 65535), null],
    ‘enter‘ =>      [T_ZBX_STR, O_OPT, P_SYS,   null,           null],
    ‘autologin‘ =>  [T_ZBX_INT, O_OPT, null,    null,           null],
    ‘request‘ =>    [T_ZBX_STR, O_OPT, null,    null,           null],
    // zabbix 独特的检查机制,如果不指定无法从 $_REQUEST 变量获取获取请求参数
    ‘logoutRequest‘ =>  [T_ZBX_STR, O_OPT, null,    null,           null],
];
check_fields($fields);

// logout
if (isset($_REQUEST[‘reconnect‘]) || !empty($_REQUEST[‘logoutRequest‘])) {
    DBstart();
    add_audit_details(AUDIT_ACTION_LOGOUT, AUDIT_RESOURCE_USER, CWebUser::$data[‘userid‘], ‘‘, _(‘Manual Logout‘),
        CWebUser::$data[‘userid‘]
    );
    DBend(true);
    CWebUser::logout();
    //$ref = empty($_SERVER[‘HTTP_REFERER‘]) ? (‘http://‘.$_SERVER[‘SERVER_NAME‘].substr($_SERVER[‘PHP_SELF‘], 0, strrpos($_SERVER[‘PHP_SELF‘], ‘/‘)+1).‘index.php‘) : $_SERVER[‘HTTP_REFERER‘];
    // cas 退出后返回的地址
    $ref = ‘http://‘.$_SERVER[‘SERVER_NAME‘].substr($_SERVER[‘PHP_SELF‘], 0, strrpos($_SERVER[‘PHP_SELF‘], ‘/‘)+1).‘index.php‘;
    phpCAS::logoutWithRedirectService($ref);
    redirect(‘index.php‘);
}

小结

代码看起来很少,但是要仔细查看源码分析登录过程,然后在什么地方做修改还是比较费心思的。

这个流程同步登录已经没问题了,但是不能同步登出。

因为zabbix的session是以cookie的形式存储。而cas-server无法清除客户端本地的cookie,这里我们又直接根据cookie验证用户,所以跳过了cas的状态复查。

这么看来,如果换成cas认证,那么必须抛弃cookie认证?

时间: 2024-10-09 16:56:29

CAS客户端整合(二) Zabbix的相关文章

zabbix 二 zabbix agent 客户端

[[email protected]_agent src]# cd zabbix-3.0.3 [[email protected]_agent zabbix-3.0.3]# ls aclocal.m4 bin ChangeLog conf config.sub configure.ac database frontends INSTALL m4 Makefile.in misc NEWS src AUTHORS build compile config.guess configure COPYI

cas sso单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析

转:http://blog.csdn.net/ae6623/article/details/8848107 1)PPT流程图:ppt下载:http://pan.baidu.com/s/1o7KIlom 一.用户第一次访问web1应用. ps:上图少画了一条线,那一条线,应该再返回来一条,然后再到server端,画少了一步...谢谢提醒.而且,重定向肯定是从浏览器过去的.我写的不严谨,画的比较通俗了...因该像下面这张图一样就ok了!!PPT自己下载下来修改吧,我就不改了. 二.用户第一次访问we

window7使用svn(svn系列 客户端 知识二总结)

 ?eclipse插件subclipse  ?TortoiseSVN  ?svn操作  ?注意事项 使用svn可以在eclipse直接装subclipse或者在windows使用TortoiseSVN. 1.eclipse插件subclipse 可以在线或者离线安装,这里只介绍离线安装. 下载subclipse:http://subclipse.tigris.org/ csdn下载地址:http://download.csdn.net/detail/sinat_31719925/9800062

Cas 服务器 Service(Cas客户端)注册信息维护

作为Cas服务器,允许哪些客户端接入与否是通过配置来定义的.对Cas服务器来说,每一个接入的客户端与一个Service配置对应:在Cas服务器启动时加载并注册上这些Service,与之对应的客户端才能接入.否则将出现 一.假设Cas服务器为HTTPS类型 假设我们的Cas服务器运行在8443端口,以HTTPS协议对外提供服务(<Cas 服务器 下载.编译及部署>中的cas服务器配置). 1.1 Cas客户端类型为HTTP应用时的配置 假设我们的Cas客户端以HTTP协议来对外提供服务,对外提供

zabbix监控之二----Zabbix受控端及监控项

4.station32受控端安装zabbix 4.1:下载所需要用的的程序包:只有受控端是主动模式时才需要装zabbix-sender [[email protected]]# yum -y localinstall \ zabbix-2.2.3-1.el6.x86_64.rpm\               # 主程序server端/agent端都需要 zabbix-agent-2.2.3-1.el6.x86_64.rpm\         # 受控端安装agent程序 zabbix-send

Mvc4单点登录之三Cas 客户端配置

上一篇博客讲解了cas服务端的配置,这篇博客为大家讲一下cas 客户端的配置! 第一步建项目 自己新建一个mvc的项目.如图所示! 第二步添引用 将上一篇博客开头中让下载的文件,下载下来后,将dotnet-client-1.0.2-bin 文件中的 DotNetCasClient.dll文件复制到bin文件夹下,并添加DotNetCasClient.dll的引用. 第三步添视图 在Controller中 新建一个controller命名为HomeController,然后为里边的index添加一

redis ruby客户端学习( 二)

接上一篇redis ruby客户端学习( 二) 对于redis的五种数据类型:字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets),上一篇介绍了字符串. 1,哈希(Map) hset.设置 key 指定的哈希集中指定字段的值.如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联.如果字段在哈希集中存在,它将被重写. require "redis" r = Redis.new r.hset 'my_h

配置php的CAS客户端

1.下载安装xmapp 2.开启Apache服务. 3.下载php的CAS客户端源码包(我使用的是CAS-1.2.0.tgz),解压到xmap的htdocs目录下(D:\xmapp\htdocs),进入D:\xmapp\htdocs\CAS-1.2.0\docs\examples,将example_simple.php拷贝到D:\xmapp\htdocs\CAS-1.2.0目录下. 4.编辑example_sample.php 修改里面关于CAS服务器配置信息,修改代码中的phpCAS::cli

spring mvc+mybatis整合 (二)

转:http://lifeneveralone.diandian.com/post/2012-11-02/40042292065 本文介绍使用spring mvc结合Mybatis搭建一个应用程序框架. demo源码下载:springMVC-Mybatis 1.准备工作: spring的jar包: spring-beans-3.1.0.RELEASE.jar spring-core-3.1.0.RELEASE.jar spring-web-3.1.0.RELEASE.jar spring-web