LDAP阶段性小结

时间:2021-07-14 00:28:17

经过几天的琢磨,利用LDAP实现用户共享的任务初步实现。

LDAP相关简介:

    1、快速响应和大容量查询并且提供多目录服务器的信息复制功能,它为读密集型的操作进行专门的 优化。因此,当从LDAP服务器中读取数据的时候会比从专门为OLTP优化的关系型数据库中读取数据快一个数量级。

   2、实现用户共享。即用某个第三方平台,管理公司内部的多个系统用户,同一个用户登录多个系统。

OpenLDAP服务器搭建:  下载地址:  openldap-2.2.29-db-4.3.29-openssl-0.9.8a-win32_Setup.exe

安装与配置:  推荐参考网址

1)、打开C:\Program Files\OpenLDAP \slapd.conf,找到ucdata-path    ./ucdata
        include  ./schema/core.schema,在它后面添加
        include  ./schema/cosine.schema
        include  ./schema/inetorgperson.schema

2)、下面我们做一个示例:需要在 slapd.conf 配置文件中,找到
       suffix  “dc=my-domain,dc=com”
       rootdn  “cn=Manager,dc=my-domain,dc=com”
     把这两行改为
       suffix     "dc=mycompany,dc=com"
       rootdn   "cn=Manager,dc=mycompany,dc=com"

3. 启动 OpenLDAP . CMD 进入到C:\Program Files\OpenLDAP 下,
        1)、启动OpenLDAP-slapd服务:作用在于开机自动启动该服务项
      slapd install OpenLDAP-slapd “OpenLDAP Directory Service” auto net start OpenLDAP-slapd
      NOTE: the “slapd install” is only needed if you didn’t choose the “create NTservice” option during installation.
      当你完成这一步后,下次开机的时候就自动启动LDAP的服务了,不必再次手动启动。(此步也可以忽略不做!)
        2)、启动OpenLDAP服务器在cmd下运行:slapd -d 1

OpenAdmin客服端: 下载地址: LdapAdmin.exe  。  我下载的版本是LdapAdminExe-w64-1.7.1.zip。功能是没问题,可视化效果不好。

      也可用LdapBrowser ,这个没试过,可能管理会方便得多。

      打开LdapAdmin.exe文件

     LDAP阶段性小结

那么就你可以按照自己的目录设计修改一下压缩包目录中的init.ldif文件,并通过LDAP Admin->Tool->Import …菜单,导入init.ldif,实现top组织的添加。当然,你也可以通过命令窗口导入ldif文件,如:ldapadd -l init.ldif

dn: dc=mycompany,dc=com
objectClass: top
objectClass: dcObject
objectClass: domain
dc: mycompany
userPassword: {CRYPT}$1$Vd5g.O/y$g34U3EEuhAh.2g2q0E1TN/

dn: ou=roles,dc=mycompany,dc=com
objectClass: top
objectClass: organizationalUnit
ou: roles

dn: ou=people,dc=mycompany,dc=com
objectClass: top
objectClass: organizationalUnit
ou: people

dn: cn=Test Users,ou=roles,dc=mycompany,dc=com
objectClass: groupOfUniqueNames
cn: Test Users
uniqueMember: uid=sspecial,ou=people,dc=mycompany,dc=com
uniqueMember: uid=jbloggs,ou=people,dc=mycompany,dc=com

dn: cn=Special Users,ou=roles,dc=mycompany,dc=com
objectClass: groupOfUniqueNames
cn: Special Users
uniqueMember: uid=sspecial,ou=people,dc=mycompany,dc=com

dn: cn=Admin Users,ou=roles,dc=mycompany,dc=com
objectClass: groupOfUniqueNames
cn: Admin Users
uniqueMember: uid=admin,ou=people,dc=mycompany,dc=com

dn: uid=admin,ou=people,dc=mycompany,dc=com
objectClass: person
objectClass: inetOrgPerson
cn: State App
displayName: App Admin
givenName: App
mail: admin@fake.org
sn: Admin
uid: admin
userPassword: adminpassword

dn: uid=jbloggs,ou=people,dc=mycompany,dc=com
objectClass: person
objectClass: inetOrgPerson
cn: Joe Bloggs
displayName: Joe Bloggs
givenName: Joe
mail: jbloggs@fake.org
sn: Bloggs
uid: jbloggs
userPassword: password

dn: uid=sspecial,ou=people,dc=mycompany,dc=com
objectClass: person
objectClass: inetOrgPerson
cn: Super Special
displayName: Super Special
givenName: Super
mail: sspecial@fake.org
sn: Special
uid: sspecial
userPassword: password

dn: ou=sdmc,dc=mycompany,dc=com
objectClass: organizationalUnit
objectClass: top
ou: sdmc

dn: cn=DEMO,ou=sdmc,dc=mycompany,dc=com
gidNumber: 500
objectClass: posixGroup
objectClass: top
cn: DEMO

dn: cn=cai dimin,ou=sdmc,dc=mycompany,dc=com
givenName: cai
sn: dimin
cn: cai dimin
uid: cdimin
userPassword: {MD5}4QrcOUm6Wau+VuBX8g+IPg==
uidNumber: 1000
gidNumber: 500
homeDirectory: /home/users/cdimin
loginShell: /bin/sh
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
mail: 724801286@qq.com

