Security2 3|学习笔记

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 快速学习 Security2 3

开发者学堂课程【高校精品课-上海交通大学-企业级应用体系架构:Security2 3】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/75/detail/15827


Security2 3

 

内容介绍:

一. Kerberos 的实现

二.安全的其他几个属性

 

一. Kerberos 的实现

上节课讲了 Kerberos,Kerberos 是做单点认证的,所谓单点认证是有很多的系统都通过 EDL 认证,作为用户只要在这一个地方认证,认证之后访问这些系统之后就不用再登录,这就是单点认证,也就是说所有的系统的认证工作放到一个地方,就像看到的 count 就是这样的一种工作的模式。

现在的问题就是,这种模式怎么实现的?Kerberos 就是专门做这个事情的,Kerberos 叫这个名字是因为希腊神话中的一种动物三头狗,因为这里面我们看到有用户、认证中心以及各种应用三方。

image.png

单点认证起始于用户端,用户端第一次访问一个系统要重新认证,用户要输入用户名和密码。但是有个很重要的一点就是用户名和密码在输入之后实际上是没有都传递的,可以看到用户实际上只是发了一个有关用户 ID 的消息给认证中心,没有任何的密钥或者是密码发送给认证中心,也就是说用户虽然输入这两个东西,但只有用户名被发送给认证中心,密码留在了用户本地。

这样有一个好处就是如果在网络上第一次传递时可能没有加密,不能保证这些信息一定不会被拦截,如果拦截比如被别人监听到,它也只是用户名用户 ID 被别人听到,password 没有因为没有传输。在 AS 认证中心认证服务这一关,会存储在服务器端,存了所有的用户名和密码,发过来用户名之后,会到数据库中找用户名对应的密码,然后用密码通过某种算法也就是哈希算法进行处理,得到一个密钥。这个密钥是用用户存储在 AS 端的密码生成的。数据库端可以存 MySQL 或者服务器都可以,这是个细节问题。原理就是在数据库中找到跟用户名匹配的密码,用这个密码通过某种散列算法得到密钥,然后 AS 端就会给客户端发送两个消息。

image.png

第一个消息是 Client/TGS Session Key,意思是一个 Client 去 AS 认证,实际上是访问一个 Service, Service 看它未被认证,把它传到 AS 做认证,AS 会给一个密钥,未来想跟 Client 这边的 Service 通信给发一个 Key,这个 Key就是 Client/TGS Session Key。这个 Key 用处是将来拿这个 Key 就知道是经过 AS 认证之后的 Client。就跟大家在售票处买一张票,能过保安的前提是保安认为这张票确实是售票处买的,不是伪造的,所以 AS 端需要给 Client 一个票,这个票是不能伪造的,然后 Client 拿着票给 Service, Service 就能跟它通信。这个票具体的内容是以后 Client 和 Service 之间进行通信时双方都要用票里的信息加密进行操作。所以消息 A 首先是用客户端输入的密码生成的密钥加密过之后的一个东西。

消息 B 是用 Service 端使用密钥加密之后的一个票,票中放了 Key。就是 AS 生成了一个 Key,这个 Key 未来给 Client 一份、Service 一份,然后 Client 与 Service 之间都用这个 Key 加密信息解密信息进行通信。但是要证明这个 Key 是 AS 生成然后去分发的。所以要做两件事,第一件用 A 消息转来的 Key 用用户输入的密码加密,实际上是通过密码生成的密钥,给了用户之后,用户使用 password用同样的散列算法生成一个密钥,这个过程和服务器端在数据库中找到密码生成密钥过程是一样的,然后拿这个密钥对 A 解密,如果输入的密码对又是同一个算法,那服务器端生成的密钥与客户端生成的密钥是一样的,也就是说使用这个密钥可以解开消息 A,能解开消息 A 的前提是客户端输入的密码是正确的,如果密码不正确,使用相同算法生成密钥,这个密钥和服务器端的密钥是不同的,不同的密钥解另一个密钥加密的东西是解不开的,所以自然后面会被终止。当密码输入不正确时会被终止。密码输入正确,客户端就得到了密钥。

