理解乐观锁 CAS 的非阻塞同步机制

在并发编程的世界里,“线程安全”通常意味着“加锁”。从 synchronized 关键字到 ReentrantLock,我们已经习惯了通过排他性地锁定资源来确保数据一致性。然而,锁并非万能良药。在追求极致性能的场景下,锁带来的上下文切换和等待成本可能成为系统瓶颈。那么,有没有一种方法可以在不挂起(阻塞)线程的情况下,安全地在多线程间修改共享变量呢? 答案是肯定的。这就是原子变量(atomic variables)和非阻塞同步算法(Non-blocking Algorithms),也就是我们俗称的“乐观锁”。 第一部分:锁的代价 在传统的并发模型中,我们主要依赖阻塞锁。这种机制也被称为悲观锁:它假设最坏的情况,认为如果不锁定资源,其他线程一定会捣乱。虽然锁能保证安全,但在高并发场景下,它带来了两个主要的性能杀手: 线程挂起与恢复的开销:当一个线程无法获取锁时,它会被阻塞(挂起)。操作系统在挂起和恢复线程时需要进行上下文切换,这在高位性能场景下是非常昂贵的。 活跃性问题:阻塞锁可能导致死锁、优先级倒置和线程饥饿。 对于简单的计数器自增操作,为此挂起和恢复线程就像为了喝杯水而关掉整个城市的供水系统一样——成本极度不成比例。对于涉及整数和对象引用变更的场景,我们需要一种更轻量、更“乐观”的方法。 第二部分:硬件级原子武器:CAS Java 5.0 引入了 java.util.concurrent 包。原子类(如 AtomicInteger)和非阻塞数据结构(如 ConcurrentLinkedQueue)性能飞跃背后的秘密武器就是 CAS (Compare-And-Swap) 指令。 什么是 CAS? CAS 是一种直接由 CPU 指令集支持的硬件原语(如 x86 的 lock cmpxchg)。它体现了乐观锁的哲学:我不加锁,直接尝试更新;如果更新失败(说明别人先到一步),我就重试或放弃,但我绝不挂起自己。 CAS 操作由三个核心步骤组成: 读取旧值:我看一眼内存里当前的值是多少。 比较:准备写入时,我再看一眼——内存里的值还是我刚才看到的那个吗? 交换:如果是,我就把它更新为新值(New Value);如果不是,说明在此期间有其他线程修改了它,我的操作失败。 我们可以用一段 Java 代码来模拟 CAS 逻辑(注意:真实的 CAS 是无锁的 CPU 指令,这里使用 synchronized 仅为了模拟其原子语义): @ThreadSafe public class SimulatedCAS { @GuardedBy("this") private int value; // 仅当内存中的值等于 expectedValue 时,才更新为 newValue public synchronized int compareAndSwap(int expectedValue, int newValue) { int oldValue = value; if (oldValue == expectedValue) value = newValue; return oldValue; } } 为什么 CAS 比锁快? ...

十二月 7, 2025 · 1 分钟

分库分表环境下的数据一致性挑战与解决方案

前言:分库分表后的“第二天”挑战 在大规模微服务架构的演进过程中,分库分表(Sharding)常被视为解决海量数据存储与高并发写入挑战的“银弹”。当我们兴奋地使用 Apache ShardingSphere 将单体数据库拆分为 16 个分库、1024 个分表,看着系统吞吐量直线飙升时,往往会忽略随之而来的一个严峻问题——运维与一致性。在分库分表上线的“第二天”,开发与运维团队通常会面临以下灵魂拷问: DDL 噩梦:当业务需求变更,逻辑表需要增加一个字段时,DBA 是否必须手动连接 16 个数据库,执行 1024 次 ALTER TABLE? 微服务“人格分裂”:在微服务多实例部署场景下,如果实例 A 修改了表结构,实例 B 如何感知?如果实例 B 不知道,依然在用旧的元数据组装 SQL,岂不是会报错? 架构选型困惑:听说 ShardingSphere 有 JDBC 和 Proxy 两种模式,我们是否还需要引入 Zookeeper?这会不会让架构变得太复杂? 基于实战经验,本文将从 DDL 变更一致性到微服务元数据同步,系统性地剖析这一问题并给出完整解决方案。 第一部分:如何优雅地管理成百上千张表? 在单体数据库时代,执行一条 ALTER TABLE 是轻松愉快的事情。但在分库分表架构下,一个逻辑表(Logic Table)可能对应分布在不同物理节点上的几十甚至上百个物理表(Actual Tables)。如果采用人工维护,不仅效率极低,而且极易出现“漏网之鱼”——即部分分表成功,部分失败,导致数据节点间的 Schema 不一致,引发应用层的灾难性错误。 解决方案:ShardingSphere-JDBC + Flyway / Liquibase 在 Java 生态中,推荐将 ShardingSphere-JDBC 与 Flyway 或 Liquibase 等数据库版本管理工具结合使用。 核心流程如下: 一次编写:开发人员只需像操作单库一样,编写一份标准的 SQL 变更脚本(如 V1.0.1__add_column_to_user.sql)。 版本管理:将脚本放入项目的 resources/db/migration 目录下,并纳入 Git 版本控制。 自动执行:应用启动时,Flyway 自动处理数据库迁移。 透明广播:这是最关键的一步。Flyway 连接的不是真实的物理数据源,而是 ShardingSphere-JDBC 提供的逻辑数据源。ShardingSphere-JDBC 内部会拦截这条 DDL 语句,识别出它是对逻辑表的操作,然后利用其核心能力,自动将该 DDL 广播到所有相关的底层物理分库分表中执行。 为什么这种方式是最佳实践? ...

十二月 6, 2025 · 2 分钟

深入解析 Spring 事务管理

Spring 框架为开发者提供了一套强大且灵活的事务管理机制。无论是复杂的分布式系统还是简单的单体应用,Spring 的事务抽象层都能让我们以统一、简洁的方式控制事务行为。本文将从为什么使用 Spring 事务开始,深入探讨其核心配置、工作原理、关键属性以及常见的坑点与最佳实践。 第一部分:为何选择 Spring 的事务模型? 在传统的 JDBC 操作中,我们需要手动处理 Connection 对象的获取、提交(commit)和回滚(rollback),代码冗余且极易出错。虽然 JTA (Java Transaction API) 提供了跨资源的事务能力,但其 API 相对复杂。 Spring 优雅地解决了这些问题。通过提供一致的编程模型,它让开发者无论是在简单的 JDBC 环境还是复杂的 JTA 环境中,都能以相同的方式管理事务。这极大地降低了学习成本和代码耦合度。 Spring 框架提供了两种核心的事务管理方式: 编程式事务管理:在代码中通过 TransactionTemplate 或直接使用 PlatformTransactionManager API 手动控制事务。这种方式更为灵活,但侵入性强。 声明式事务管理:基于 AOP (面向切面编程),通过 @Transactional 注解来管理事务。这是目前最流行也是 Spring 官方推荐的方式,因为它将业务代码与事务管理代码彻底解耦,保持了 POJO 的纯净。 第二部分:核心配置:TransactionManager 的幕后英雄 要让声明式事务生效,必须在 Spring 容器中正确配置一个 PlatformTransactionManager Bean。这个管理器是 Spring 事务基础设施的核心,负责执行事务的创建、提交和回滚。 对于基于 JDBC 的应用,我们通常使用 DataSourceTransactionManager。以下是一个典型的基于 Java 的配置: @Configuration @EnableTransactionManagement // 开启声明式事务管理能力 @PropertySource("classpath:jdbc.properties") public class DataSourceConfig { @Value("${jdbc.driverClassName}") private String driverClassName; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; /** * 配置数据源 */ @Bean(destroyMethod = "close") public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName(driverClassName); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } /** * 配置事务管理器,并注入数据源 */ @Bean public PlatformTransactionManager txManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } } @EnableTransactionManagement 注解是激活声明式事务处理能力的关键。配置完成后,我们就可以在代码中使用 @Transactional 注解了。 ...

十一月 19, 2025 · 2 分钟 · 肖斌

理解 ABAC 访问控制模型

访问控制(AC)的发展历程 访问控制(Access Control, AC)是保护系统资源的重要机制,决定“谁”可以访问“哪些”资源,并能执行“哪些操作”。它的核心目标是防止越权访问和恶意操作,从而保障系统安全和数据机密性。访问控制技术的历史可以追溯到 20 世纪 60-70 年代,几乎与计算机的诞生同步。经过数十年的发展,访问控制模型从MAC(强制访问控制)演进到 ABAC(基于属性的访问控制),不同阶段的技术各有特点,适用于不同的场景。 AC 的演进阶段 访问控制技术的发展经历了以下关键阶段: MAC(强制访问控制,Mandatory Access Control) 特点:最早出现的访问控制模型,由系统统一管理权限,用户无法修改自己的权限。 优点:安全性高,适用于军事、政府等高安全要求的环境。 缺点:灵活性低,难以适应企业或商业应用。 DAC(自主访问控制,Discretionary Access Control) 特点:资源的所有者可以自行分配权限,比如文件的拥有者可以决定谁能读取或修改它。 优点:灵活性高,易于实现,适用于个人电脑、文件系统等应用场景。 缺点:权限管理分散、缺乏统一性,可能导致安全漏洞。 RBAC(基于角色的访问控制,Role-Based Access Control) 特点:用户被分配角色,权限与角色绑定,用户继承角色的权限,而不是直接分配权限。 优点:简化权限管理,特别适用于企业和组织化管理,可以减少手动管理的复杂度。 缺点: 细粒度控制能力有限,难以满足复杂权限需求。 “角色爆炸” 问题:当组织规模扩大时,角色数量可能大幅增加,导致管理复杂化。 ABAC(基于属性的访问控制,Attribute-Based Access Control) 特点:通过用户、资源和环境的属性动态计算访问权限,而不是固定的角色分配。 优点: 更灵活,可以支持复杂的权限需求,适用于云计算、大型企业、跨组织合作等场景。 动态调整权限,可以基于实时环境(如访问时间、地点、设备)调整权限。 缺点:管理复杂度较高,需要更强的策略管理能力和计算资源。 AC 的发展趋势 总体来看,访问控制技术正在从静态、粗粒度控制向动态、细粒度管理演进,以适应日益复杂的 IT 环境和安全需求。 早期的 MAC 强调安全性和统一管理,但缺乏灵活性。 DAC 和 RBAC 提高了灵活性和可管理性,尤其是 RBAC 适用于企业组织管理,至今仍是许多企业的主要访问控制模式。 ABAC 将灵活性提升到新高度,通过属性组合实现更细粒度的权限管理,适用于云计算和复杂安全需求的企业。 尽管 RBAC 目前仍然是企业访问控制的主流,但 ABAC 由于其强大的灵活性,正在越来越多地被采用,尤其在需要动态权限调整和细粒度控制的场景下。 未来,RBAC 和 ABAC 的混合模式(RBAC-ABAC)可能成为新的趋势,即RBAC 用于管理基础权限,ABAC 用于细粒度控制,这样既能保证管理的简便性,又能提升系统的安全性和灵活性。 ABAC 的概述说明 ABAC(Attribute-Based Access Control,基于属性的访问控制) 是一种动态、细粒度的访问控制方式,与传统的 RBAC(基于角色的访问控制) 和 ACL(访问控制列表) 不同,ABAC 不依赖预定义的角色或权限,而是根据用户、资源和环境等属性实时计算访问权限。 相比于 RBAC 这样固定的权限模型,ABAC 提供了更强的灵活性,能够基于不同属性动态调整权限。 ...

二月 9, 2025 · 5 分钟

hppts 传输加密的主要过程

概述 现代密码学对信息的处理主要离不开以下的三种形式: 摘要:主要用于数据校验,例如存储密码等,摘要是对信息进行单向的哈希,改变信息的原有形态,因为哈希函数的特点是易变性(即使微小的变化也会产生完全不同的哈希值),而且无法被反向推导出来,例如上文提到常见的哈希加密方式有:MD2/4/5/6、SHA0/1/256/512 算法等方式。 加密:主要用于保证信息的安全传输,确保真实的信息只能被授权的人访问(拥有密钥),通常使用密钥对信息进行加密,和摘要不同的是,加密是可以解密为明文信息的。密钥的类型又分为:对称型密钥,非对称型密钥(公钥、私钥)等,常见的有 DES、AES、RC4、IDEA 等方式。 签名:主要是用来保证明文信息的完整性、真实性和检查是否被篡改的一种方式(使用哈希函数),例如 jwt 令牌 中就是有一段签名,用于保证负载信息的真实性,签名并不保证信息的私密性。 总体来说,它们的分工是: 摘要:用于确保数据的完整性和快速比较,无法被解密。 加密:用于保护数据的机密性,它和摘要的区别是加密可以逆向破解,也就是解密。 签名:则提供了一种验证消息来源和完整性的方法。但信息是公开的。 这三者共同构成了现代密码学的基石,广泛应用于数据保护、身份验证和网络安全等领域。 密钥 对称型密钥 对称型密钥加密的基本原理是将明文数据通过一个加密算法和一个密钥转换成密文,然后接收方使用相同的密钥和解密算法将密文还原成原始的明文。由于加密和解密都使用同一个密钥,因此被称为对称加密。对称型密钥加密算法的特点是算法简单、速度快,适合于大量数据的加密。常见的对称型密钥加密算法包括:AES (Advanced Encryption Standard)、DES (Data Encryption Standard)、3DES (Triple DES)。 对称型密钥在密钥的保管和分发上面存在困难,因为密钥必须安全地分发给所有需要它的用户,并且每次通信都需要一个新的密钥,这在大规模通信中可能会变得复杂。关于对称型密钥总结如下: 优点:加解密速度快,适合大量数据、算法简单,资源消耗低,适合大量数据的加解密的场景。 缺点:密钥的保存和分发困难:无法在不可信的网络上进行分发,存在 “先有鸡,还是先有蛋” 的问题。 非对称型密钥 非对称型密钥加密,也称为公钥加密或双密钥加密,是一种使用两个不同密钥的加密方法:一个用于加密(称为公钥),另一个用于解密(称为私钥)。公钥可以公开分享,而私钥则必须保密。 非对称加密的基本原理是: 密钥生成:首先生成一对密钥,包括一个公钥和一个私钥。这两个密钥是数学上相关的,但即使知道了公钥,也无法轻易推导出私钥。 加密:当 A 想要向 B 发送加密信息时,A 会使用 B 的公钥来加密信息。这样,只有拥有相应私钥的 B 才能解密这条信息。 解密:B 收到加密信息后,使用自己的私钥来解密,恢复原始信息。 非对称加密的关键特性是公钥可以公开,而私钥必须保密。这使得非对称加密在某些应用场景中非常有用,但非对称加密的主要缺点是计算复杂,消耗资源,速度慢等,因此它通常与对称加密结合使用:非对称加密用于安全地交换对称密钥,然后使用对称密钥进行实际的数据加密,以提高效率。使用非对称型密钥主要解决两个不信任个体在不安全通信环境下的信息传输问题,解决信息在公开网络中传输的问题,既然被截获也不会受到影响。关于非对称型密钥总结如下: 优点:使用密钥对解决密钥分发的问题,可以在公开网络中安全传输信息 缺点:速度慢,不适合对大量数据进行加密,计算资源消耗高,拥有长度的限制多长的密钥只能加密多长的明文。 因此,对称密钥和非对称密钥的区分是为了满足不同的安全需求、提高效率、简化密钥管理,并适应不同的通信场景。单独依靠某一种算法(对称加密、非对称加密)既做不了加密,也做不了签名。在实际应用中,对称加密和非对称加密往往是结合使用的。已混合加密方式来保护信道安全。 具体做法: 使用非对称加密方式,协商一个密钥(少量信息)给通信的另一方 双方基于共同的密钥进行对称加密传输大量的信息 混合使用对称和非对称加密方法来传输信息,这样可以同时利用两种加密方式的优势,也称为现代密码学套件。信息传输的终极解决方案 HTTPS 就是基于该方式实现的。 证书 在现实生活中,我们要和一个未曾谋面的人建立信任,通常有两种方式: 基于共同的私密信息:对方打电话来说是我的小学同学,他能说出我们小学还有同学的名字,做过的一些糗事,那么我就会信任他 基于权限的公证人:对方说他是警察,需要我配合办案,如果他能提供证件和警员编号,那么我们也会信任他,并且进行配合 在网络世界里面,我们不能认为两台计算机是相互认识并且存在共同的私密信息的,所以解决信任问题只有基于第二种 基于权限的公证人 的方式。 CA 认证中心 CA 认证中心是负责给计算机的服务端颁发数字证书(Certificate)的机构,类似于上面例子中给警察颁发证件的权威机构类似。当客户端访问服务端时,会检查服务端的证书是有效,确认无误后才会建立安全链接。 ...

五月 7, 2024 · 1 分钟

信息加密的基本方法

概述 在我很喜欢的一部(根据真实事件改编)的电影《模仿游戏》里面:著名的科学家图灵带领他的团队,花费两年的时间,费劲九牛二虎之力,在找到德军的话术口令后才得以破解了德军通讯加密装置 “英格玛”,为第二次世界大战取得胜利打下的坚实的基础。那么德军使用的通讯加密究竟是一种怎样的技术,这是我们今天要探讨的数据加密技术。数据的保密是对数据加密、解密的统称,用学院派的说法就是,**使用某种算法改变了信息原本的形态,使攻击者即使窃取了信息也因为没有对应的解密的方法也无法获取当信息的真实内容。**这就是信息保密的目的,对于信息的保密,可以在三个环节进行,分别是: 在客户端进行保密 在传输时进行保密(最复杂,也最有效) 在服务端进行保密 加密的强度 在安全领域大家都知道安全是区分等级的,不同应用的敏感信息重要性不同,所以需要的安全等级也不同,这个世界上没有绝对的安全,安全等级不可能无止境的拉满,任何安全手段都可以破解(只要花费足够的成本),想要更高级别的安全等级,就要付出更高的成本(工作量,算力)等。例如常见的加密技术可以说明这一点。加密的强度从低到高,分别有: 一:哈希算法:最常见的加密手段,对明文密码使用 MD5 等哈希摘要算法进行不可逆的哈希计算进行加密,示例: import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Hash { public static void main(String[] args) { String text = "yourPassword"; try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hashBytes = md.digest(text.getBytes()); StringBuilder hexString = new StringBuilder(); for (byte b : hashBytes) { hexString.append(String.format("%02x", b)); } System.out.println("MD5 Digest: " + hexString.toString()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } } 输出结果: MD5 Digest: 65a8e27d8879283831b664bd8b7f0ad4 这种方式,安全等级低,弱密码容易被彩虹表(预先进行摘要好的哈希表,进行反向破译)破击。 ...

四月 28, 2024 · 2 分钟

Cookie-Session 与 JWT 两种凭证管理方案的对比

概述 在上一篇文章我们聊完了授权的过程,在服务器对客户端完成授权之后,服务器会给客户端颁发对应的凭证,客户端持有该凭证访问服务端,服务器便能知道你是谁,你有什么权限等信息。这一章我们具体聊聊常见的凭证管理技术有哪些。 在软件架构中,关于凭证如何存储和传递,一直有两种不同的解决思路,两种不同的解决方式,实际上反映了两种不同的架构思路: 一种是把所有状态信息都放在服务器端 (Cookie-Session 方案) 一种是把所有状态将信息存储在客户端(JWT 方案) 在互联网早期,这个问题早就有了明确的答案。大多数应用都采用了 “Cookie-Session” 的方法,这种方法通过在服务器上存储用户状态,来实现用户身份的识别和信息的传递。这种方法在很长一段时间里都是主流。 然而,随着微服务和分布式系统的兴起,我们发现由于 CAP 的限制,服务器端存储状态信息的方式开始面临很多问题(微服务要求服务端本身是无状态,才能实现动态扩缩容)。这就迫使我们重新考虑被放弃的客户端状态存储方法。在这个背景下,JWT(JSON Web Token)的令牌的方案开始受到关注。JWT 是一种在客户端存储用户状态信息的方式,它允许用户在不同的服务器之间自由切换,而不需要重新登录。这种特性在分布式系统中非常有用。但是要明白,JWT 和 Cookie-Session 只是对授权信息存储的主体(客户端,服务端)不同,各有优势,合适场景不同,不存在谁比谁要先进的问题。在本节中,我们将探讨 Cookie-Session 和 JWT 两种方案的相同点和不同点,帮你更好地理解这两种方案的优缺点,以及它们在不同场景下的应用。 cookie-session 总所周知,因为 HTTP 是无状态协议,所以 Cookie-Session 的原理其实很简单,就是解决 HTTP 协议无状态的问题,在 RFC 6265 中定义了 HTTP 的状态管理机制,增加 Set-Cookie 指令,服务端向客户端发送一组信息(标识)示例: HTTP/1.1 200 OK Content-type: text/html Set-Cookie: session_token=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Path=/ 客户端收到指令后在此后一段时间的 HTTP 请求中都发给服务端会话信息(在 Header 中携带 cookie 信息),以便服务器区分不同的客户端: GET /profile HTTP/1.1 Host: www.example.com Cookie: sessionid=xyzasdzxc123789456 客户端的 Cookies 里通常只存储一个无意义,不重复的字符串,通常命名是 sessionid 或 jessionid ,服务端则根据该字符串作为 Key,和用户信息建立关联后存储在服务端的内存或者缓存中。再辅以一些超时自动清理的措施来管理会话。 ...

四月 24, 2024 · 2 分钟

基本的访问和授权模型:OAuth2 和 RBAC 的组合应用

概述 在安全管理系统里面,授权(Authorization)的概念常常是和认证(Authentication)、账号(Account)和审计(Audit)一起出现的,并称之为 4A。就像上一文章提到的,对于安全模块的实现,最好都遵循行业标准和最佳实践,授权也不例外。 作为安全系统的一部分,授权的职责如下: 确保授权过程的可控:常见的参考标准有 OAuth2、SAML2、CAS 等协议 确保授权结果的可控:常见的参考标准有 RBAC、ABAC 等授权模型 对于大多数应用来说,主流的做法是基于 OAuth2 + RBAC 的组合搭配实现授权。下面就从这两个方向展开聊聊。 RBAC RBAC(角色基础访问控制)是一种常见的权限管理方式。在这种模型中,系统根据用户的角色来分配权限,而不是直接分配给单个用户。这样可以简化权限管理和配置的复杂性。避免频繁的对用户进行权限操作。如下: 如果还有更复杂的访问控制需求,则可以在 RBAC0 的基础上可以扩展 RBAC1 (层次化 RBAC,角色之间有继承关系)和 RBAC2(受约束的 RBAC,角色之间有互斥关系)来提高系统的安全性和管理的便利性。还有 RBAC 3 等等。 对于大多数应用来说,通常都无需自己去实现这些理论的模型,应用遇到的安全问题大多都是相同的,具有普遍性,所以可以抽象到框架层面来解决,例如著名的 Spring Security 框架就提供 RBAC 模型的授权实现。 不过,需要特别说明的是,与具备通用性的访问控制权限相比,对于数据权限的控制则显的困难的多,用户能访问的数据权限通常与业务高度关联,具体到不同部门,不同角色,甚至指定人员可以访问的数据权限都不尽相同。完全不具备通用性,所以无法通过框架层面解决,就连 Spring Security 框架也未能提供数据权限的相关控制。只能有业务系统结合实际情况各自在业务层实现,这也是目前无法解决的问题。 OAuth 2 OAuth2 是一种业界标准的授权协议,允许用户授权第三方应用程序访问他们在其他服务提供者上的资源,而无需分享用户名和密码,它定义了四种授权交互模式,适用于各种应用场景: 授权码模式 隐式授权 用户模式 应用模式 OAuth2 通过发放访问令牌(Access Token)和刷新令牌来实现对受保护资源的访问控制。通过创新的使用访问令牌 Token 替代了用户密码,避免用户凭证的泄露。 授权码 授权码模式可以说是最安全的授权模式,综合考虑了各种风险和防范措置,但相对也是最复杂的授权协议,适合有服务端可以存储密钥(ClientSecret)的场景,授权流程如下: 看完授权码的过程,你可能会觉得好奇:为什么授权服务器要返回授权码,而不直接返回令牌呢 ? 返回授权码而不是直接返回令牌的设计主要是为了提高安全性,原因如下: 即使授权码被截获,攻击者因为没有客户端密钥无法获取访问令牌,客户端密钥只在服务器端保存,不会通过前端暴露。 在重定向回客户端应用的过程中,授权码会通过浏览器传输。如果直接传输访问令牌,一旦泄露,就会带来更高的安全风险。授权码则可以进行严格的限制(如一次性使用,很短的有效期),所以即使泄露也难以被利用。 在客户端使用授权码请求访问令牌时,授权服务器可以验证请求中包含的客户端密钥和重定向 URI 等信息,确保令牌的请求合法 另外令牌颁发的策略上,授权码模式下也使用长刷新令牌 + 短访问令牌的双令牌策略,来最大化减少 JWT 令牌无状态难回收的问题。因此,在服务端可以存储令牌的前提下,授权码模式可以说是大多数场景下的首选。 隐式授权 隐式授权模式对于实在没有服务端存储 ClientSecret 的纯前端应用提供接入支持。接入流程也比较简单,如下: ...

四月 15, 2024 · 1 分钟

生物识别标准技术的基本概述

概述 几乎所有的系统都会面临安全认证相关的问题,但是安全相关的问题是一个很麻烦的事情。因为它不产生直接的业务价值,而且处理起来复杂繁琐,所以很多时都容易被忽视。很多后期造成重大的安全隐患,往往都是前期的不重视造成的。但庆幸的是安全问题是普遍存在的,而且大家面临的问题几乎相同,所以可以制定行业标准来规范处理,甚至是可以抽出专门的基础设施(例如:AD、LDAP 等)来专门解决这类共性的问题。总之,关于安全问题非常复杂而且麻烦,对于大多数 99% 的系统来说,不要想着在安全问题领域上搞发明和创新,容易踩坑。而且行业的标准解决方案已经非常成熟了。经过长时间的检验。所以在安全领域,踏踏实实的遵循规范和标准就是最好的安全设计。 HTTP 认证 HTTP 认证协议的最初是在 HTTP/1.1标准中定义的,后续由 IETF 在 RFC 7235 中进行完善。HTTP 协议的主要涉及两种的认证机制。 基本认证 常见的叫法是 HTTP Basic,是一种对于安全性不高,以演示为目的的简单的认证机制(例如你家路由器的登录界面),客户端用户名和密码进行 Base64 编码(注意是编码,不是加密)后,放入 HTTP 请求的头中。服务器在接收到请求后,解码这个字段来验证用户的身份。示例: GET /some-protected-resource HTTP/1.1 Host: example.com Authorization: Basic dXNlcjpwYXNzd29yZA== 虽然这种方式简单,但并不安全,因为 base64 编码很容易被解码。建议仅在 HTTPS 协议下使用,以确保安全性。 摘要认证 主要是为了解决 HTTP Basic 的安全问题,但是相对也更复杂一些,摘要认证使用 MD5 哈希函数对用户的密码进行加密,并结合一些盐值(可选)生成一个摘要值,然后将这个值放入请求头中。即使在传输过程中被截获,攻击者也无法直接从摘要中还原出用户的密码。示例: GET /dir/index.html HTTP/1.1 Host: example.com Authorization: Digest username="user", realm="example.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="/dir/index.html", qop=auth, nc=00000001, cnonce="0a4f113b", response="6629fae49393a05397450978507c4ef1", opaque="5ccc069c403ebaf9f0171e9517f40e41" **补充:**另在 RFC 7235 规范中还定义当用户没有认证访问服务资源时应返回 401 Unauthorized 状态码,示例: HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="Restricted Area" 这一规范目前应用在所有的身份认证流程中,并且沿用至今。 Web 认证 表单认证 虽然 HTTP 有标准的认证协议,但目前实际场景中大多应用都还是基于表单认证实现,具体步骤是: ...

四月 7, 2024 · 1 分钟

理解 Kubernetes 的 Controller Manager

Controller Manager Controller Manager 是控制平面的一个重要组件,负责维护 Kubernetes 集群的整体状态。 流程: 在集群中 Controller Manager 主要做以下几件事情: 监听: Controller Manager 通过 API Server 监听集群中的资源状态变化。当资源状态发生变化时,Controller Manager 会收到通知。 决策: Controller Manager 会根据资源的定义和状态做出决策。如果一个 Deployment 的 Pod 数量低于预期,Controller Manager 会创建新的 Pod。 执行: Controller Manager 会根据决策,执行相应的操作。例如,如果要创建新的 Pod,Controller Manager 会调用 API Server 来创建 Pod。 常见的 Controller Kubernetes 中内置了许多 Controller,当资源状态发生变化时,Controller Manager 会通知这些 Controller 做出决策和执行操作。 Deployment Controller:负责部署和管理 Pod 副本。 ReplicaSet Controller:负责管理 Pod 副本的数量。 DaemonSet Controller:确保每个节点都运行指定的 Pod。 Job Controller:负责执行一次性任务。 CronJob Controller:负责按照指定的频率执行任务。 StatefulSet Controller:确保 Pod 的顺序性和持久性。 Cloud Controller Manager ...

十二月 13, 2023 · 7 分钟