首页 > 其他分享 >LDAP统一认证服务解决方案(转)

LDAP统一认证服务解决方案(转)

时间:2024-09-02 10:49:54浏览次数:12  
标签:get 解决方案 LDAP 认证 attrs ldap import ou

原文链接:https://javaforall.cn/126568.html

LDAP是什么

  • 首先LDAP是一种通讯协议,LDAP支持TCP/IP。协议就是标准,并且是抽象的。在这套标准下,AD(Active Directory)是微软出的一套实现。 那AD是什么呢?暂且把它理解成是个数据库。也有很多人直接把LDAP说成数据库(可以把LDAP理解成存储数据的数据库)。像是其他数据库一样,LDAP也是有client端和server端。server端是用来存放资源,client端用来操作增删改查等操作。
  • 而我们通常说的LDAP是指运行这个数据库的服务器。
  • 可以简单理解AD =LDAP服务器+LDAP应用。

LDAP与数据库有什么区别?

 
LDAP是一个数据库,但是又不是一个数据库。说他是数据库,因为他是一个数据存储的东西。但是说他不是数据库,是因为他的作用没有数据库这么强大,而是一个目录。
为了理解,给一个例子就是电话簿(黄页)。我们用电话簿的目的是为了查找某个公司的电话,在这个电话簿中附带了一些这个公司的基本信息,比如地址,经营范围,联系方式等。
其实这个例子就是一个LDAP在现实生活中的表现。电话簿的组织结构是一条一条的信息组成,信息按照行业,类比进行了分类。每条记录都分成了若干的区域,其中涵盖了我们要的信息。这就是一个Directory。一个树状的结构,每个叶子都是由一条一条的分成若干区域的记录。LDAP就是这么一个东西。
从概念上说,LDAP分成了DN, OU等。OU就是一个树,DN就可以理解为是叶子,叶子还可以有更小的叶子。但是LDAP最大的分层按照IBM的文档是4层。
还是上面这个例子,电话簿由电话公司进行维护,因此写是由他们去写,去组织。写完了,组织好了,就完成了,以后再写,再组织的次数是有限的。而其作用是为了查找。LDAP也是类似,目的不是为了写,主要是为了查找。这就回答了有同志问,有人要写有人要读的并发怎么解决的问题。LDAP的用途不是针对这个来设计的,如果你有这样的需求,解决办法就应该是数据库,而不是LDAP。这就是另外一个例子,Access和SQL Server。Access就是一个数据库产品,但是主要用于家庭,功能和性能都比较弱。SQL Server就是一个专业的数据库系统,功能强大。LDAP是一个轻量级的产品,主要目的是为了查,因此在架构和优化主要是针对读,而不是写。但并不是说LDAP不能满足,只是说强项不在这里。
LDAP作为一个统一认证的解决方案,主要的优点就在能够快速响应用户的查找需求。比如用户的认证,这可能会有大量的并发。如果用数据库来实现,由于数据库结构分成了各个表,要满足认证这个非常简单的需求,每次都需要去搜索数据库,合成过滤,效率慢也没有好处。虽然可以有Cache,但是还是有点浪费。LDAP就是一张表,只需要用户名和口令,加上一些其他的东西,非常简单。从效率和结构上都可以满足认证的需求。这就是为什么LDAP成为现在很人们的统一认证的解决方案的优势所在。
当然LDAP也有数据写入的借口,是可以满足录入的要求的。这里就不多说了。

LDAP这种数据库有什么特殊的呢?

我们知道,像MySQL数据库,数据都是按记录一条条记录存在表中。而LDAP数据库,是树结构的,数据存储在叶子节点上。看看下面的比喻:

假设你要树上的一个苹果(一条记录),你怎么告诉园丁它的位置呢?
当然首先要说明是哪一棵树(dc,相当于MYSQL的DB),
然后是从树根到那个苹果所经过的所有“分叉”(ou)
,最后就是这个苹果的名字(uid,相当于MySQL表主键id)。
好了!这时我们可以清晰的指明这个苹果的位置了,就是那棵“歪脖树
”的东边那个分叉上的靠西边那个分叉的再靠北边的分叉上的半红半绿的……,晕了!你直接爬上去吧!