AS 端没有直接把密钥发给客户端要访问的 Service,它是生成 B, B仍然是这个密钥,但是是用的 TGS,也就是说这个 Service  TGS 也就是 Ticket-Granting-Ticket,通过所谓的票认证要访问的服务,与之交互的 Service 的密钥。比如是私钥,AS 端的是公钥,可以用 Service 的公钥加密消息。

加密之后,B 没有给 Service,而是给了客户端,所以需要把 B 发给 Service,不用怕客户端篡改 B,因为是拿服务端的公钥加密的,只有拿服务端的私钥解密,客户端最多只有 Service 的公钥,是解不开的,只能把消息原封不动的给 Service, Service拿到之后使用私钥解这个消息。如果一旦失败,说明消息被篡改过或者不是不认可这个认证过程。

如果 Service 拿私钥解开了消息 B,意味着消息未被篡改,并且可以解开 Key。当客户端和药访问的 Service 之间都有了 Key 之后,Key是一样的,说明都认可对方,可以拿这个 Key 通信比如加密等。实际上 AS 给客户端发送的两个消息中一个是 AS 自己使用的,并且密码正确的情况下,用户才能得到 Key。

还有一个是像一张票一样,要把票原封不动的传给 Service,只有 Service 能解开,当正确才认可才能通。第一步就是当用户名传递到了认证服务,返回给用户这两个消息,B 消息一定要再发送给 Service,就是这个用户的票,所以客户端接收到 A 和 B 之后,要做两件事情。

image.png

第一件事情就是输入密码,根据密码生成密钥,如果输入的密码和在服务器端认证服务存储的密码不一致,很显然生成的密钥也不同,就解不开消息 A,认证失败。解开了 A,说明输入密码正确,解开了 A 之后,得到了 Key,然后把 Session Key,是不能一直有效的,一定要有个 timeout,就是说在与服务交流过程中只在一段时间内会话过程中有效,超出时间不应该一直有效。

image.png

首先有 A,然后把票原封不动的把消息 B 发给 TGS,并且加上要访问的服务。

比如有一个 Client,一个 AS,一个软件学院的主页,底下有好多网站,比如学生管理、课程管理和缴费等等,实际上想要访问这些网站之一,但是这些网站都是统一的认证,得先给软件学院主页交互,当 Client 拿到了消息 B,把消息 B 给了 Service 端时,同时得说清楚是底下哪一个。实际上消息 B 没有做任何的改动,直接转发,只是加了一个东西,本身没有任何改动。

然后消息 D 是由 Client ID 以及时间戳构成的,认证服务用公钥加密的密钥给了 Client,然后 Client 发送给 Service, Service 使用私钥解密,这所有的过程都是信任 Client。Client 想看看对方是否为钓鱼网站,就拿这个密钥把信息加密,如果是钓鱼网站不可能有公钥配私钥,也就是说解不开,自然也无法解开消息 D,如果能解开消息 D,那就说明确实是想要访问的网站。

image.png

服务器端 TGS 收到 C、D 之后,C 其实没有收到,就是把 B 封装了一下,解出来 B 之后,使用私钥解密 B,于是得到 Key,消息 C 是为了得到 Key。得到 Key 之后,消息 D 使用这个 Key,再加密这个信息,所以用得到的密钥解 D 消息,解出来正常就知道要访问谁,不正常则有问题。软件学院这个网站一旦解开,认证好双方都彼此信任对方,关键是不是要访问软件学院,而是软件学院底下的网站,这些网站不是一个网站而是管理系统。

