欢迎来到我的博客

肖斌

你好,我是肖斌。这里记录我的技术笔记与思考。

了解更多关于我以及我的项目 Visual NCE,请点击这里。

📱 微信:18198971094

架构不是高级词汇,它是你代码能活多久的决定因素

最近在读 Robert C. Martin 的《架构整洁之道》,前两章读完就有不少想说的。这本书不是那种给你一套框架让你照搬的类型,它更像是在帮你重新理解:你每天写的代码,到底在服务什么。 把前两章的核心观点整理一下,加上我自己的理解和一些工作中踩过的坑。 “设计"和"架构"是同一件事 很多人一听到"架构"两个字就觉得是高层决策,是技术总监才需要操心的事。“设计"嘛,那就是普通开发者日常写代码时的选择。行业里流传着这种隐隐约约的分工:架构管大的,设计管小的。 Uncle Bob 上来就把这个观念给拆了。 他说,设计和架构没有本质区别。底层的代码细节和高层的系统结构,共同组成了一个完整的设计。你不可能画一张漂亮的架构图,然后底层代码随便写——架构图里的每一个决策,最终都得落到具体的代码上。反过来也一样,如果底层的砖头质量不行,你再怎么画图纸也盖不出好房子。 这个观点听起来简单,但你仔细想想,它其实在说一件挺颠覆的事:不存在"只负责架构不管代码"的架构师,也不存在"只管写代码不用想架构"的程序员。 架构的终极目标,不是"好看” 那架构到底在追求什么?Uncle Bob 给了一句非常干脆的话: 软件架构的目标是:为了在修改和维护系统时,最大程度地降低人力成本。 注意,不是"系统跑得多快”,不是"用了什么流行技术",而是——你改这个系统的时候,花的人力有多少。 如果一个系统上线很快,初期产出很高,但随着版本迭代,开发成本越来越高、改一个小功能要动半天、修一个 Bug 冒出三个新 Bug——那它的架构就是失败的,不管当初用了多先进的框架。 书里有一组生产力曲线,我读完之后印象特别深。 项目早期,大家赶着上线,不管什么架构不架构的,先把功能怼出来。生产力看起来特别高——需求一提,代码就出。但到了版本三四之后,你会发现每加一个功能,要改的地方越来越多。以前两天能做完的事,现在要一周。不是因为功能本身变复杂了,而是之前写的那些代码已经缠在一起了,动一根线就牵出一坨。 到项目后期,工程师 100% 的时间都在"收拾烂摊子"——修以前的 Bug、小心翼翼地绕开已有的逻辑、想办法在一坨耦合的代码里塞一个新功能。真正用于创造价值的时间?几乎为零。 我见过太多次这种场景了。最可怕的不是一开始就烂,而是一开始看起来很好——因为那时候代码量还少,怎么写都能跑。等你意识到架构出了问题的时候,通常已经来不及了。 “先上线,以后再重构"是个谎言 书里专门批了一个观点,我觉得特别解气。 这个你肯定听过:“我们先把功能做出来,以后再重构。” 每个项目初期都会有人说这句话,说的人通常是产品经理或者老板,偶尔是技术负责人自己。 问题是,“以后"永远不会来。 因为一旦你开始往一个没有架构的系统上堆功能,每一次"以后再说"都会让重构的成本变得更高。到最后你面对的选择不是"现在重构还是以后重构”,而是"继续在烂泥里走还是整个系统推倒重来”。推倒重来谁都不敢,所以就继续在烂泥里走。于是你就看到了那条生产力曲线一路往下滑。 Uncle Bob 在书里展示了一组 TDD 方法的对比数据——采用测试驱动开发的团队,每个迭代周期的耗时保持稳定;不采用 TDD 的团队,耗时在后期明显上升。 这个数据验证了一个我以前不太信但现在越来越信的观点: 要想跑得快,先要跑得稳。 不是说你一开始就要搞一个完美架构——那叫过度设计。而是说,你不能用"先不管质量"来换取速度。那种速度是假的,是预支未来的。你今天省掉的那半天架构思考,三个月后会变成三周的痛苦重构。 我自己来说,以前也经常觉得"先跑起来再说",结果每次都后悔。而且后悔的点特别一致:不是因为功能做不出来,是因为改不动。这大概就是 Uncle Bob 说的——架构设计失败的标志,不是系统不能用,而是系统不能改。 你的代码提供了两种价值,大多数人只看到了一种 第二章讲了一个更深层的问题:软件系统提供两种完全不同的价值——行为价值和架构价值。 行为价值很好理解。软件实现了业务需求,用户能用,能产生收益——这就是行为价值。写代码让程序按需求跑起来,修 Bug 让它不出错。大多数程序员认为这就是他们全部的工作。 架构价值就没那么直观了。它指的是软件保持"软"的能力——也就是说,当需求变化的时候,你能多容易地去修改它。 这两个东西,用现在流行的说法,一个叫功能性需求,一个叫非功能性需求。功能性需求是"系统能做什么",非功能性需求是"系统改起来有多方便"。 问题在于:功能性需求是看得见的,你做了什么功能,用户立刻感知到。非功能性需求是看不见的,系统改起来方不方便,只有下一次改的时候才知道。所以在日常决策中,几乎所有人都会优先满足功能性需求,架构的事"以后再说"——又是"以后再说"。 书里有一段话我觉得写得特别到位: 如果你问业务部门,是否想要能够变更需求,他们的回答一般是肯定的,而且他们会加一句:完成现在的功能比实现未来的灵活度更重要。但讽刺的是,如果事后业务部门提出了一项需求,而你的预估工作量大大超出他们的预期,这帮家伙通常会对你放任系统混乱到无法变更的状态而勃然大怒。 这段话简直是在描述我经历的每一家公司。 业务部门说"先做功能",你就先做功能。做到后来改不动了,业务部门反过来骂你"怎么这么慢"。他们不知道(也不关心)系统变慢的原因是什么,他们只看到结果——你越来越慢了。然后他们就觉得你不行。 紧急的事和重要的事,很少是同一件 Uncle Bob 用了艾森豪威尔矩阵来解释这两种价值之间的冲突。 ...