就这样就可以描述清楚“树结构”上的一条记录了。 说一下LDAP里如何定义一个记录的位置吧。

树(dc=ljheee)
分叉(ou=bei,ou=xi,ou= dong)
苹果(cn=redApple)

好了,redApple的位置出来了: dn:cn=honglv,ou=bei,ou=xi,ou=dong,dc=ljheee 其中dn标识一条记录,描述了一条数据的详细路径。 咦!有人疑问,为什么ou会有多个值?你想想,从树根到达苹果的位置,可能要经过好几个树杈,所有ou可能有多个值。关于dn后面一长串,分别是cn,ou,dc;中间用逗号隔开。

总结一下LDAP树形数据库如下:
dn :一条记录的详细位置
dc :一条记录所属区域    (哪一颗树)
ou :一条记录所属组织    (哪一个分支)
cn/uid:一条记录的名字/ID   (哪一个苹果名字)
LDAP目录树的最顶部就是根,也就是所谓的“基准DN"。
  • 为什么要用LDAP目录树来存储数据,用MySQL不行吗,为什么非要搞出一个树形的数据库呢?
  • 这是因为用树形结构存储数据,查询效率更高(具体为什么,可以看一下关系型数据库索引的实现原理——B树/B+树)。在某些特定的场景下,使用树形数据库更理想。比如:需要储存大量的数据,而且数据不是经常更改,需要很快速的查找。
  • 把它与传统的关系型数据库相比,LDAP除了快速查找的特点,它还有很多的运用场景,比如域验证等。

LDAP场景描述

一、多平台认证的烦恼

小明的公司有很多IT系统, 比如邮箱、SVN、Jenkins , JIRA,VPN, WIFI… 等等 。

新人入职时需要在每个系统中申请一遍账号,每个系统对用户名和密码的要求还不一样, 实在是烦人。

这还不算, 按照公司的策略, 这些密码每隔三个月还得更改一次,每次都是一次大折腾。

离职的时候, 各个账号又都得删除一遍,太折磨了。

能不能让这些系统用同一套用户名和密码呢? 申请一次,到处使用!

“嗯,这其实是一个用户统一认证的问题” 小明做了一个总结。

怎么去实现? 当然是开发一套系统了, 关键是要把账号统一起来用Mysql 数据库来保管, 然后用自己擅长的SpringMVC对外提供JSON接口, 别的系统比如SVN想做用户认证的时候,调用一下这个接口,把用户名和密码传过来,系统就会判断认证是否成功。

在这里插入图片描述 在这里插入图片描述

被这么一个美好的前景激励着,小明像打了鸡血,充满激情地、迅速地把这个系统开发出来了。

二、用户中心的推广

他先找了SVN的管理员,结果栽了跟头,人家根本不买账,理由很简单: “你这个系统稳定性、性能怎么样? 还有,你这接口是自己定义的,也不是业界标准,我甚至得开发代码和你做集成, 太麻烦。 对了, 你怎么不用LDAP啊?”

LDAP ? 这是什么鬼? 小明没放在心上, 又去找邮箱和VPN的负责人, 都被残忍地拒绝了, 甚至连理由都一样。

最后的希望集中在Jenkins身上, 管理Jenkins的是自己的哥们张大胖, 中午吃饭的时候小明向基友哭诉了自己的悲惨遭遇,希望能博得一点同情。

“我觉得你的想法很好啊,我们就缺你这样的实干家, 你说说接口是什么样的?” 大胖路见不平,决定为好基友两肋插刀。

“其实我这里提供了一个HTTP+JSON的接口, 你的Jenkins调用一下就行了” 小明满怀期望。

“这个… 虽然我没有仔细研究过, 但是Jenkins 好像只支持自定义的用户认证,还没有LDAP。” 大胖的刀还没拔出来就放回去了。

看来推广又要失败了。

干嘛不用LDAP?

“这个LDAP是什么东西,你们的系统为什么都要支持它?” 小明愤愤不平地问道。

“LDAP是Lightweight Directory Access Protocol,即轻量级目录访问协议, 用这个协议可以访问提供目录服务的产品,例如OpenLDAP。”

