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认证?

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

  1. CAS客户端整合(四)-- Cacti

    Cacti 是一套纯 lnmp 搭建的服务器监控系统,用 SNMP 抓取数据,RRDTool 绘制表格 登录流程 Cacti 的登录同样是先判断session,再尝试从 cookie 读取 sessi ...

  2. CAS客户端整合(三) Otrs

    OTRS 是用Perl写的一个工单邮件系统,非常强大. 登录流程 流程图略过 otrs没有像 discuz 和 zabbix 类似的游客登录状态,这样处理起来逻辑分支少一些. 不过还是考虑用 otrs ...

  3. CAS客户端整合(一) Discuz!

    有好几个系统需要接入CAS,所以登录模块统统需要重构 版本 CAS服务端是Java的 Cas-server-4.0 CAS的php客户端 是 phpCAS-1.2.0 论坛版本是 Discuz!X3. ...

  4. zabbix 二 zabbix agent 客户端

    [root@zabbix_agent src]# cd zabbix-3.0.3 [root@zabbix_agent zabbix-3.0.3]# ls aclocal.m4 bin ChangeL ...

  5. 品优购商城项目(六)CAS客户端与SpringSecurity集成

    cas单点登录旨在解决传统登录模式session在分布式项目中共享登录信息的问题. 本文cas服务器使用 4.0版本,仅供学习参考.把 cas.war 直接部署在tomcat即可,这里有个固定的用户名 ...

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

    转:http://blog.csdn.net/ae6623/article/details/8848107 1)PPT流程图:ppt下载:http://pan.baidu.com/s/1o7KIlom ...

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

     ♣eclipse插件subclipse  ♣TortoiseSVN  ♣svn操作  ♣注意事项 使用svn可以在eclipse直接装subclipse或者在windows使用TortoiseSVN ...

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

    作为Cas服务器,允许哪些客户端接入与否是通过配置来定义的.对Cas服务器来说,每一个接入的客户端与一个Service配置对应:在Cas服务器启动时加载并注册上这些Service,与之对应的客户端才能 ...

  9. springboot之cas客户端

    一.CAS Client 与受保护的客户端应用部署在一起,以 Filter 方式保护受保护的资源.对于访问受保护资源的每个 Web 请求,CAS Client 会分析该请求的 Http 请求中是否包含 ...

随机推荐

  1. Cardboard Talk01 HeadTracker

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Android studio 3.0.0 | Cardboard 1.0 使用 Google 的 Cardboard开发V ...

  2. 77. Combinations (Recursion)

    Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For exampl ...

  3. Associate File Type with Qt In Mac Os and Win

    Win Registry Question One day, my boss want me to finish one function which let the users can double ...

  4. yii 关于如何改变默认访问的控制器(site)

    以前Yii1学了个皮毛就没去管了,现在想重新捡起来Yii2.0.2却出来了,于是搭建好环境来学习. 安装好Yii2后第一个想到的问题就是修改默认的控制器了. 按照网上所说,终于在/vendor/yii ...

  5. MongoDB增加用户认证: 增加用户、删除用户、修改用户密码、读写权限、只读权限

    1.添加并验证用户 > use admin> db.addUser("zjx","tsjianxin") #添加用户 > db.auth(&q ...

  6. Linux select/poll和epoll实现机制对比

    关于这个话题,网上已经介绍的比较多,这里只是以流程图形式做一个简单明了的对比,方便区分. 一.select/poll实现机制 特点: 1.select/poll每次都需要重复传递全部的监听fd进来,涉 ...

  7. Spring 学习记录2 Environment

    Environment是什么 environment是什么呢....中文是环境大家都知道但是具体代表什么呢?感觉很抽象....从代码里的解释来看environment代表了profile和proper ...

  8. lnmp 一键安装包 nginx配置tp5 phpinfo模式 隐藏index.php

    tp5 url 线上访问 在nginx 上 出现404错误 那是因为pathinfo没有被支持 修改如下:找到   /usr/local/nginx/config/vhost/项目名.config s ...

  9. context:propertyPlaceholder

    Activates replacement of ${...} placeholders by registering a PropertySourcesPlaceholderConfigurer w ...

  10. 两个openssh间免密码登录

    以下针对的是openssh,而不是ssh,也不是ssh2.配置分两部分:一是对登录机的配置,二是对被登录机的配置,其中登录机为客户端,被登录机为服务端,也就是解决客户端到服务端的无密码登录问题.下述涉 ...