三月 8, 2026 · 1 分钟

代码是副产品:AI Coding 时代,真正的源码变了

最近在读 Stanford 的 AI 编程课程,有一篇阅读材料,引发了我的思考和关注。 文章的题目叫《Specs Are the New Source Code》,作者是 Ravi Mehta 和 Danny Martinez。观点很简单,但说透了会让人不太舒服:在 AI Coding 的时代,代码正在变成一种副产品。真正的源码,是你写的那份 Spec。 我想用自己的语言把这件事再说一遍,因为它影响的不只是产品经理,也在影响每一个写代码的人。 先说清楚 Vibe Coding 是什么 Vibe Coding 是一种新的编程方式:你把需求描述给 AI,AI 生成代码,你看结果、调整方向、继续迭代。写代码这件事本身,变成了一个被 AI 大量承担的环节。 举个你可能已经在做的事:用 Claude Code 或者 Codex 描述一个功能,五分钟后 AI 给你一个可以跑的版本;不满意就改 Prompt 再跑一次;跑通了就继续往前走。这个过程里,你几乎不直接写代码,但你是整个过程的导演。 这件事带来的变化,比很多人意识到的要深。 代码变便宜了,但不是所有东西都变便宜了 当代码可以在几分钟内生成,当你不满意可以随时扔掉重来——代码的边际成本开始无限接近于零。 这不是说代码不重要了。运行着的代码当然重要。但生产一行代码的成本已经不再是瓶颈。以前你要花几天写一个功能,现在可能几个小时就有了。 那瓶颈在哪? 在于你到底想要什么,以及你能不能把"想要什么"说清楚。 Spec 为什么成了新的源码 原文提出了一个概念叫 Lossy Projection(有损投影),我觉得这是全文最有价值的一个洞察。 代码是你意图的一次有损压缩。它告诉你"做了什么",但不告诉你"为什么这么做"、“边界条件是什么”、“什么情况下算成功”。代码里没有上下文,没有决策理由,没有你和用户之间的那些对话。 写完的代码是静态的,它记录的是一个历史时刻。 而一份好的 Spec 不一样。它包含了意图、方法、验收标准,以及做决策时的上下文。它不只能生成代码,还能生成文档、测试用例,甚至能在三个月后帮你回忆起"当时为什么这么设计"。 换句话说,代码是从 Spec 里生成出来的,而不是反过来。丢掉代码可以重新生成,但如果你丢掉了那份 Spec,你就真的丢掉了那个决策本身。 这是为什么说 Spec 是新的源码:它才是那个不可再生的东西。 工作流变了 原文对比了新旧两种开发流程: ...

三月 6, 2026 · 1 分钟

给 AI 装上 USB-C:MCP 协议工作原理完整拆解