“目录服务?”

“对, 比如公司有个员工列表名单, 对于一个员工,你能查到他的电话,工位,部门等各种信息, 这就是一个目录啊。”

“听起来很适合保存一个公司员工的账号和密码啊” 小明说。

“是啊,这个目录服务啊,存储数据的方式有点特殊,完全不像我们熟知的关系数据库, 数据都在表中,一行一行的,一目了然,这个OpenLDAP是以树的方式存储的。 比如一个人的信息是这样的:

在这里插入图片描述 在这里插入图片描述

小明说:“ 有点古怪,不过这很像文件系统的目录树, 每个目录都有属性,可以存储信息,比如用户名和秘密,但是查询的时候还得一层一层的来,多麻烦, 为啥不用关系型数据库,直接一个select 不就出来了 ”

张大胖说: “我对LDAP研究不深, 但是我知道LDAP速度快, 非常快,比当今最快的数据库还要快。“

“怎么可能,现在的关系数据库多强悍啊。”

其实LDAP主要的应用场景是查询多而修改极少,查询和修改的比率是10:1 甚至更高, 那就充分发挥LDAP的优势了,因为没有事务处理,那数据库的速度可是比不上。 还有LDAP能存储海量的数据,还可以轻松地在各个系统之间复制,可用性超高。 ”

小明想想确实是这样,公司员工信息变化本来就很少,我们把用户名密码存进去, 三个月才改一次, 查询的操作远远高于修改,如果LDAP专注于优化查询,又没有事务处理, 就像一个缓存一样, 肯定要更快了, 怪不得很多软件都支持LDAP做用户认证,这是个重要原因啊。

小明有点沮丧,觉得自己在没有充分调查研究的情况下,又造了一个轮子。

既然如此,那就搭建一个支持LDAP的目录服务器吧, 小明这一次吸取了教训,先说服了领导,在领导的支持下,进行了跨部门的沟通,经过艰苦的努力,各个系统终于搞成了统一认证, 现在的结构是这样的:

在这里插入图片描述 在这里插入图片描述

小明的努力没有白费, 除了学到技术外,还得到了公司的认可,年底的时候给他发了一个领导力的奖,奖励他勇于走出自己的工作岗位、跨部门的与同事沟通,用自己的专业能力带来大家完成了用户的统一认证,极大提高了工作的效率。

Spring LDAP的使用

  • Spring LDAP,是Spring的一个组件,实现对LDAP的操作。
  • 在编程操作MySQL时,我们除了用JDBC,可能都会选用一些框架,比如JbdcTemplate。
  • JdbcTemplate的实现是通过传入sql语句和RowMapper,query返回目标列表,或是传入sql和参数,执行update方法。JdbcTemplate的优点是简化了与数据库连接的代码,以及避免了一些常见的错误。
  • 同样的,Spring LDAP框架也提供了类似的特性——LdapTemplate。
  • 优点都是相通的,Spring LdapTemplate的优点是简化了与LDAP交互的代码。
  • 按之前Spring配置JavaBean的方式,在xml文件配置LdapTemplate及其属性值即可,本文将演示使用Springboot 用Java代码的方式定义LdapTemplate,完成Spring ldap连接数据库服务及进行相关操作。

首先引入LDAP依赖

 
<!-- spring ldapTemplate操作 -->
        <dependency>
            <groupId>com.sun</groupId>
            <artifactId>ldapbp</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.ldap</groupId>
            <artifactId>spring-ldap-core</artifactId>
            <version>2.3.2.RELEASE</version>
        </dependency>
  • 先介绍一些Spring-ldap,因为网上有很多教程,在给出的工程依赖中有用spring-ldap的,也有spring-ldap-core的,而且还有版本问题。笔者使用目前最新的spring-ldap-2.3.2.RELEASE。推荐直接使用,这个最新版本。
  • spring-ldap框架,是Spring集成ldap操作的总和,包含spring-ldap-core,spring-ldap-core-tiger,spring-ldap-ldif-core,spring-ldap-odm等jar,而通常我们在工程中只需要引入spring-ldap-core即可,它提供了绝大部分功能。而且截至目前,spring-ldap的<version>2.3.2.RELEASE</version>不在maven的中央仓库,不好获取。但spring-ldap-core在。
  • 另外,Spring LDAP 2.0对jdk版本要求是1.6,并且开始支持ODM,并后来引入Spring ldap pool连接池。
  • 据本人尝试,这些版本之间,变化差异很大。在新版本中可能有些关键的核心类,都会被移动到不同的package下;一些老版本完成的愚钝功能,可能在新版本中有了更好的实现或支持,所以在新版本中,一些“愚钝”实现可能会被移除。
  • 比如LdapTemplate,原先在org.springframework.ldap包,在最新版本被移至core包。在spring-ldap-core的<version>2.0.2.RELEASE</version>版本中支持类似于JPA方式的LdapRepository,但在2.3.2最新版本中,完全被移除,但是新版本增强的LdapTemplate,使得LdapTemplate功能更强大,可以完全替代LdapRepository。

