SpringBoot实战(六)之使用LDAP验证用户
关于ubuntu16.04服务器安装配置LDAP参考链接为:https://www.howtoing.com/how-to-install-and-configure-openldap-and-phpldapadmin-on-ubuntu-16-04/ 本文主要讲LDAP相关的概念,普及相关知识和相关例子实战。 一、LDAP服务器概念和原理 1. 目录服务目录是一个为查询、浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好象Linux/Unix系统中的文件目录一样。目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。所以目录天生是用来查询的,就好象它的名字一样。 目录服务是由目录数据库和一套访问协议组成的系统。类似以下的信息适合储存在目录中:
LDAP是轻量目录访问协议(Lightweight Directory Access Protocol)的缩写,LDAP是从X.500目录访问协议的基础上发展过来的,目前的版本是v3.0。与LDAP一样提供类似的目录服务软件还有ApacheDS、Active Directory、Red Hat Directory Service?。 ? 2. LDAP特点
? 3. LDAP组织数据的方式?4. 基本概念在浏览LDAP相关文档时经常会遇见一些概念,下面是常见概念的简单解释。 ? 4.1 Entry条目,也叫记录项,是LDAP中最基本的颗粒,就像字典中的词条,或者是数据库中的记录。通常对LDAP的添加、删除、更改、检索都是以条目为基本对象的。
? 4.2 Attribute每个条目都可以有很多属性(Attribute),比如常见的人都有姓名、地址、电话等属性。每个属性都有名称及对应的值,属性值可以有单个、多个,比如你有多个邮箱。 属性不是随便定义的,需要符合一定的规则,而这个规则可以通过schema制定。比如,如果一个entry没有包含在 inetorgperson 这个 schema 中的 LDAP为人员组织机构中常见的对象都设计了属性(比如commonName,surname)。下面有一些常用的别名:
?4.3 ObjectClass对象类是属性的集合,LDAP预想了很多人员组织机构中常见的对象,并将其封装成对象类。比如人员(person)含有姓(sn)、名(cn)、电话(telephoneNumber)、密码(userPassword)等属性,单位职工(organizationalPerson)是人员(person)的继承类,除了上述属性之外还含有职务(title)、邮政编码(postalCode)、通信地址(postalAddress)等属性。 通过对象类可以方便的定义条目类型。每个条目可以直接继承多个对象类,这样就继承了各种属性。如果2个对象类中有相同的属性,则条目继承后只会保留1个属性。对象类同时也规定了哪些属性是基本信息,必须含有(Must 活Required,必要属性):哪些属性是扩展信息,可以含有(May或Optional,可选属性)。 对象类有三种类型:结构类型(Structural)、抽象类型(Abstract)和辅助类型(Auxiliary)。结构类型是最基本的类型,它规定了对象实体的基本属性,每个条目属于且仅属于一个结构型对象类。抽象类型可以是结构类型或其他抽象类型父类,它将对象属性中共性的部分组织在一起,称为其他类的模板,条目不能直接集成抽象型对象类。辅助类型规定了对象实体的扩展属性。每个条目至少有一个结构性对象类。 对象类本身是可以相互继承的,所以对象类的根类是top抽象型对象类。以常用的人员类型为例,他们的继承关系: 下面是inetOrgPerson对象类的在schema中的定义,可以清楚的看到它的父类SUB和可选属性MAY、必要属性MUST(继承自organizationalPerson),关于各属性的语法则在schema中的attributetype定义。
?4.4 Schema对象类(ObjectClass)、属性类型(AttributeType)、语法(Syntax)分别约定了条目、属性、值,他们之间的关系如下图所示。所以这些构成了模式(Schema)——对象类的集合。条目数据在导入时通常需要接受模式检查,它确保了目录中所有的条目数据结构都是一致的。 schema(一般在 ?4.5 backend & databaseldap的后台进程slapd接收、响应请求,但实际存储数据、获取数据的操作是由Backends做的,而数据是存放在database中,所以你可以看到往往你可以看到
另外 ?4.6 TLS & SASL分布式LDAP 是以明文的格式通过网络来发送信息的,包括client访问ldap的密码(当然一般密码已然是二进制的),SSL/TLS 的加密协议就是来保证数据传送的保密性和完整性。 SASL (Simple Authenticaion and Security Layer)简单身份验证安全框架,它能够实现openldap客户端到服务端的用户验证,也是 Kerveros V5是里面最复杂的一种,使用GSSAPI机制,必须配置完整的Kerberos V5安全系统,密码不再存放在目录服务器中,每一个dn与Kerberos数据库的主体对应。DIGEST-MD5稍微简单一点,密码通过saslpasswd2生成放在sasldb数据库中,或者将明文hash存到LDAP dn的userPassword中,每一个authid映射成目录服务器的dn,常和SSL配合使用。参考将 LDAP 客户端配置为使用安全性 EXTERNAL一般用于初始化添加schema时使用,如 ?4.7 LDIFLDIF(LDAP Data Interchange Format,数据交换格式)是LDAP数据库信息的一种文本格式,用于数据的导入导出,每行都是“属性: 值”对,见?openldap ldif格式示例 OpenLDAP(2.4.3x)服务器安装配置方法见这里。 ? 二、实例讲解 1.maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0</> groupId>org.springframeworkartifactId>gs-authenticating-ldapversion>0.1.0parent> >org.springframework.boot>spring-boot-starter-parent>1.5.8.RELEASEpropertiesjava.version>1.8java.version<!-- tag::security[] --> dependencies> dependency>spring-boot-starter-web>spring-boot-starter-security>org.springframework.ldap>spring-ldap-core>org.springframework.security>spring-security-ldap>com.unboundid>unboundid-ldapsdk>spring-boot-starter-testscope>test>spring-security-test end::security[] --> buildplugins> plugin> >spring-boot-maven-plugin> project> ? 2.编写WEB安全配置 WebSecurityConfig.java package hello; import org.springframework.context.annotation.Configuration; org.springframework.security.authentication.encoding.LdapShaPasswordEncoder; org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; org.springframework.security.config.annotation.web.builders.HttpSecurity; org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().fullyAuthenticated() .and() .formLogin(); } @Override void configure(AuthenticationManagerBuilder auth) Exception { auth .ldapAuthentication() .userDnPatterns("uid={0},ou=people") .groupSearchBase("ou=groups") .contextSource() .url("ldap://localhost:8389/dc=springframework,dc=org") .and() .passwordCompare() .passwordEncoder(new LdapShaPasswordEncoder()) .passwordAttribute("userPassword"); } } ? 3.编写启动类 org.springframework.boot.SpringApplication; org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication class Application { static void main(String[] args) { SpringApplication.run(Application.,args); } } ? 4.对应的配置文件 test-server.ldif dn: dc=springframework,dc=org objectclass: top objectclass: domain objectclass: extensibleObject dc: springframework dn: ou=groups,dc=springframework,1)">org objectclass: top objectclass: organizationalUnit ou: groups dn: ou=subgroups,ou=groups,1)">org objectclass: top objectclass: organizationalUnit ou: subgroups dn: ou=people,1)">org objectclass: top objectclass: organizationalUnit ou: people dn: ou=space cadets,1)">org objectclass: top objectclass: organizationalUnit ou: space cadets dn: ou="quoted people",dc=org objectclass: top objectclass: organizationalUnit ou: "quoted people" dn: ou=otherpeople,1)">org objectclass: top objectclass: organizationalUnit ou: otherpeople dn: uid=ben,1)">org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Ben Alex sn: Alex uid: ben userPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ= dn: uid=bob,1)">org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Bob Hamilton sn: Hamilton uid: bob userPassword: bobspassword dn: uid=joe,ou=otherpeople,1)">org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Joe Smeth sn: Smeth uid: joe userPassword: joespassword dn: cn=mouse,jerry,1)">org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Mouse,Jerry sn: Mouse uid: jerry userPassword: jerryspassword dn: cn=slash/guy,1)">org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: slash/guy sn: Slash uid: slashguy userPassword: slashguyspassword dn: cn=quote"guy,ou="quoted people",1)">objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: quote"guy sn: Quote uid: quoteguy userPassword: quoteguyspassword dn: uid=space cadet,ou=space cadets,1)">org objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson cn: Space Cadet sn: Cadet uid: space cadet userPassword: spacecadetspassword dn: cn=developers,1)">org objectclass: top objectclass: groupOfUniqueNames cn: developers ou: developer uniqueMember: uid=ben,1)">org uniqueMember: uid=bob,1)">org dn: cn=managers,1)">org objectclass: top objectclass: groupOfUniqueNames cn: managers ou: manager uniqueMember: uid=ben,1)">org uniqueMember: cn=mouse,1)">org dn: cn=submanagers,ou=subgroups,1)">org objectclass: top objectclass: groupOfUniqueNames cn: submanagers ou: submanager uniqueMember: uid=ben,dc=org ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |