背景:

基于目前存在多套员工使用的日常工作子系统,现状为各系统各自有一套用户体系,员工需要记住各系统的用户名、密码等信息,还需要登录多个系统,重复工作量颇多。统一用户认证组件将用户名、密码等信息统一存储与管理,对各子系统提供统一认证接口。二期引入OpenLDAP,解决Jira、Git、Hue、CM、SVN等国外常用的开源软件不支持统一认证,而修改源码对接CUAS又成本过高的痛点。

名词解析:

Centraly User Auth Service(集中用户认证服务)以下简称CUAS;

AccessToken:访问码,默认有效期为24小时,当用户重新登录后,授权码过期。

Cectoken:跳转码,默认有效期为5分钟,当系统之间互相跳转时带上该token;

CuasToken:类似于网银的UKey,采用GoogleAuthenticator算法,30S刷新一次;

LDAP:轻量级目录访问协议,是一种广泛被遵循的协议。

二次认证:

采用GoogleAuthenticator算法,二维码生成算法结构otpauth://totp/masg?secret=3456ABCDEFGIDM。需要注意提供密钥刷新接口,当用户密钥泄露后可生成新密钥。

架构图:







关键数据库表:

用户表:T_USER

用户信息操作日志(新增、修改、修改密码): T_USER_LOG

用户密钥表(二次验证用): T_USER_SECRETKEY

用户认证日志:T_USER_AUTHLOG

Access Token表:T_USER_ACCESSTOKEN

CEC Token日志表(获取、验证):T_USER_CECTOKEN_LOG

Redis结构设计:

Redis CEC Token结构:Redis Hash结构,key=CuasService:cectoken:${cecToken}

LDAP设计

一级目录节点为dc=com,二级目录节点为dc=mzsg,不可更改;

三级目录节点定义:

用户信息节点:ou=users,存储用户及账号信息

组织信息节点:ou=organizations,存放组织信息

群组信息节点:ou=groups,存放群组信息

结构如下图:

用户信息

1.所有用户都存储在ou=users下

2.用户以uid来标识,uid为用户姓名拼音全拼,有重复时加数字

3.使用业界标准的inetOrgPerson作为基类,加入displayName、status、secAuth、companyCode、departmentCode等扩展;

组织信息

1.所有组织都存储在ou=organizations下

2.使用业界标准的organizationalUnit对象类

群组信息

1.所有群组都存储在ou=groups下

2.使用业界标准的posixGroup对象类

用户权限设计

用户组:

一个用户可以属于一到多个用户组,当用户组编码为空时为默认用户组。举例:小M是jira的管理员,在jenkins是普通用户,则小M的群组信息如下:

jira-administrators JIRA管理员

jenkins-users Jenkins普通用户

如果用户未加入jira的任何群组(jira-sofeware-users,jira-administrators),则此时用户无jira权限,无法登陆jira。

用户组设计

不是所有的第三方软件都支持userGroups的meberUid关联查找,所以还需要在用户schema上增加userGroups以对这种情况进行支持,用属性会让搜索语句变得更加简洁,当然也会增加同步维护的复杂度。

LDAP同步设计

由于需要拿到密码同步给LDAP服务器,所以用户密码需要可逆加密存储,可采用AES等对称加密。LDAP同步采用异步方式同步,即将用户修改日志T_USER_LOG按严格有序同步给LDAP服务器,如同步失败则后续跳过此用户的记录,直到问题解决。

LDAP同步编码

我用的是novell的jldap包,相比一般的JDBC操作,ldap的同步对字段要求很严格,属性值不能为空值或null值,在操作前需要先进行判断,要自行区分对属性的增、删、改操作,在增删改之前要先检查记录或属性是否存在。

OpenLDAP自定义结构

这部分网上资料较少,而且互相抄袭也比较严格,缺少一些较权威和详细的操作过程。这里鸣筝给大家一个亲测可行的步骤

1、编写schema

/etc/openldap/schema/local.schema

参考扩展mzsgCnblogsPerson结构