下面是用Java代码的方式定义LdapTemplate,完成用Spring ldap连接LDAP服务器

 
import com.xxx.xxx.sim.ldap.constants.LdapConstans;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.pool.factory.PoolingContextSource;
import org.springframework.ldap.pool.validation.DefaultDirContextValidator;
import org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy;
import java.util.HashMap;
import java.util.Map;

/**
 * LDAP 的自动配置类
 *
 * 完成连接 及LdapTemplate生成
 */
@Configuration
public class LdapConfiguration {

    private LdapTemplate ldapTemplate;

    @Bean
    public LdapContextSource contextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        Map<String, Object> config = new HashMap();

        contextSource.setUrl(LdapConstans.url);
        contextSource.setBase(LdapConstans.BASE_DC);
        contextSource.setUserDn(LdapConstans.username);
        contextSource.setPassword(LdapConstans.password);

        //  解决 乱码 的关键一句
        config.put("java.naming.ldap.attributes.binary", "objectGUID");

        contextSource.setPooled(true);
        contextSource.setBaseEnvironmentProperties(config);
        return contextSource;
    }
 
    @Bean
    public LdapTemplate ldapTemplate() {
        if (null == ldapTemplate)
            ldapTemplate = new LdapTemplate(contextSource());
        return ldapTemplate;
    }

}

 

  • 完成LdapTemplate的bean定义,是最关键的一步。因为后续的操作,对于LDAP目录树的CRUD操作,全都靠它完成。
  • 通过上面的代码,在IOC容器完成bean的定义,我们在外部就可以注入使用LdapTemplate了。

下面给出用LdapTemplate完成CRUD功能:

 
import com.xxx.xxx.sim.ldap.attribute.LdapDeptAttributeMapper;
import com.xxx.xxx.ldap.attribute.LdapUserAttributeMapper;
import com.xxx.xxx.xxx.ldap.module.dto.LdapUser;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import java.util.List;

public class ConfigTest extends BaseTest {
    @Autowired
    private LdapTemplate ldapTemplate;

    /**
     * 获取所有 internal人员
     * ou=Internal,ou=People
     */
    @Test
    public void listUsers(){
        AndFilter filter = new AndFilter();
        filter.and(new EqualsFilter("objectClass", "person"));

        //查询所有内部人员
        List<LdapUser> users = ldapTemplate.search("ou=internal,ou=People", filter.encode(), new LdapUserAttributeMapper());
        for (LdapUser user: users ) {
            System.out.println(user);
        }

//        Assert.assertEquals(123, users.size());
    }

    /**
     * 根据userid 查找单个人员
     */
    @Test
    public void findUser(){

        //uid=123,ou=internal,ou=People,o=xxx.com,o=xxx
        DirContextAdapter obj = (DirContextAdapter) ldapTemplate.lookup("uid=123,ou=internal,ou=People");//BASE_DC 不用填
        System.out.println(obj);
    }

    /**
     * 根据部门编号o,查找部门
     */
    @Test
    public void findDept(){
        //o=abcd,ou=Organizations,ou=People,o=xxx.com,o=xxx
        DirContextAdapter obj = (DirContextAdapter) ldapTemplate.lookup("o=abcd,ou=Organizations");//BASE_DC 不用填
        System.out.println(obj);
    }

