Return true if the parameter is an empty string or a stringcontaining only whitespace, false otherwise@param string $p_var string to test@return bool@access public */
Gets the value of a specific field from LDAP given the user nameand LDAP field name. *@todo Implement caching by retrieving all needed information in one query.@todo Implement logging to LDAP queries same way like DB queries. *@param string $p_username The user name.@param string $p_field The LDAP field name.@return string The field value or null if not found. */
function ldap_get_field_from_username( $p_username, $p_field ) {
Authenticates an user via LDAP given the username and password. *@param string $p_username The user name.@param string $p_password The password.@return true: authenticated, false: failed to authenticate. */
function ldap_authenticate_by_username( $p_username, $p_password ) {
$c_username = ldap_escape_string( $p_username );
$t_ldap_organization = config_get( 'ldap_organization' );
$t_ldap_root_dn = config_get( 'ldap_root_dn' );
$t_ldap_uid_field = config_get( 'ldap_uid_field', 'uid' );
$t_search_filter = "(&$t_ldap_organization($t_ldap_uid_field=$c_username))";
$t_search_attrs = array(
$t_ldap_uid_field,
'dn',
);
# Bind
try {
$t_ds = ldap_connect_bind();
} catch (Exception $e) {
message(1,'活动目录设置参数可能不对,请检查?');
}
# Search for the user id
$t_sr = ldap_search( $t_ds, $t_ldap_root_dn, $t_search_filter, $t_search_attrs );
if ( $t_sr === false ) {
ldap_unbind( $t_ds );
}
$t_info = @ldap_get_entries( $t_ds, $t_sr );
if ( $t_info === false ) {
ldap_free_result( $t_sr );
ldap_unbind( $t_ds );
}
$t_authenticated = false;
if ( $t_info['count'] > 0 ) {
# Try to authenticate to each until we get a match
for ( $i = 0; $i < $t_info['count']; $i++ ) {
$t_dn = $t_info[$i]['dn'];
# Attempt to bind with the DN and password
if ( @ldap_bind( $t_ds, $t_dn, $p_password ) ) {
$t_authenticated = true;
break;
}
}
}
ldap_free_result( $t_sr );
ldap_unbind( $t_ds );
return $t_authenticated;
@爱学习的UncleLI 执行这条命令可以修复声音问题:
echo -e 'pcm.!default pulse\nctl.!default pulse' | sudo tee /etc/asound.conf
来自 https://www.youtube.com/watch?v=9K9b2tXLGrw
https://www.danieltufvesson.com/makeresolvedeb
DaVinci Resolve视频编辑软件
https://blog.csdn.net/lemonminer/article/details/107187297
minio PHPsdk
https://qzone.work/codes/255.html
typecho
https://blog.phpgao.com/typecho_plugin_release_page.html
插件
https://www.cnblogs.com/newz/p/12598899.html
https://recomm.cnblogs.com/blogpost/12910360
1 如何查看日志? 遇到问题不要慌,排查日志第一步。 # 系统实时日志 journalctl -n 100 -f # 搜索警告日志 journalctl | grep 'level=warning' # 根据可能关键词搜索 journalctl | grep 'Networking will not work' 或者 journalctl | grep 'IPv4'
2.如何解决问题? 从原因可以看到,IP转发被禁用,导致网络不通,那么如何开启内核IP转发呢,如下: 备注:解决问题其实最容易,根据自己的知识google就行了,找出原因往往才是最难的,这里就不详细说明了。 # 2.1 会话 echo 1 > /proc/sys/net/ipv4/ip_forward # 2.2 永久 vi /etc/sysctl.conf 添加如下代码: net.ipv4.ip_forward=1 # 2.3 检查 重启network服务 systemctl restart network 查看是否修改成功 sysctl net.ipv4.ip_forward
【活跃】猎人 20:16:55
更建议debian 不是很建议centos
【群主】疯子手机号888866 20:17:12
因为容器会共享基础镜像的
【群主】疯子手机号888866 20:17:22
一个debian可能占用80M,你开10个还是80M
【活跃】穴儿 20:18:44
docker 咋保存啊 想换服务的时候复原。。。
【群主】疯子手机号888866 20:19:16
然而alpine因为缺少各种依赖,你在每个容器中安装依赖,这些东西不共享的,占用的空间你容器越多反而比debian更多。
【群主】疯子手机号888866 20:19:58
如果你只有golang程序可能alpine是最好的选择,因为golang基本都没啥依赖,如果是其他的话果断选个依赖包全的镜像
【群主】疯子手机号888866 20:20:11
比如aite.xyz的基础镜像就是golang:alpine
【群主】疯子手机号888866 20:20:20
但是php-fpm之类的我多选择了debian
【群主】疯子手机号888866 20:20:30
根据实际情况选择基础镜像,而不是啥都不知道就上alpine
【群主】疯子手机号888866 20:20:41
比如postgres的alpine镜像有locales区域问题
https://www.bilibili.com/video/BV1pt411p7jg?p=8
https://www.urlos.com/center-home-software-freeVersion-w-s-y.html#urlosInstall
http://www.xjishu.com/zhuanli/55/201720047432.html
http://www.xjishu.com/zhuanli/54/201822255098.html
https://www.linuxidc.com/Linux/2018-11/155466.htm
smb服务器
funsion 360
实体建模
Nordic Semiconductor nRF52832
占位符呀 不同的符号代表不同的类型
bool string int float32 等 %s %d %t %f 等
王道长 22:02:48
问个问题哈 md5.Sum() 我想用变量str来替换 md5,那这个函数该怎么写呢?
北京-dotdotdot 22:11:53
s:=fmt.Sprintf("%x",m)
mmmm
https://github.com/guanzi008/OpenSSLForAndroid
گگ罐گ//./xian.
克隆了.
@گگ罐گ//./xian. 照着https://blog.csdn.net/qq_27637465/article/details/106531334写的。
用github action编译了个openssl 1.1.1g for android
您查询的关键词仅在网页标题或指向此网页的链接中出现。
如果打开速度慢,可以尝试快速版;如果想更新或删除快照,可以投诉快照。
百度和网页 http://bbs.xiuno.com/thread-150118.htm 的作者无关,不对其内容负责。百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面。
插件
首页
程序发布
安装
BUG
插件
模板
WEB开发
XiunoPHP
测试
交流
IP查询
搜索
登录
插件
LDAP活动目录认证插件
LDAP活动目录认证插件 功能增强 文档教程
1Bill 2019-1-20 2830
由于公司业务发展需要,在原认证基础上增加LDAP认证。实现统一账户认证。
目前公司已经把邮件、网盘、GIT、禅道、一些不能使用认证的应用比如(elasticsearch,netdata)通过nginx 的auth_request 与活动目录认证集成。
现在分享下:这个插件,程序简单粗暴。
至于 活动目录用户则是通过 shell脚本定时写入到数据库,保证用户信息同步。 这里就不提供了。
欢迎大家一起交流。。。。
LDAP配置信息采用 cache。
通过 kv_get('ldap_settiings') 获取参数。
新增模型: ./model/ldap.func.php
<?php
/**
Created by PhpStorm.User: bill mailto:benma9@qq.comDate: 2019/1/20Time: 2:43 AM*/
/**
返回配置参数@param string $key@return*/
function config_get($key)
global $ldap_config; $ldap_config=kv_get('ldap_settings'); if($ldap_config) { return isset($ldap_config[$key])?$ldap_config[$key] : $value; }else { return ''; }{
}
/**
Return true if the parameter is an empty string or a stringcontaining only whitespace, false otherwise@param string $p_var string to test@return bool@access public*/
function is_blank( $p_var ) {
$p_var = trim( $p_var ); $str_len = strlen( $p_var ); if( 0 == $str_len ) { return true; } return false;}
/**
Connect and bind to the LDAP directory@param string $p_binddn@param string $p_password@return resource or false*/
function ldap_connect_bind( $p_binddn = '', $p_password = '' ) {
if( !extension_loaded( 'ldap' ) ) { message(1,'请确认已经安装php-ldap?'); } $t_ldap_server = config_get( 'ldap_server' ); # Connect to LDAP server $t_ds = @ldap_connect( $t_ldap_server ); if ( $t_ds !== false && $t_ds > 0 ) { $t_protocol_version = config_get( 'ldap_protocol_version' ); if( $t_protocol_version > 0 ) { $t_result = @ldap_set_option( $t_ds, LDAP_OPT_PROTOCOL_VERSION, $t_protocol_version ); if( !$t_result ) { echo ( $t_ds ); } } # Set referrals flag. $t_follow_referrals = 0 == config_get( 'ldap_follow_referrals' ); $t_result = @ldap_set_option( $t_ds, LDAP_OPT_REFERRALS, $t_follow_referrals ); if( !$t_result ) { echo( $t_ds ); } # If no Bind DN and Password is set, attempt to login as the configured # Bind DN. if( is_blank( $p_binddn ) && is_blank( $p_password ) ) { $p_binddn = config_get( 'ldap_bind_dn', '' ); $p_password = config_get( 'ldap_bind_passwd', '' ); } if( !is_blank( $p_binddn ) && !is_blank( $p_password ) ) { $t_br = @ldap_bind( $t_ds, $p_binddn, $p_password ); } else { # Either the Bind DN or the Password are empty, so attempt an anonymous bind. $t_br = @ldap_bind( $t_ds ); } } return $t_ds;}
/**
Escapes the LDAP string to disallow injection.*@param string $p_string The string to escape.@return string The escaped string.
*/
function ldap_escape_string( $p_string ) {
$t_find = array( '\\', '*', '(', ')', '/', "\x00" ); $t_replace = array( '\5c', '\2a', '\28', '\29', '\2f', '\00' ); $t_string = str_replace( $t_find, $t_replace, $p_string ); return $t_string;}
/**
Gets the value of a specific field from LDAP given the user nameand LDAP field name.*@todo Implement caching by retrieving all needed information in one query.@todo Implement logging to LDAP queries same way like DB queries.
*@param string $p_username The user name.@param string $p_field The LDAP field name.@return string The field value or null if not found.
*/
function ldap_get_field_from_username( $p_username, $p_field ) {
$t_ldap_organization = config_get( 'ldap_organization' ); $t_ldap_root_dn = config_get( 'ldap_root_dn' ); $t_ldap_uid_field = config_get( 'ldap_uid_field' ); $c_username = ldap_escape_string( $p_username ); # Bind $t_ds = @ldap_connect_bind(); if ( $t_ds === false ) { return null; } # Search $t_search_filter = "(&$t_ldap_organization($t_ldap_uid_field=$c_username))"; $t_search_attrs = array( $t_ldap_uid_field, $p_field, 'dn' ); $t_sr = @ldap_search( $t_ds, $t_ldap_root_dn, $t_search_filter, $t_search_attrs ); if ( $t_sr === false ) { ldap_unbind( $t_ds ); return null; } # Get results $t_info = ldap_get_entries( $t_ds, $t_sr ); if ( $t_info === false ) { return null; } # Free results / unbind ldap_free_result( $t_sr ); ldap_unbind( $t_ds ); # If no matches, return null. if ( count( $t_info ) == 0 ) { return null; } # Make sure the requested field exists if( is_array($t_info[0]) && array_key_exists( $p_field, $t_info[0] ) ) { $t_value = $t_info[0][$p_field][0]; } else { return null; } return $t_value;}
/**
Authenticates an user via LDAP given the username and password.*@param string $p_username The user name.@param string $p_password The password.@return true: authenticated, false: failed to authenticate.
*/
function ldap_authenticate_by_username( $p_username, $p_password ) {
$c_username = ldap_escape_string( $p_username ); $t_ldap_organization = config_get( 'ldap_organization' ); $t_ldap_root_dn = config_get( 'ldap_root_dn' ); $t_ldap_uid_field = config_get( 'ldap_uid_field', 'uid' ); $t_search_filter = "(&$t_ldap_organization($t_ldap_uid_field=$c_username))"; $t_search_attrs = array( $t_ldap_uid_field, 'dn', ); # Bind try { $t_ds = ldap_connect_bind(); } catch (Exception $e) { message(1,'活动目录设置参数可能不对,请检查?'); } # Search for the user id $t_sr = ldap_search( $t_ds, $t_ldap_root_dn, $t_search_filter, $t_search_attrs ); if ( $t_sr === false ) { ldap_unbind( $t_ds ); } $t_info = @ldap_get_entries( $t_ds, $t_sr ); if ( $t_info === false ) { ldap_free_result( $t_sr ); ldap_unbind( $t_ds ); } $t_authenticated = false; if ( $t_info['count'] > 0 ) { # Try to authenticate to each until we get a match for ( $i = 0; $i < $t_info['count']; $i++ ) { $t_dn = $t_info[$i]['dn']; # Attempt to bind with the DN and password if ( @ldap_bind( $t_ds, $t_dn, $p_password ) ) { $t_authenticated = true; break; } } } ldap_free_result( $t_sr ); ldap_unbind( $t_ds ); return $t_authenticated;}
控制器
覆盖 ./route/user.php (login部分重写,增加LDAP认证方法,LDAP认证不通过,则继续使用原认证),此模版会与 xn_mobile冲突,如有手机登录需求,请自行合并。
elseif($action == 'login') {
// hook user_login_get_post.php
if($method == 'GET') {
// hook user_login_get_start.php $referer = user_http_referer(); $header['title'] = lang('user_login'); // hook user_login_get_end.php include _include(APP_PATH.'view/htm/user_login.htm');} else if($method == 'POST') {
// hook user_login_post_start.php// LDAP认证部分
include APP_PATH.'plugin/socialbird_ldap/model/ldap.func.php';
$email = param('email'); // 邮箱或者手机号 / email or mobile
$password = param('password');
empty($email) AND message('email', lang('email_is_empty'));
if(is_email($email, $err)) {
$_user = user_read_by_email($email);
empty($_user) AND message('email', lang('email_not_exists'));
} else {
$_user = user_read_by_username($email);
empty($_user) AND message('email', lang('username_not_exists'));
}
if (ldap_authenticate_by_username($_user['username'],$password))
{
user_update($_user['uid'], array('login_ip' => $longip, 'login_date' => $time, 'logins+' => 1));
$uid = $_user['uid'];
$_SESSION['uid'] = $uid;
user_token_set($_user['uid']);
message(0, lang('user_login_successfully'));
}
$password = md5($password);
// LDAP认证结束,注释掉以下代码,
// 同时覆盖 view/htm/user_login.html文件,
// 注释掉 70行代码 //postdata.password = $.md5(postdata.password);
// 防止密码 md5加密,活动目录认证则失败!
// 账户同步脚本 可以联系作者 billmailto:benma9@qq.com 获得。
// $email = param('email'); // 邮箱或者手机号 / email or mobile
!is_password($password, $err) AND message('password', $err); $check = (md5($password.$_user['salt']) == $_user['password']); // hook user_login_post_password_check_after.php !$check AND message('password', lang('password_incorrect')); // 更新登录时间和次数 // update login times user_update($_user['uid'], array('login_ip'=>$longip, 'login_date' =>$time , 'logins+'=>1)); // 全局变量 $uid 会在结束后,在函数 register_shutdown_function() 中存入 session (文件: model/session.func.php) // global variable $uid will save to session in register_shutdown_function() (file: model/session.func.php) $uid = $_user['uid']; $_SESSION['uid'] = $uid; user_token_set($_user['uid']); // hook user_login_post_end.php // 设置 token,下次自动登陆。 message(0, lang('user_login_successfully'));// $password = param('password');
// empty($email) AND message('email', lang('email_is_empty'));
// if(is_email($email, $err)) {
// $_user = user_read_by_email($email);
// empty($_user) AND message('email', lang('email_not_exists'));
// } else {
// $_user = user_read_by_username($email);
// empty($_user) AND message('email', lang('username_not_exists'));
// }
}
管理: 覆盖./admin/index.php (login部分重写)
if($action == 'login') {
// hook admin_index_login_get_post.php if($method == 'GET') { // hook admin_index_login_get_start.php $header['title'] = lang('admin_login'); include _include(ADMIN_PATH."view/htm/index_login.htm"); } else if($method == 'POST') { // hook admin_index_login_post_start.php include APP_PATH.'plugin/socialbird_ldap/model/ldap.func.php'; $password = param('password'); if (!ldap_authenticate_by_username($user['username'],$password)) { $password = md5($password); if(md5($password.$user['salt']) != $user['password']) { xn_log('password error. uid:'.$user['uid'].' - ******'.substr($password, -6), 'admin_login_error'); message('password', lang('password_incorrect')); } } admin_token_set(); xn_log('login successed. uid:'.$user['uid'], 'admin_login'); // hook admin_index_login_post_end.php message(0, jump(lang('login_successfully'), '.')); }}
模版view:
覆盖 ./view/htm/user_login.htm ,注释掉70行,防止md5加密导致ldap认证无法通过
覆盖 ./admin/view/htm/index_login.htm, 注释
//postdata.password = $.md5(postdata.password);
收藏 1
收藏的用户(1) X
正在加载信息~
最新回复 (5)
axiuno 2019-1-20
引用 2楼
nice
senlo 2019-1-20
引用 3楼
优秀
452010152 2019-1-20
引用 4楼
给力
达无谓惧 2019-2-14
引用 5楼
特别感谢,近期正好有此方面的需要,但是目前在官方插件库里并没有看到此插件,请问能否提供一下下载路径吗?谢谢
十品香茗爱观音 2019-3-1
引用 6楼
感谢楼主的无私分享,这个插件哪里可以下载呢?
返回
发新帖
1Bill
主题数
1 帖子数
1 精华数
1 注册排名
21369
关键词
搜索
Powered by Xiuno BBS 4.0.4 - 北京若深科技有限公司
Processed: 0.003, SQL: 8 / 京ICP备17008605号-1
https://pdf2doc.com/zh/
文件管理器 https://tinyfilemanager.github.io/
hu60.cn
hu60.cn
。
。
。
天蓝的博客https://xn--rssy03h.cn/
新的一天