c 中已经有了想要访问的服务,信任之后,与之前认证中心给Client 一个票访问 TGS 一样,TGS 会给Client 一个票去访问具体的服务,所以以下动作就是 TGS 要给 Client 再发两条信息 E 和 F。Client 最终要和某一个 Service 通信,所以给发一个票,这个票是用要访问的服务的私钥加密过的,就是通过之后给 Service 发一个消息,将来可以与之管理系统交互,但是需要一个密钥,用 Service 的公钥加密,这就是 E。E 给 Client, Client 是解不开的,只能原封不动的发给 Service,这个票只是为了让 Client分发给 Service, Client 最终也要有这个 Key。

F 会用之前的密钥加密 Key,将来要给 Client 解开通信,但是以后通信使用 AS 分发的密钥,所以软件学院网站就会使用这个密钥来通信,给 Client 发与底下网站通信的密钥,拿到 F 之后,就可以解除 F  这边密钥。E 实际上是一张票,将来真正跟服务器通信的票。F 实际上是为了把密钥分发给客户端。

 image.png

真正的 Service一旦接触到 E 和 F,E 是密钥,要用票解开,拿私钥解出来得到密钥,然后生成新的认证服务,有Client ID。Client 收到 E 和 F 之后, 把 E 原封不动的发走,从 F 中用密钥把加密之后的密钥解开,之后对Client 加密生成一个 Authenticator,然后发给真正要访问的服务。真正要访问的服务拿到消息之后拿私钥解开,解开之后就得到了公钥,以后可以和那边的公钥进行通信。

 image.png

服务拿到公钥之后要告诉 Client 收到了,否则 Client 不知道服务器端是否收到,所以就回传一个 Message H,把 Client 发过来的 G 有 ClientID 和时间戳的认证服务中的时间戳加了一条收到了,然后用密钥把添加的时间戳回传给 Client。

至此都认证完了,以后通信是否使用密钥取决于网站的设计。现在的密钥都是把 Key 加密或者认证服务加密,做传递作用。真正在系统部署中,count 和整个系统的交互所有系统的管理都部署在一台服务器上,所以在很多地方看到的图很多是这个样子:

image.png

就是客户端发送密码,服务器端给客户端票,然后 A、B 消息过来解开。然后客户端把 C、D 发给服务器端,服务器端给客户端发送 E、F。所以在真实情况下就是只有 count AS和TGS。所以各种各样不同的 SS 都去 count进行认证,认证之后进行通信。

在认证过程中只要有一次认证,count就会知道,访问其他服务时,就会去 count 询问是否登录过,登录之后就会 mark,发送之前的登录过程,发一个密钥,在这个过程中用户不用再输入用户名和密码,因为之前输入过用户名和密码,已经被记住了,只需要重新生成一个与服务之间通信的票就可以。所以在一个地方登录,就可以不用再登录,是因为登录过之后,只需要把票发送过来,就知道不但正确的解开了并且已经拿到了票,所以就知道这是一个活跃的用户。这里面有两个票,一个是 Client 和 TGS 之间通信的票,是 AS 发的票,还有一个票是用户和 SS 通信的票,是 TGS 发的。显然 AS 会约定比如登录有效期是一天,那么这个票的有效期与 TGS 沟通的票就是一天,也就是说在访问另一个 SS 时,消息会要求服务哪个服务,新产生一个消息 C 和消息 D 发送,因为 AS 发过来的票有效期是一天,所以一天内可能都不用登录,直接用票里的密钥访问一个新的服务,AS 看票没过期就会新发一个票,这个票是与要访问的 SS 相关的,消息 E 中使用 SS 的公钥加密以后的票。

一旦第一个系统认证过,第二次就不需要认证了,直接用有效票即可。如果票已经过了一天作废了,那就需要重新输入用户名和密码。虽然有 count,在一天之内登录就只要输入一次,但在第二天还需要再次登录,这就是 Kerberos 协议的实现。

image.png