    @Test
    public void listDepts(){
        AndFilter filter = new AndFilter();
        filter.and(new EqualsFilter("objectClass", "organization"));
        //search是根据过滤条件进行查询,第一个参数是父节点的dn,可以为空,不为空时查询效率更高
        List depts = ldapTemplate.search("", filter.encode(), new LdapDeptAttributeMapper());
        System.out.println(depts.size());
//        Assert.assertEquals(305600, depts.size());
    }
}

 

  • 在ldap中,有两个”查询”概念,search和lookup。search是ldaptemplate对每一个entry进行查询,lookup是通过DN直接找到某个条目。
  • 在Ldap中,新增与删除叫做绑定bind和解绑unBind。这些方法LdapTemplate全部提供,并且还提供各种条件过滤等方法,不如findAll(),list()等。

我们注意到,findAll(),list()肯定是返回一个java.util.List<T>,包括,

 
//查询所有internal人员
List<LdapUser> users = ldapTemplate.search("ou=internal,ou=People", filter.encode(), new LdapUserAttributeMapper());

 

也是返回列表,列表里装的是查询出来的结果。但是上一篇文章用JNDI方式查询出来的是 Attributes attrs = ctx.getAttributes("uid=123,ou=Internal,ou=People");//获取到一个人员 Spring-ldap是基于JNDI实现的封装,那是哪里实现的把Attributes转成我们需要的Java Bean对象呢? 答案在new LdapUserAttributeMapper(),这个接口实现了查询结果到对象的转化。

 
import com.xxx.csb.sim.ldap.module.dto.LdapUser;
import org.springframework.ldap.core.AttributesMapper;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;

/**
 * 将ldap返回的结果,转成指定对象
 */
public class LdapUserAttributeMapper implements AttributesMapper {

    /**
     * 将单个Attributes转成单个对象
     * @param attrs
     * @return
     * @throws NamingException
     */
    public Object mapFromAttributes(Attributes attrs) throws NamingException {
        LdapUser user  = new LdapUser();

        if(attrs.get("uid") != null){
            user.setUsername( attrs.get("uid").get().toString());
        }
        if(attrs.get("cn") != null){
            user.setUserCn( attrs.get("cn").get().toString());
        }
        if(attrs.get("mobile") != null){
            user.setMobile( attrs.get("mobile").get().toString());
        }
        if(attrs.get("mail") != null){
            user.setMail( attrs.get("mail").get().toString());
        }
        if(attrs.get("employeeNumber") != null){
            user.setUserNumber( attrs.get("employeeNumber").get().toString());
        }

        if(attrs.get("type") != null){
            user.setUserType( attrs.get("type").get().toString());
        }
        if(attrs.get("py") != null){
            user.setPinyin(attrs.get("py").get().toString());
        }
        if(attrs.get("alias") != null){
            user.setAlias(attrs.get("alias").get().toString());
        }
        if(attrs.get("departmentNumber") != null){
            user.setDeptId(attrs.get("departmentNumber").get().toString());
        }
        if(attrs.get("departmentName") != null){
            user.setDeptName(attrs.get("departmentName").get().toString());
        }
        if(attrs.get("jobname") != null){
            user.setPositionName(attrs.get("jobname").get().toString());
        }
        if(attrs.get("modifyTimestamp") != null){
            user.setModifyTimestamp(attrs.get("modifyTimestamp").get().toString());
        }
        return user;
    }
}

 

可以看到转化的过程非常繁琐,无非就是拿JNDI查询到的Attributes,不停的获取属性值,再设置到Java对象中;attrs.get(“uid”).get().toString()然后set。

那好了,在每次查询的时候,要查询到多少列,在这个AttributesMapper转化方法中就要写多少个,判断及赋值。而且,如果因为业务不同,要查询不同的列,那AttributesMapper接口的实现必须重新写。那有没有支持复用的方式呢?答案是肯定的。

标签:get,解决方案,LDAP,认证,attrs,ldap,import,ou
From: https://www.cnblogs.com/richered/p/18392305