attributetype ( 1.1.2.1.2 NAME 'companyCode'
DESC 'company code'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.1.2.1.3 NAME 'departmentCode'
DESC 'department code'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.1.2.1.4 NAME 'status'
DESC 'status 1 means normal 0 means login forbid'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.1.2.1.5 NAME 'birthday'
DESC 'birthday'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.1.2.1.6 NAME 'phone'
DESC 'phone'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.1.2.1.7 NAME 'sex'
DESC 'sex 0 means unknow 1 means male 2 means female'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.1.2.1.8 NAME 'certType'
DESC 'cert type'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.1.2.1.9 NAME 'employeeNum'
DESC 'employee number'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.1.2.1.10 NAME 'certId'
DESC 'certId'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.1.2.1.11 NAME 'secAuth'
DESC 'second auth switch 0 means on 1 means off'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.1.2.1.12 NAME 'cnName'
DESC 'cn name'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
SINGLE-VALUE )
attributetype ( 1.1.2.1.13 NAME 'userGroups'
DESC 'user groups'
EQUALITY caseExactIA5Match
SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26)
objectclass ( 1.1.2.2.2 NAME 'mzsgCnblogsPerson'
DESC 'https://www.cnblogs.com/mzsg/ person'
SUP inetOrgPerson
MUST ( status )
MAY ( companyCode $ departmentCode $ status $ birthday $ phone $ sex $ certType $ employeeNum $

2、修改sladp.conf,增加对local.schema的include

include /etc/openldap/schema/local.schema

3、编译

在/tmp下建立myConf.conf文件,添加所需依赖

include /etc/openldap/schema/core.schema

include /etc/openldap/schema/collective.schema

include /etc/openldap/schema/corba.schema

include /etc/openldap/schema/cosine.schema

include /etc/openldap/schema/duaconf.schema

include /etc/openldap/schema/inetorgperson.schema

include /etc/openldap/schema/java.schema

include /etc/openldap/schema/misc.schema

include /etc/openldap/schema/nis.schema

include /etc/openldap/schema/openldap.schema

include /etc/openldap/schema/pmi.schema

include /etc/openldap/schema/ppolicy.schema

include /etc/openldap/schema/local.schema

/etc/init.d/httpd restart

注:如果/tmp下有cn=config,则先删除。

之后运行,slapcat -f /tmp/myConf.conf -F /tmp/ -n0

把生成的的cn=config/cn=schema目录下对应的ldif文件去替换ldap中原先cn=config/cn=schema中的ldif文件。

位置在:/etc/ldap/slapd.d/cn=config/cn=schema

注意有时phpLdapAdmin会显示自定义Schema报错,JXplorer能正常支持

cd /etc/openldap/slapd.d/cn=config/cn=schema

rm -rf *

cp /tmp/cn=config/cn=schema/* .

chmod 777 *

注意,要先删除,再加,否则容易有重复定义的问题

接入LDAP

在git、svn、jenkins、jira、confluence、Kibana接入LDAP的过程中,注意事项有

在接入git之前必须保证用户信息中的email信息齐全并与历史git中的用户的邮箱一致,否则需做相应修改,相同用户名邮箱名不同的记录用户名会被自动修改,我就在这里花了挺长的时间。SVN接入时,使用SASL进行用户验证,svn的用户管理还是要在authz中管理,相当于加SVN的用户需要在CUAS和SVN的服务器authz中分别新增。

几点思考

1、为什么不去掉Mysql,改为使用OpenLDAP存储?

OpenLDAP更适合写少读多的场景,OpenLDAP不支持事务。最为重要的是我们在关系型数据库上具有丰富的经验,万一在OpenLDAP中的数据被玩坏了,我们可以轻松地从Mysql中同步恢复过来。

2、为什么LDAP服务器用的是OpenLDAP?

LDAP比较知名的开源实现是OpenLDAP和ApacheDS,两者都是优秀的产品。相比之下,前者在网络上的文档资料更多,也更轻量。

3、为什么不采用CAS而自行建设CUAS?

由于公司内部存在不少遗留系统,如果引入CAS需进行大量定制和裁减以减少各系统的集成难度和减少推行压力,而CUAS灵活定制化后结合公司内部的研发框架,可大大减少集成复杂度。

4、LDAP设计为什么要采用用户、组织、群组指定DN,为什么用户不挂在组织下形成严格的树状结构?

严格的树状结构会导致组织和用户的维护严重耦合,另外扁平的结构更方便条件查找。

效果

各业务系统管理后台通过统一门户进行统一认证后进行单点登陆。git、svn、jenkins、jira、confluence、Kibana以ldap进行统一认证。员工离职只需要在统一门户进行操作,所有系统均不可登录。员工入职通过统一门户进行录入可同步给各业务系统并分配最低权限(实施中),通过用户组,由各系统自行映射用户组对应的权限列表。该实现方式的不足是CUAS只管到用户组,权限仍散落到各业务系统各自管理。

好了,如果你对企业统一用户认证系统建设或LDAP有其它疑问,可在评论区讨论。如果你有关于企业统一用户认证系统建设或LDAP的开发、培训或咨询需求,也请站内信联系我。

统一用户认证系统CUAS实现要点的更多相关文章

  1. 基于DDD + SD.Framework实现的统一身份认证系统

    项目地址 http://git.oschina.net/lishilei0523/ShSoft.UAC 项目说明 本项目开发的目的有三: 1.作为一个使用SD.Framework框架开发的项目样板 2 ...

  2. django用户认证系统——拓展 User 模型

    Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等个人信息.对于 Django 内置的 User 模型, 仅包含以下一些主要的属性: username,即用户名 ...

  3. “Django用户认证系统”学习资料收集

    首推追梦人物——Django用户认证系统 待续……

  4. 中国科学技术大学统一身份认证系统CAS

    CAS | Apereohttps://www.apereo.org/projects/cas 中国科学技术大学统一身份认证系统https://passport.ustc.edu.cn/login?s ...

  5. Django Authentication 用户认证系统

    一. Django的认证系统 Django自带一个用户认证系统,用于处理用户账户.群组.许可和基于cookie的用户会话. 1.1 概览 Django的认证系统包含了身份验证和权限管理两部分.简单地说 ...

  6. django用户认证系统——重置密码7

    当用户不小心忘记了密码时,网站需要提供让用户找回账户密码的功能.在示例项目中,我们将发送一封含有重置用户密码链接的邮件到用户注册时的邮箱,用户点击收到的链接就可以重置他的密码,下面是具体做法. 发送邮 ...

  7. django用户认证系统——修改密码6

    再此之前我们已经完成了用户登录.注册.注销等功能,接下来让我们继续为用户提供修改密码的功能.该功能 Django 的 auth 应用也已经为我们提供,过程几乎和之前的登录功能完全一样. 编写修改密码模 ...

  8. django用户认证系统——登录4

    用户已经能够在我们的网站注册了,注册就是为了登录,接下来我们为用户提供登录功能.和注册不同的是,Django 已经为我们写好了登录功能的全部代码,我们不必像之前处理注册流程那样费劲了.只需几分钟的简单 ...

  9. django用户认证系统——拓展 User 模型2

    Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等个人信息.对于 Django 内置的 User 模型, 仅包含以下一些主要的属性: username,即用户名 ...

随机推荐

  1. [Java复习] JVM

    Part1:Java类加载机制:类加载器,类加载机制,双亲委派模型 1. Java 类加载过程? 类加载过程即是指JVM虚拟机把.class文件中类信息加载进内存,并进行解析生成对应的class对象的 ...

  2. [maven]maven插件 tomcat7-maven-plugin 的使用

    使用 tomcat7-maven-plugin,可以将tomcat内嵌到web项目中,直接运行webapp项目. 第一步.pom.xml的配置: <build> <plugins&g ...

  3. String字符串的截取

    根据某个字段将字符串分割成绩部分 String str = "string number one 1/9/0"; //将字符串由/ 截取成绩部分 String[] strs = s ...

  4. MIGO 收货

    ls_code-gm_code = '01'. 01 - MB01 - Goods Receipts for Purchase Order 02 - MB31 - Goods Receipts for ...

  5. unity3d 嵌入iOS的 In App Purchase 应用程序内购买

    Unity做东西是快,但是有些功能是需要额外开发的,比如 IAP (In App Purchase,应用程序内购买) 还好unity提供了灵活的扩展功能,允许嵌入原生代码来做一些unity未实现的功能 ...

  6. 用例建模 Use Case Modeling

    用例建模 以您的工程实践项目为例,在理解项目需求的基础上进行用例建模,抽取Abstract use case,画出用例图,并确定每一个用例的范围High level use case,对关键用例进一步 ...

  7. MapReduce程序的开发过程

    1. 在linux(虚拟机环境)下安装hadoop2.8.3 1.1 安装JDK环境 1.2 安装hadoop 1.3 进行配置:core-site.xml,hdfs-site.xml设置 1.4 初 ...

  8. Cocos Creator Android打包 apk

    这一篇讲的是用 Cocos Creator 编译器打包 Android APP 的时候遇到的一些问题,虽然说打包的过程不是很复杂,但是在其中还是会遇到各式各样的坑. 我们将项目用CCC(Cocos C ...

  9. Quartz任务调度系统,克隆表达式

    Quartz任务调度系统,克隆表达式 (1).克隆表达式可以包括7个字段:秒.分.小时.月内日期.月.周内日期.年(可选字段) (2).特殊字符: 一.反斜线(/)字符表示增量."5/15& ...

  10. 推荐一个好用的免费开源的笔记本软件CherryTree

    我是一个好奇心很强的人,对未知的事物总有一种想要追根究底的冲动.多年以来,我学了很多东西,也学的很杂,积累了很多领域的知识.但不得不承认,人的记忆力很有限,学的越多忘的就越多.很久以前我就在想,怎么样 ...