本文主要是介绍认证、授权、凭证、保密、传输、验证,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
系统如何正确分辨操作用户的真实身份?
认证(Authertication) :系统如何正确分辨出操作用户的真实身份?
授权(AUthorization)**:系统如何控制一个用户该看到哪些数据、能操作哪些功能?
凭证(Credentinls):系统如何保证它与用户之间的承诺时双方当时真实意图的体现,是准确、完整且不可抵赖的?
保密(Confidentiality):系统如何保证敏感数据无法被包括系统管理员在内的外部人员所窃取、滥用?
传输(Transport Scurity):系统如何保证通过网络传输的信息是无法被第三方窃听、篡改、冒充?
验证(Verification):系统如何确保提交到每项服务中的数据是否合乎规则的,不会对系统稳定性、数据一致性、正确性产生风险?
系统如何确保授权的过程可靠?
对于单一系统来说,授权的过程是比较容易做到可控的,而在涉及多方的系统中,授权过程则是一个比较困难,但是必须要严肃对待的问题:如何既让第三方系统能够访问到所需要的资源,又能保证其不泄漏用户的铭感数据呢?以OAuht 2.0协议为例子
OAuth 2.0解决的是第三方服务中涉及的安全授权问题
首先OAuth 2.0提供了四种不同的授权方式:
授权码模式
1、第三方应用将资源所有者(用户)导向授权服务器的授权页面,并向授权服务器提供ClientID及用户同意授权后的回调URI,这是第一次客户端页面跳转
2、授权服务器根据ClientID确认第三方用户身份,然后决定是否对该应用授权,注意⚠️用户认证的过程未定义在此步骤中,在此之前已经完成
3、如果用户同意授权,授权服务器将给第三方应用提供回调的URI,并附带一个授权码和获取令牌的地址作为参数,第二次跳转
4、第三方应用通过回调地址收到授权码,然后将授权码与自己的ClientSecret一起作为参数,通过服务器向授权服务器提供的获取令牌的服务器地址发器请求,换取令牌。该服务器的地址应该与注册时提供的域名处于同一个域中
5、授权服务器核对授权码和ClientSecret,确认无误后,向第三方应用授权令牌,令牌可以是一个或者两个,其中必定有的是访问令牌,可选的是刷新令牌。访问令牌用于资源服务器获取资源,有效期较短,刷新令牌用于在访问令牌失效后重新获取,有效期较长。
6、资源服务器根据访问令牌所允许的权限,向第三方应用提供资源。
简化模式
简化模式就与授权码模式的明显区别就是授权服务器在得到用户的授权之后,直接返回了访问令牌。授权服务器不再会去验证第三方应用的身份,因为没有应用服务器了,ClientSecret没人保管
密码模式
认为第三方应用高度可信,直接提供密码凭证给到第三方应用,第三方应用再发送用户的密码凭证给到授权服务器,然后返回访问令牌和刷新令牌
客户端模式
这种模式只涉及两个主体:第三方应用和授权服务器。这种模式通常用于管理操作或自动处理类型的场景
会不会有其他应用冒充第三方应用骗取授权?
ClientID 代表一个第三方应用的"用户名",这项信息可以完全公开的。但Client Secret应当只有8u应用自己才知道,这个代表了第三方应用"密码“。
为什么要先发放授权码,再用授权码换令牌?
因为授权码,可能会暴露给用户以及用户机器上的其他程序,但是由于用户并没有ClientSeret,光有授权码无法换取到令牌,所以避免了令牌在传输过程中页面跳转过程中被泄漏的风险
系统如何确保授权的过程可控?
RBAC权限角色控制,最典型的例子是操作系统权限管理中的用户组。即根据对不同角色的职责分工,如管理员、系统用户、验证用户、普通用户、来宾用户
凭证:系统如何确保用户之间的约定是准确完整且不可抵赖的?
Cookie-Session:HTTP的状态管理机制
Cookie-Session的方法在安全架构系统中,其实是占据一定天生优势的:因为状态信息都存储于服务器,只要依靠客户端的同源策略和HTTPS的传输安全,保证Cookie中的键值对不被窃取而出现被冒认身份的情况,就能完全规避掉信息在传输过程中被泄漏和篡改的风险。
因为Session存储在服务器的内存中,那么当服务器水平扩展成多节点时,我们在设计时,就必须在以下三种方案中选其一
要么牺牲集群的一致性,让均衡器采用亲和式的负载均衡算法。比如根据用户IP或Session来分配节点,每一个特定的用户发出的所有请求,只能提供一个节点来服务,每个节点不重复的保存着一部分用户的状态,如果这个节点崩溃了,里面的用户状态便完全丢失
要么牺牲集群可用性:让各个节点采用复制式的Session,每一个节点的Session变动广播到每个节点服务器上。问题就是Session之间的同步代价比较昂贵
要么牺牲集群的分区容错性:让普通节点不再保留状态,将上下文集中到一个节点,这样会存在单点问题。一旦数据损坏或者出现网络分区,整个集群不再提供服务
JWT:解决认证授权的无状态方案
在Cookie- Session机制下分布式环境会遇到CAP不可兼得的问题,而在多方系统中,也就更不可能谈什么Seesion层面的数据共享了,哪怕服务器之间能共享数据,客户端的Cokkie也没办法跨域
JWT的三部分组成、令牌头、负载、签名
令牌头(Header)
负载(PayLoad)
签名(Signature)
JWT解决了防止篡改问题,并没有解决泄密问题,额外补充一点:散列消息认证码:HMAC哈希与普通哈希算法的差别是,普通的哈希算法通过Hash函数结果易变性,保证了原有内容未被篡改,而HMAC不仅保证了内容未被篡改,还保证了该Hash确实是由密钥的所持有人生成的【简单理解就是Hash算法➕盐】
JWT的缺点:
只能携带有限的数据,无法携带大量信息
令牌难以主动失效
比如要求用户只能在一台设备上登录,在B设备登录了,之前登录过的A设备需要自动退出。所以在使用JWT时,我们需要使用一个黑名单逻辑,主动把失效的令牌集中存储起来
相对容易遭受重放攻击
必须考虑令牌令牌在客户端如何存储
更严谨的问题是系统设计的问题,不是JWT的问题
保密:系统如何保证敏感数据无法被内外部人员窃取滥用?
保密的强度及做法
1、以摘要代替铭文
以摘要代替明文
如果密码本身比较复杂,那么一次简单的哈希摘要就至少可以保证,即使在传输过程中有信息泄露,也不会被逆推出原信息;即使密码在一个系统中泄露了,也不至于威胁到其他系统的使用。但这种处理不能防止弱密码被彩虹表攻击所破解。
2、先加盐值再做哈希是应对弱密码的常用方法
盐值可以替弱密码建立一道防御屏障,在一定程度上可以防御已有的彩虹表攻击。但它并不能阻止加密结果被监听、窃取后,攻击者直接发送加密结果给服务端进行冒认。
3、将盐值变为动态值能有效防止冒认
如果每次向服务端传输时,密码都掺入了动态的盐值,让每次加密的结果都不一样,那么即使传输给服务端的加密结果被窃取了,攻击者也不能冒用来进行另一次调用。不过,尽管在双方通讯均可能泄露的前提下,协商出只有通讯双方才知道的保密信息是完全可行的(后面两讲介绍“传输安全层”时会提到),但这样协商出盐值的过程将变得极为复杂,而且每次协商只能保护一次操作,因而也很难阻止攻击者对其他服务的重放攻击。
4、加入动态令牌防止重放攻击
我们可以给服务加入动态令牌,这样在网关或其他流量公共位置建立校验逻辑,服务端愿意付出在集群中分发令牌信息等代价的前提下,就可以做到防止重放攻击。但这种手段的弱点是,依然不能抵御传输过程中被嗅探而泄露信息的问题。
5、启用HTTPS来应对因嗅探而导致的信息泄露问题
启用HTTPS可以防御链路上的恶意嗅探,也能在通讯层面解决重放攻击的问题。但是它依然有因客户端被攻破而产生伪造根证书的风险、因服务端被攻破产生证书泄露被中间人冒认的风险、因CRL更新不及时或者OCSPSoft-fail产生吊销证书被冒用的风险,以及因TLS的版本过低或密码学套件选用不当产生加密强度不足的风险。
6、进一步提升保密强度的不同手段
为了抵御前面提到的这种种风险,我们还要进一步提升保密强度。比如说,银行会使用独立于客户端的存储证书的物理设备(俗称的U盾),来避免根证书被客户端中的恶意程序窃取伪造;当大型网站涉及到账号、金钱等操作时,会使用双重验证开辟出一条独立于网络的信息通道(如手机验证码、电子邮件),来显著提高冒认的难度;甚至一些关键企业(如国家电网)或机构(如军事机构),会专门建设遍布全国各地的、与公网物理隔离的专用内部网络,来保障通讯安全。
数据证书与传输层安全(HTTPS)
HTTPS握手过程解读
第一步,客户端请求:Client Hello
客户端向服务器请求进行加密通讯,在这个请求里面,它会以明文的形式,向服务端提供以下信息:
支持的协议版本,比如TLS 1.2。但是你要注意,1.0至3.0分别代表了SSL1.0至3.0,而TLS1.0则是3.1,一直到TLS1.3的3.4。
一个客户端生成的32 Bytes随机数。这个随机数将稍后用于产生加密的密钥。
一个可选的SessionID。注意,你不要和前面的Cookie-Session机制混淆了,这个SessionID是指传输安全层的Session,它是为了TLS的连接复用而设计的。
一系列支持的密码学算法套件。比如TLS_RSA_WITH_AES_128_GCM_SHA256,代表着密钥交换算法是RSA,加密算法是AES128-GCM,消息认证码算法是SHA256。
一系列支持的数据压缩算法。
其他可扩展的信息。为了保证协议的稳定,后续对协议的功能扩展大多都是添加到这个变长结构中。比如TLS 1.0中,由于发送的数据并不包含服务器的域名地址,导致了一台服务器只能安装一张数字证书,这对虚拟主机来说就很不方便,所以从TLS 1.1起,就增加了名为“Server Name”的扩展信息,以便一台服务器给不同的站点安装不同的证书。
第二步,服务器回应:Server Hello
服务器接收到客户端的通讯请求后,如果客户端声明支持的协议版本和加密算法组合,与服务端相匹配的话,就向客户端发出回应。如果不匹配,将会返回一个握手失败的警告提示。这次回应同样是以明文发送的,主要包括以下信息:
服务端确认使用的TLS协议版本。
第二个32 Bytes的随机数,稍后用于产生加密的密钥。
一个SessionID,以后可通过连接复用减少一轮握手。
服务端在列表中选定的密码学算法套件。
服务端在列表中选定的数据压缩方法。
其他可扩展的信息。
如果协商出的加密算法组合是依赖证书认证的,服务端还要发送出自己的X.509证书,而证书中的公钥是什么,也必须根据协商的加密算法组合来决定。
密钥协商消息,这部分内容对于不同的密码学套件有着不同的价值。比如对于ECDH + anon这样的密钥协商算法组合来说(基于椭圆曲线的ECDH算法可以在双方通讯都公开的情况下,协商出一组只有通讯双方知道的密钥),就不需要依赖证书中的公钥,而是通过Server Key Exchange消息协商出密钥。
第三步,客户端确认:Client Handshake Finished
由于密码学套件的组合复杂多样,这里我就只用RSA算法作为密钥交换算法来给你举个例子,介绍下客户端确认的后续过程。
首先,客户端在收到服务器应答后,要先验证服务器的证书合法性。然后,如果证书不是可信机构颁布的,或者是证书中的信息存在问题,比如域名与实际域名不一致、或证书已经过期、或通过在线证书状态协议得知证书已被吊销,等等,这都会向访问者显示一个“证书不可信任”的警告,由用户自行选择是否还要继续通信。
而如果证书没有问题,客户端就会从证书中取出服务器的公钥,并向服务器发送以下信息:
客户端证书(可选)。部分服务端并不是面向全公众的,而是只对特定的客户端提供服务,此时客户端就需要发送它自身的证书来证明身份。如果不发送,或者验证不通过,服务端可自行决定是否要继续握手,或者返回一个握手失败的信息。客户端需要证书的TLS通讯,也被称为“双向TLS”(Mutual TLS,常简写为mTLS),这是云原生基础设施的主要认证方法,也是基于信道认证的最主流形式。
第三个32 Bytes的随机数,这个随机数不再是明文发送,而是以服务端传过来的公钥加密的,它被称为PreMasterSecret,将与前两次发送的随机数一起,根据特定算法计算出48 Bytes的MasterSecret,这个MasterSecret也就是为后续内容传输时的对称加密算法所采用的私钥。
编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的哈希值,以供服务器校验。
第四步,服务端确认:Server Handshake Finished
服务端向客户端回应最后的确认通知,包括以下信息:
编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的哈希值,以供客户端校验。
那么到这里,整个TLS握手阶段就宣告完成,一个安全的连接就成功建立了。你要知道,每一个连接建立的时候,客户端和服务端都会通过上面的握手过程协商出许多信息,比如一个只有双方才知道的随机产生的密钥、传输过程中要采用的对称加密算法(例子中的AES128)、压缩算法等,此后该连接的通讯将使用此密钥和加密算法进行加密、解密和压缩。
这种处理方式对上层协议的功能上完全透明的,在传输性能上会有下降,但在功能上完全不会感知到有TLS的存在。建立在这层安全传输层之上的HTTP协议,就被称为“HTTP Over SSL/TLS”,也即是我们所熟知的HTTPS。
这篇关于认证、授权、凭证、保密、传输、验证的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!