背景:

基于目前存在多套员工使用的日常工作子系统,现状为各系统各自有一套用户体系,员工需要记住各系统的用户名、密码等信息,还需要登录多个系统,重复工作量颇多。统一用户认证组件将用户名、密码等信息统一存储与管理,对各子系统提供统一认证接口。二期引入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. Qt编写自定义控件26-平铺背景控件

    一.前言 平铺背景控件,主要的应用场景是作为画布出现,黑白相间的背景图,然后上面可以放置图片图形等,使得看起来更美观,比如PS软件新建图层以后的背景,FireWorks软件新建画布以后的透明背景,IC ...

  2. 数学建模python matlab 编程(疾病传播模型)

    例12:一只游船上有800(1000)人,一名游客不慎患传染病,12(10)小时后有3人发病,由于船上不能及时隔离,问经过60(30)小时,72小时,患此病的人数.(与人口模型和Logistic模型类 ...

  3. golang的下载与安装

    golang的官网可能由于政策原因登陆不上. 所以可以到Go语言中文网下载:https://studygolang.com/dl 我下载的是go1.10.3.windows-amd64.msi安装包, ...

  4. wp-query调用前几篇文章的方法

    ---恢复内容开始--- 利用强大的wp-query函数调用指定分类下的前几篇文章,下面的代码表示调用的是分类ID4下的前两篇文章. <?php $cunt_wenzhen = array('c ...

  5. Flutter dio伪造请求头获取数据

    在很多时候,后端为了安全都会有一些请求头的限制,只有请求头对了,才能正确返回数据.这虽然限制了一些人恶意请求数据,但是对于我们聪明的程序员来说,就是形同虚设.下面就以极客时间为例,讲一下通过伪造请求头 ...

  6. Flutter安卓客户端打包

    想要安装到手机上,必须要进行打包,因为没有苹果手机,所以只能打包Android客户端的apk. 检查 App的配置 查看默认应用程序清单文件(位于/android/app/src/main/中的And ...

  7. 攻防世界WEB新手练习

    0x01 view_source 0x02 get_post 这道题就是最基础的get和post请求的发送 flag:cyberpeace{b1e763710ff23f2acf16c2358d3132 ...

  8. 【MOOC课程学习记录】程序设计与算法(一)C语言程序设计

    课程结课了,把做的习题都记录一下,告诉自己多少学了点东西,也能给自己一点鼓励. ps:题目都在cxsjsxmooc.openjudge.cn上能看到,参考答案在差不多结课的时候也会在mooc上放出来. ...

  9. jstack使用

    top -p 22072 -H  -p:查看某个进程 -H列出所有的线程 printf '%x' 22398 (16进制线程号) sudo -u tomcat jstack 22072 | grep ...

  10. 2019SDN第四次作业

    一.配置java环境 输入命令sudo gedit ~/.bashrc 添加如下内容 二.启动并安装插件 cd distribution-karaf-0.4.4-Beryllium-SR4/bin/ ...