Kerberos 协议虽然比较好,但还有一些问题。第一个问题就是单点故障,如果 count 崩了,Java 所有的网站可能都登不进去了,就会有问题,所以这是单点故障在一个系统里面单点故障我们总是不愿意出现。其次,可以看到无论是Session 管理,还是在时间戳上加一个动作,都对时间有要求,也就是说希望所有的机器时钟都在一个给定的范围内,可以有误差,但这个误差必须满足一定条件不能太大,比如一个计算机上面的时钟和另一个差五个小时,这时候就会有问题,所发的票如果有效期就是五个小时,可能收到的时候就已经过期了,所以要求时间只能在给定范围内,虽然误差可以人为设定,但是总的来说要求比较精确。

在分布式系统中,想要所有的时钟都比较一致是比较困难的,所以这是第二个缺陷。第三个缺陷就是有很多细节没有被标准化,比如做一些管理比如票到底应该是什么格式、如果过期该怎么处理等,一些细节问题没有标准化,所以可以找到很多服务器都说它是基于 Kerberos 协议实现的,但是它们的实现有一些差异, Kerberos 协议实现的这些服务也许 API 不一样,随意做一个实现的替换可能会有一些问题。所有的认证都有一个集中式的密钥库做管理,如果直接黑进密钥库,就可以知道密钥库所有信息,所以有这样一个风险。Kerberos 协议到网络分布式系统,每一个网络服务比如学生管理等或许都有不同的命名,可能都会有自己的公钥私钥对,会有一个问题就是每一台机器都有不同的主机名, AS 会存储很多很多 primary Key。总的来说,Kerberos 协议是一个标准的大家都在实现的比如最常见的 CAS 服务,可以做分布式的处理,它是最常见的 Kerberos 协议的实现,它非常容易的能够实现单点认证,但是它和其他的会有一些差异。如果做一个单点认证的协议,开源的工具可以做。

 

二.安全的其他几个属性

安全应该包含什么内容,之前讲的都是在加密解密,然后认证身份防止别人冒充身份。安全实际上还包含其他的一些属性。

 image.png

第一个不可否认性,比如开了一个网店,有人下了一笔订单,这个订单可能下了非常多,就需要花大量钱备货,就会发现一个问题可能资金不足,把东西买回来之后,对方否认做过这件事情,那所谓的不可否认性就是作为一个用户不能否认曾经下过这个订单,意味着这个系统中必须要比较详细的比如 log 能记住所有用户的所有的动作,包括对数据的访问,如果不是对数据进行直接操作,而是调用服务,这种操作都应该记下来,用户不能否认执行过的操作。

显然需要一个比较强大的日志功能,目前为止,代码中很少看到写这种机制的动作,所以在用户是否有 log4j 这样的包,我们在别人的代码中经常看到 log. info、log.debug 不同级别的机制,能做到这一点是比较好的习惯,至少为能做到不可否认性提供了一个依据。第二点叫机密性,就是数据要加密,但是要注意数据加密实际上分两个部分,之前是数据的内容加密,第二还要注意就是数据传输过程中也要注意机密性。传输过程中的机密性就是如果被从中间监听,如果把内容加密就监听不到,如果只是把内容加密,在传输过程中还要考虑是对称密钥还是非对称密钥。

非对称密钥慢但是安全,对称密钥快但是不太安全,所以用非对称密钥传一次对称密钥,然后拿对称密钥互相通信。所以传输是一个密钥分发问题,总的来说就是要让别人不能打开数据库直接看到数据,比如经过 md5 加密之后存储到数据库,这是一方面。第二方面是在网络上传输时,要进行用证书用公钥私钥对加密,这两部分合起来就是机密性。

 image.png