相关文章

  • 问题-解决方案对-《分析模式》漫谈24
    DDD领域驱动设计批评文集做强化自测题获得“软件方法建模师”称号《软件方法》各章合集“AnalysisPatterns”的第一章有这么一句:Itisanimportantformbecauseitsupportsthedefinitionofapatternas"asolutiontoaproblemincontext," adefinitionthat......
  • 解决方案 | 基于边缘智能控制器的变电所巡检系统
    前言供电系统作为轨道交通关键系统之一,承担着全线牵引系统和动力照明系统供电的首要任务,其运行安全性、可靠性直接关系到轨道交通的运营安全。传统模式下,为保证变电所的安全运行,巡视人员需每日对全线变电所设备进行巡视工作,确认设备运行状态及环境安全情况。但是,人工巡检存在巡检工......
  • 智能化办公新纪元:大中型企业的ChatGPT专属解决方案
    随着ChatGPT等AIGC技术在全球范围内的广泛应用,提升企业工作效率、降低运营成本已成为全球共识。大中型企业对这一技术充满兴趣。然而,现有的ChatGPT类产品需要将企业内部信息通过公网传输到AIGC产品后端,这不仅增加了信息被黑客截获的风险,而且外部大模型可能会将企业上传的数据纳......
  • VBA数据库解决方案第十四讲:如何在数据库中动态删除和建立数据表
    《VBA数据库解决方案》教程(版权10090845)是我推出的第二套教程,目前已经是第二版修订了。这套教程定位于中级,是学完字典后的另一个专题讲解。数据库是数据处理的利器,教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法和实例操作,教程第一版的修订内容主要是完成所有程序文件的32位和64......
  • Microsoft 365 解决方案:数据备份的必要性、配置架构
    51CTO博客链接:https://blog.51cto.com/u_13637423业务连续性保障是许多公司最关心的问题。如果发生加密大量数据的勒索软件攻击,或者内部意外或恶意数据删除或覆盖事件的实例,则需要能够尽快使业务恢复正常状态。这是Microsoft365备份产品提供的功能,无论是通过Microsoft365管......
  • QPS Qinsy 9.6.5 多波束海洋测量规划和实时水文数据处理解决方案,数据采集和处理以及
    QPSQinsy9.6.5软件是荷兰QPS公司开发的集导航、数据采集和处理以及制图一体化的软件。QPSQinsy9.6.5为各种类型的海上导航、定位和测量提供了一种友好、可靠的解决方案,广泛应用于海道测量、疏浚监控、地震测量、动态定位等领域。点击文章末尾下载软件链接体验吧!系统特点:......
  • 前端跨域请求的问题-解决方案
    前端跨域请求问题是Web开发中常见的一个挑战,尤其是在现代Web应用中,前端经常需要从不同的源(即协议、域名或端口不同的服务器)请求数据。由于浏览器的同源策略(Same-originpolicy),当尝试从一个源加载另一个源的资源时,浏览器会出于安全考虑阻止这些请求。本文将详细解释前端跨域请求......
  • “蓝屏事件”阴魂不散,微软安全更新导致 Linux 系统无法启动即解决方案
    最近,众多Linux用户报告称他们的设备在尝试启动时,收到了一条神秘的错误消息:“系统出了严重问题。”这起事件的罪魁祸首是微软在月度安全更新中发布的一个补丁,用于修复一个存在已久的GRUB漏洞。这次更新却导致了Linux和Windows双系统设备的启动问题,引发大量用户投诉和抱怨。L......
  • VBA代码解决方案第十七讲:如何选择一个工作表,如何选择多个工作表
    《VBA代码解决方案》(版权10028096)这套教程是我最早推出的教程,目前已经是第三版修订了。这套教程定位于入门后的提高,在学习这套教程过程中,侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码摆好。这套教程共三册,一百四十七讲,内容覆......
  • kerberos 认证流程-理解
    kerberos认证理解一、认证过程1)AS-REQ(请求)域内的用户向KDC(域控服务器)发送请求包,告诉域控,我要获得访问服务的票据。请求包:用户名,主机名,认证因子Authenticator(由客户端用户hash加密的时间戳等信息),其他信息2)AS-REP(响应)KDC接受到客户端的请求包。KDC判断用户是不是......