dn: cn=ldapsdmc,ou=sdmc,dc=mycompany,dc=com
cn: ldapsdmc
telephoneNumber: 18682135083
l: sz
objectClass: organizationalRole
objectClass: top
phpldapadmin客户端(版本1.2.3) 
    a.官网下载源码放入WEB目录下:http://phpldapadmin.sourceforge.net/wiki/index.php/Download
    b.安装依赖的扩展gettext ldap这2个扩展
    c.按需配置 源码目录下config/config.php ( 需要取消注释的配置有)

          $servers->setValue('server','name','My LDAP Server');
          $servers->setValue('server','host','10.10.121.8');
          $servers->setValue('server','base',array('dc=mycompany,dc=com'));
          $servers->setValue('login','auth_type','session');
          $servers->setValue('login','bind_id','cn=Manager,dc=mycompany,dc=com');
          $servers->setValue('login','bind_pass','secret');) //空时,每次登录时,要手动输入

 注意:在运行时,由于PHP版本是5.6,不兼容正则的'/e',则preg_replace() ->preg_replace_callback() ,

          $a[$key] = preg_replace('/\\\([0-9A-Fa-f]{2})/e',"''.chr(hexdec('\\1')).''",$rdn);
          $a[$key] = preg_replace_callback('/\\\([0-9A-Fa-f]{2})/',function($r) { return ''.chr(hexdec($r[0])).'' ; },$rdn);

 还有 password_hash()->passwordhash()

公司内部系统连接LDAP服务器:        推荐参考网址:http://www.mzone.cc/article/621.html

spring-ldap-xml文件

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- ldap -->
<bean id="contextSource"
class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://10.10.121.8:389" />
<property name="base" value="dc=mycompany,dc=com" />
<property name="userDn" value="cn=Manager,dc=mycompany,dc=com" />
<property name="password" value="secret" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>

<bean id="userLdapDao" class="com.sdmc.basecms.ldap.UserDaoLdapImpl">
<property name="ldapTemplate" ref="ldapTemplate"/>
</bean>
<!-- end ldap -->
</beans>
Ldap.java

public static Object init(){
ApplicationContext cxt = new ClassPathXmlApplicationContext("spring-ldap.xml");
userLdapDao = (UserDaoLdapImpl)cxt.getBean("userLdapDao");
return userLdapDao ;
}
UserDaoLdapImpl.java

        @SuppressWarnings("unchecked")
public LdapUser getLdapUserByuid(User user) {
// TODO Auto-generated method stub
byte[] bytes=(byte[])DigestUtils.md5( user.getPassword() );
String passwordValue=new String(bytes);
String filter = "(&(uid=" + user.getUsername()+"))";
List<LdapUser> list = ldapTemplate.search("ou=sdmc", filter, new AttributesMapper() { @Override
public Object mapFromAttributes(Attributes attributes) throws NamingException {
LdapUser ldapuser = new LdapUser();
Attribute attr = attributes.get("gidnumber");
if(attr!=null ){
ldapuser.setRoleId( attr.get()+"" );
}attr = attributes.get("userpassword");
if(attr!=null ){
byte[] bytes=(byte[])attr.get();
String passwordValue=new String(bytes);
ldapuser.setPassword( passwordValue );
}
attr = attributes.get("cn");
if(attr!=null ){
ldapuser.setCn( attr.get()+"" );
}attr = attributes.get("mail");
if(attr!=null ){
ldapuser.setMail( attr.get()+"" );
}
return ldapuser;
}
});
if (list.isEmpty()) return null;
return list.get(0);
}


        1-LDAP服务器——已搭建好
        2-phpldapadmin系统——已安装上(能操作LDAP的用户)
        3-应用系统(CMS)——含有自己的用户及角色权限(也能操作到LDAP的用户)

LDAP阶段性小结

        总结:通过phpldapadmin管理LDAP上的用户实体,在CMS登录时,用该用户实体,实现CMS的登录鉴权验证和权限控制。

我的想法是:由于CMS存在一个用户表,表中有些字段在CMS系统操作时是有用的,CMS登录的时候,通过username,先去查询LDAP是否存在该用户,查密码等。 通过ldap分组名(唯一)获取cms中角色的权限。

        1、LDAP存在,且CMS不存在该用户,就在CMS的用户表中插入用户数据,再按照CMS原来流程的登录

        2、LDAP不存在,直接按照CMS原来流程的登录

说明:phpldapadmin系统对用户实体加密默认是MD5代码如下:   base64_encode(pack('H*',md5( password ))); 

 那么用username查出的密码,与CMS加密的密码需比较来验证 :

        String ldapPassword =  new String(Base64.decodeBase64( ldapUser.getPassword().substring(5).getBytes()),"UTF-8") ;
        String loginPassword = CommonUtil.toStringHexTest(   CommonUtil.getMd5( user.getPassword().getBytes())  ) ;
        if( !loginPassword.equals(ldapPassword) ){
               ResultVO<User> resutlVO = new ResultVO<User>();
               resutlVO.setFlag(false);
               resutlVO.setMessage("The Username Or Password On The LDAP Is incorrect!");
               return resutlVO;
       }