第三个是完整性,完整性就是没有经过详细的讨论,比如客户端让服务器发送数据,无论是哪个协议发,都是把一大块数据拆分成很多小块,一块一块通过 TCP 的包传输,如果在传输过程中丢了一些,有没有要求数据必须是完整的,不完整是不行的,举例如果数据是非常重要的,TCP 要求是发给你要说收到了才会认为数据发送成功,如果不成功还会尝试转发,所以 TCP 协议发送包的时候如果对方收到顺序是乱的还需要整理。对应的比如 udp 就不需要,大量数据传输丢了就丢了,好处是大量数据传输速度比较快没有重发的机制,不保证数据一定传到,潜在数据丢失的问题。

这是在传输层的加密解密,如果在应用层比如把班上20个同学的信息传走,服务器收到的是18个,在通信服务器端只是收数据并不知道少发了数据,这时需要设计一种通信的协议,比如发的第一包数量是20,后面接收为18时,需要想一些校验的办法。比较简单的一个办法就是 checksum (校验和),比如发20个人的信息之后再发一个 salary 的总和,服务器端收到之后进行校验,把收到的所有人的 salary 加起来和最后收到的 salary 总和不一致,说明数据被修改或者丢失。

数据的完整性是数据安全的一部分,如果数据不完整因为传输的问题被篡改或者其他原因导致数据不完整,那么这个数据也就不安全了,最好的办法就是把数据扔掉,重新传输。

如果要服务一个网站,如果服务的是一个钓鱼网站,怎么知道对方是否为钓鱼网站,之前工商银行是 www.icbc.com,有人做个钓鱼网站 www.1cbc.com,首页做的一模一样,就会有用户登录输入用户密码,一旦点进去就会显示对不起网站忙请稍后再试。考虑这个问题其实得靠证书,就是公钥密钥对,如果是工商银行,就拿工商银行的公钥加密信息发送,工商银行会用其私钥解开,如果是钓鱼网站是没有 ICBC 的私钥,解不开数据。

工商银行为了表明确实是工商银行,在通信时就会约定一定要用证书加密,所以可以看到重要网站都是 https 旁边会有一把锁,表示需要查看证书。敏感信息传递时一定要非对称的密钥对通信。

 image.png

第五个是可用性,可用性是什么信息都能进可以扛住,不管怎么打击攻击,都能扛住系统原来的服务,安全性是不让进,只要进来就能抵御。可用性是靠增加冗余,不断发现设备是否完好,安全性是认证授权保证只有认证之后有权限的才能访问。如果有服务攻击 也就是 dos 攻击,DDOS 对网站发起大量的请求,需要过滤来自同一个 IP 的请求,在单位时间内不能超过多少,比如一秒内超过十个就拒绝后面的请求。

最后一点是之前所有的事情都是假设能抵御所有攻击,一旦受到攻击能否发现,对日志做审计,对用户做审计讨论用户行为判断是否为合法用户。

相关文章
|
6月前
|
安全 Java 数据安全/隐私保护
Security快速入门
Security快速入门
|
存储 安全 Java
Web Security 之 Insecure deserialization
Web Security 之 Insecure deserialization
53 0
|
缓存 安全 Java
Security2 1|学习笔记
快速学习 Security2 1
232 0
Security2 1|学习笔记
|
存储 安全 Java
Security1 2|学习笔记
快速学习 Security1 2
117 0
Security1 2|学习笔记
|
自然语言处理 算法 安全
Security2.2|学习笔记
快速学习 Security2.2
123 0
Security2.2|学习笔记
|
安全 Java 数据安全/隐私保护
案例之认证服务security配置|学习笔记
快速学习案例之认证服务security配置
案例之认证服务security配置|学习笔记
|
存储 前端开发 安全
Security RememberMe原理分析
Security RememberMe原理分析
177 0
|
安全 NoSQL Java
security和oauth2.0的整合
security和oauth2.0的整合 之前已经介绍过security的相关的介绍,现在所需要做的就是security和oauth2.0的整合,在原有的基础上我们加上一些相关的代码;代码实现如下: pom.
1545 0
|
安全 网络安全 数据安全/隐私保护