最近在梳理 MCP 协议的体系,在梳理完成后顺手整理了一篇笔记,但发现有两件事一直没被说清楚,我想在这篇文章里专门拆一遍。 第一个问题:USB 的比喻说了等于没说。 你一定见过这种解释:「MCP 就像给 AI 装上了 USB 接口,什么设备都能插。」听起来很直观,但仔细想想,这个比喻根本没有回答任何问题——USB 到底是什么?它解决的是什么问题?为什么没有 USB 之前不行?这些全没讲清楚,读者离开还是一头雾水。 第二个问题:「模型越强,MCP 就会被淘汰」这个说法站不住脚。 有一种流行的观点认为:现在需要 MCP 是因为模型能力不够,等模型足够强了,它自己就能直接理解和操作任何系统,MCP 这层协议就没用了。这个逻辑听起来合理,但我认为它误解了 MCP 解决的是什么层面的问题。 这篇文章我把这两个问题都解释清楚。读完之后,你至少能说清楚 MCP 是什么、它在底层怎么工作、以及为什么它不会因为模型变强而消失。 没有 MCP 之前,AI 是怎么接工具的 先说痛点。 在 MCP 出现之前,如果你想让一个 AI 应用接入某个外部工具——比如一个数据库、一个 API、一个本地文件系统——你需要为每一个工具单独写一套集成代码。每个工具的认证方式不同、数据格式不同、错误处理逻辑不同,你需要逐一搞定。 更麻烦的是:同一个工具,如果你在不同的 AI 应用里用——比如 Cursor 和你自己写的聊天机器人——你得在每个地方各写一遍。没有复用,没有标准,全是一次性的胶水代码。 这种状态下,AI 就像一个大脑很聪明、但手脚被绑着的机器。它知道怎么分析,但获取信息的每一条路都是单独打通的。 这就是 MCP 要解决的核心问题:怎么给 AI 一个通用的接口,让它能以标准化方式接入任何外部工具,而不是每次都重新焊线。 MCP 是什么 Model Context Protocol,模型上下文协议。 本质上,它是一个通信标准——规定了 AI(客户端)和工具(服务端)之间,用什么格式说话、按什么顺序交互。 底层协议是 JSON-RPC 2.0,一种通用的请求/响应格式。无论服务器背后是 Python 写的还是 Go 写的,无论是本地数据库还是云端 API,发出来的消息包都长得一样。AI 不需要分别学不同工具的「语言」,对接一个标准就够了。 这里要说一下开头提到的 USB 比喻。课程里用的其实是 USB-C 而不是普通的 USB,这个细节很重要。 ...

三月 2, 2026 · 3 分钟

照抄 OpenAI 工程师的 Codex 用法:一套可直接复制的 Prompt 工作流

用了 AI 编程工具这么久,我发现一件很尴尬的事。 大多数人其实不是在用它编程,而是在用它写代码。看起来很像,但本质不同。 写代码是:你知道要做什么,你只是让它帮你打字。 编程是:你要决策架构、排查问题、控制风险、把一堆不确定性变成可交付的东西。 用 AI 工具“打字”很容易,但真正的工程问题,比如接手一个陌生系统、做一次跨模块重构、排查一个线上诡异 bug,很多人还是卡壳。不是工具不够强,是根本不知道应该往哪个方向问、怎么问、问完之后怎么推进。 最近我看了 OpenAI 公开的一份 PDF:《How OpenAI uses Codex》。这份文档讲的是他们自己的工程师怎么在日常工作里使用 Codex,覆盖了 7 类高频场景,以及他们沉淀下来的最佳实践。 原文链接:How OpenAI uses Codex 读完之后我最大的感受是:他们并没有把 Codex 当成一个更聪明的自动补全,而是把它当成工程流程里的一个“标准件”,嵌进了真实的工作节奏里。 这篇文章我把这份 PDF 拆了一遍,用我自己的语言整理出两件事:他们在哪 7 个场景里高频使用 Codex,以及他们总结出来的最佳实践是什么。你可以直接对照自己的工作方式,看哪里能搬过来用。 OpenAI 的 7 个高频用法 代码理解:把陌生系统变成“可提问的东西” 接手一个陌生系统,最折磨人的不是代码量,是那种“不知道从哪下手”的感觉。 不知道核心逻辑在哪,不知道模块之间怎么依赖,不知道一个请求进来之后到底走了哪条路。这种情况下你甚至没办法开始工作,更别说 oncall 时要在压力下快速定位。 OpenAI 的工程师用 Codex 做的第一件事,往往不是写代码,而是“问系统”:认证逻辑在哪、请求链路是什么、哪个模块如果出问题会影响哪里。那些“理应存在但没人写”的文档,也顺手让它生成。 还有一个细节很值得学:修完 bug 之后不是关掉对话,而是接着问:“同类问题还可能出现在哪?”这一步,把一次修复变成了一次预防性扫描。 重构与迁移:一致性才是真正的难点 重构最难的不是“改”,是“改得一致”。 你改了这个文件里的 API 调用,但仓库里还有另外八个地方用的是旧写法。你改完上线,线上炸了,然后才发现漏了一处。这种事情发生过一次,你就会对跨文件改动产生本能恐惧。 OpenAI 的工程师处理这类任务的方式是:先扫描全仓库,找出所有受影响的地方,把影响范围总结出来,然后再动手。不是蒙眼改,而是先弄清楚边界。 从拆分大模块、替换旧模式,到把紧耦合代码改成可测结构,Codex 做的是把一致性工作批量化,而不是帮你逐个文件手动改。 性能优化:先找到真正在痛的地方 性能问题最坑的一点是:你以为在慢的地方,往往不是真正慢的地方。 你去优化一个“看起来慢”的循环,但真正瓶颈可能是另一个每次请求都反复执行的昂贵操作,或者是一段没加缓存的 DB 查询。肉眼 review 很难发现这些,因为你不知道它在生产上到底跑了多少次。 ...

三月 1, 2026 · 2 分钟

理解乐观锁 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(); } } } 输出结果: ...

四月 28, 2024 · 2 分钟