架构05-架构安全性
零、文章目录
架构05-架构安全性
1、软件架构安全的重要性
- **系统安全:**不仅包括防御黑客攻击,还包括安全备份与恢复、安全审计、防治病毒等。
- **关注重点:**认证、授权、凭证、保密、传输安全、验证。
2、认证(Authentication)
(1)定义
- **定义:**系统如何正确分辨出操作用户的真实身份。
- **重要性:**即使是简陋的信息系统,也不会忽略用户登录功能。
- **认证、授权与凭证:**解决“你是谁?”、“你能干什么?”、“你如何证明?”三个基本问题。
(2)认证的标准
- 历史背景:
- **J2EE 1.2:**引入了四种内置认证方案(Client-Cert、Basic、Digest、Form)和相关接口。
- **架构安全性的经验原则:**以标准规范为指导、以标准接口去实现。
(3)基于通讯协议的认证
- HTTP 认证框架:
- **工作流程:**客户端请求资源,服务端返回 401 Unauthorized,客户端生成凭证,服务端验证。
- 常见认证方案:
- **Basic:**用户名和密码经过 Base64 编码。
- **Digest:**用户名和密码加盐后通过哈希算法取摘要。
- **Bearer:**基于 OAuth 2.0 规范。
- **HOBA:**基于自签名证书的认证方案。
- **风险:**Basic 和 Digest 认证存在中间人攻击的风险。
(4)基于通讯内容的认证
- Web 认证(表单认证):
- **特点:**高自由度,允许开发者自行设计认证交互细节。
- **优点:**灵活性高,可以支持多种登录方式和验证码。
- **缺点:**缺乏标准化,容易出现安全漏洞。
- WebAuthn:
- **定义:**FIDO 联盟领导起草的无密码认证标准。
- **工作流程:**注册和登录流程均采用非对称加密,提高安全性。
- **优势:**消除密码输入错误和验证码需求,提高用户体验和安全性。
(5)Java 技术体系中的认证实现
- JAAS:
- **历史:**Java 1.3 时代的认证授权服务。
- **特点:**同时面向代码级和用户级安全,过于复杂,应用不广泛。
- 私有安全框架:
- **Apache Shiro:**便捷易用。
- **Spring Security:**功能复杂强大,广泛应用于 Spring 生态系统。
3、授权
(1)授权的基本概念
- **授权概念:**授权解决“你能干什么”的问题,常与认证、审计、账号(AAAA)一同出现。
- **授权的重要性:**在程序中广泛应用于类或方法的范围控制,如
public
、protected
、private
等。 - **授权与访问控制:**授权过程通常涉及访问控制,两者应分开但常常混用。
- **多方系统中的授权:**涉及第三方系统时,授权过程更加复杂,需要解决如何既让第三方访问资源又保护用户敏感数据的问题。
- **常见授权协议:**OAuth 2.0 和 SAML 2.0。
(2)OAuth 2.0 授权协议
- 工作原理
- **OAuth 2.0 定义:**RFC 6749 中定义的国际标准,主要用于第三方应用的认证授权。
- **适用场景:**适用于涉及第三方系统的情况,单体架构系统无需引入。
- **实际案例分析:**The Fenix Project 网站
- **流程:**Markdown 文章 -> GitHub 仓库 -> Travis-CI 检测 -> Vuepress 编译 -> GitHub Pages -> CDN 缓存刷新。
- **授权问题:**Travis-CI 需要访问 GitHub 仓库,但不能泄露用户密码,也不能有过多权限。
- OAuth 2.0 解决的问题
- **密码泄漏:**防止第三方应用泄露用户密码。
- **访问范围:**限制第三方应用的访问权限。
- **授权回收:**方便回收授权,不影响其他应用。
- OAuth 2.0 核心机制
- **令牌机制:**用令牌代替密码,令牌可以设定访问范围和时效性,每个应用持有独立的令牌。
- OAuth 2.0 授权模式
- 授权码模式:
- 步骤:
- 第三方应用注册获取 ClientID 和 ClientSecret。
- 用户导向授权服务器,提供 ClientID 和回调 URI。
- 用户同意授权,授权服务器返回授权码。
- 第三方应用用授权码和 ClientSecret 换取令牌。
- 授权服务器验证后发放令牌。
- 资源服务器根据令牌提供资源。
- **特点:**最严谨,安全性高,但调用过程复杂。
- 步骤:
- 隐式授权:
- 步骤:
- 用户导向授权服务器,提供 ClientID 和回调 URI。
- 用户同意授权,授权服务器直接返回访问令牌。
- **特点:**简化了授权过程,不需要服务端支持,但安全性较低。
- 步骤:
- 密码模式:
- 步骤:
- 第三方应用用用户名和密码换取令牌。
- **特点:**适用于高度可信的第三方应用,认证和授权合一,安全性依赖用户和第三方应用。
- 步骤:
- 客户端模式:
- 步骤:
- 第三方应用用 ClientID 和 ClientSecret 换取令牌。
- **特点:**最简单,适用于管理操作或自动处理场景,没有资源所有者。
- 步骤:
- 授权码模式:
- **其他授权模式:**设备码模式
- 步骤:
- 设备从授权服务器获取 URI 和用户码。
- 用户输入用户码。
- 设备循环尝试获取令牌。
- **特点:**适用于无输入设备的授权场景,如手机锁网解锁。
- 步骤:
(3)RBAC权限管理模型
- 引言
- **主题:**系统如何确保授权的结果可控
- **背景:**授权的结果用于对程序功能或资源的访问控制
- **模型:**基于角色的访问控制(RBAC)
- RBAC 的基础概念
- **核心问题:**谁(User)拥有什么权限(Authority)去操作(Operation)哪些资源(Resource)
- **传统方法:**直接在用户对象上设定权限,导致操作量大、出错概率高
- RBAC 解决方案:
- **角色(Role):**权限从用户身上剥离,绑定到角色上
- **许可(Permission):**抽象权限的具象化体现,解耦操作与资源之间的多对多关系
- RBAC 的概念间关系
- **最小特权原则:**角色拥有完成工作所需最小权限
- 角色关联与约束:
- **继承性:**角色可以继承其他角色的权限
- **互斥性:**角色之间可以有互斥关系,防止越权操作
- RBAC 的访问控制
- **垂直权限:**功能权限,易于抽象和管理
- **水平权限:**数据权限,难以抽象,需具体到用户和数据行、列
- Spring Security 实现:
- **Role 和 Authority:**共享同一存储结构,差异在于语义和使用方式
- **灵活性:**允许用户自行决定权限分配方式
4、凭证
(1)Cookie-Session 机制
- HTTP 协议的无状态特性
- **无状态特性:**HTTP 协议对事务处理没有上下文的记忆能力,每个请求都是独立的。
- **重要性:**无状态特性简化了服务器与客户端的交互,避免了复杂的协调工作。
- **定义:**HTTP 的状态管理机制,通过
Set-Cookie
指令在客户端存储信息。 - 工作原理:
- 服务器发送
Set-Cookie
指令,客户端在后续请求中附带Cookie
。 - 服务器通过
Cookie
区分不同的用户。
- 服务器发送
- 优点:
- 安全性高:状态信息存储在服务器端,客户端只需传输一个标识符。
- 服务端有主动的状态管理能力,可以随时修改或清除用户状态。
- 缺点:
- 分布式环境下的 CAP 问题:一致性、可用性和分区容错性不可兼得。
- 需要在多节点间同步 Session,增加了复杂性和成本。
(2)JWT 令牌
- **定义:**JSON Web Token,广泛用于分布式系统中的认证授权。
- 结构:
- **Header:**描述令牌类型和签名算法。
- **Payload:**携带用户信息和权限信息。
- **Signature:**确保信息未被篡改,由服务器使用密钥签名。
- 优点:
- 无状态:服务端不需要存储用户状态,便于水平扩展。
- 便于 RESTful API 设计,支持无状态服务。
- 缺点:
- 令牌一旦签发,到期前始终有效,难以主动失效。
- 重放攻击问题:需要在信道层次解决。
- 令牌大小受限,不适合携带大量信息。
- 泄露风险:客户端存储令牌可能被窃取。
(3)JWT 与 Cookie-Session 的对比
- 适用场景:
- **Cookie-Session:**单节点服务,需要强状态管理。
- **JWT:**分布式系统,需要无状态服务。
- 安全性:
- **Cookie-Session:**状态信息存储在服务器端,安全性较高。
- **JWT:**客户端存储令牌,需注意防止泄露。
- 扩展性:
- **Cookie-Session:**多节点同步复杂,影响性能。
- **JWT:**无状态,易于水平扩展。
(4)其他凭证实现方案
- 其他凭证实现方案:
- **Basic Auth:**简单但安全性低,适合内部系统。
- **Digest Auth:**比 Basic Auth 安全,但仍有限制。
- **OAuth 1.0a:**早期的 OAuth 版本,使用签名机制。
- **OpenID Connect:**基于 OAuth 2.0 的身份认证协议。
- 应用场景和优缺点:
- **Basic Auth:**适用于内部系统,简单但安全性低。
- **Digest Auth:**适用于需要基本安全性的场景,但不支持多步骤认证。
- **OAuth 1.0a:**适用于需要高级安全性的场景,但实现复杂。
- **OpenID Connect:**适用于需要身份认证和授权的场景,兼容 OAuth 2.0。
5、保密
(1)保密的定义
- **保密:**加密和解密的统称,通过特殊算法改变信息数据,使未授权用户即使获得加密信息也无法了解真实内容。
(2)保密的分类
- 信息在客户端时的保密
- 信息在传输时的保密
- 信息在服务端时的保密
(3)保密的强度
- **成本:**追求更高安全等级需要更多工作量和算力消耗。
- **分级:**国家保密法将秘密信息划分为秘密、机密、绝密三级,信息安全也应有所取舍。
(4)用户登录的保密手段
- 哈希摘要
- **优点:**防止信息在传输过程中被逆推出原信息。
- **缺点:**无法防止弱密码被彩虹表攻击破解。
- 加盐
- **优点:**防御彩虹表攻击。
- **缺点:**无法防止加密结果被监听、窃取后直接发送给服务端进行冒认。
- **动态盐值 **
- **优点:**每次加密结果不同,防止重放攻击。
- **缺点:**协商过程复杂,难以阻止其他服务的重放攻击。
- 动态令牌
- **优点:**防止重放攻击。
- **缺点:**无法抵御传输过程中被嗅探而泄露信息的问题。
- HTTPS
- **优点:**防御链路上的恶意嗅探,解决重放攻击问题。
- **缺点:**存在客户端被攻破、服务端被攻破、CRL更新不及时等风险。
- **绝对安全的可能性 **
- **一次性密码:**理论上绝对安全,但实际应用中不可行。
(5)客户端加密的意义
- 争议
- **观点1:**客户端加密对防御泄密无意义,HTTPS是唯一实际可行的方案。
- **观点2:**客户端加密有助于防止密码在服务端被滥用。
- 传输链路的不安全性
- **中间人攻击:**劫持客户端到服务端之间的节点,注入恶意代码,客户端加密无法完全防御。
(6)服务端的信息保密
- 密码创建过程
- **客户端注册:**用户输入明文密码。
- **客户端哈希摘要:**选择合适的哈希算法(如MD5、SHA1等)。
- **加盐处理:**防御彩虹表攻击。
- **慢哈希函数:**引入BCrypt等慢哈希函数,防止暴力破解。
- **服务端加盐:**生成随机盐值,混合客户端哈希值,再次哈希。
- **数据库存储:**存储最终的密文和盐值。
- 密码验证过程
- **客户端登录:**用户输入明文密码,经过相同加密过程传输。
- **服务端验证:**从数据库中取出密文和盐值,计算摘要结果。
- **比较结果:**判断计算结果与数据库存储的哈希值是否相同。
6、传输
(1)摘要(哈希)
- 特点:
- **易变性:**输入发生任何细微变动,输出结果会产生极大变化。
- **不可逆性:**从摘要结果无法逆向还原出输入值。
- 作用:
- 校验信息完整性,确保信息在传输过程中未被篡改。
- 用于生成哈希值,如文件下载时的校验码。
(2)对称加密
- 特点:
- 加密和解密使用相同的密钥。
- 执行速度快,适用于大量数据的加密。
- 优劣势:
- **优点:**设计简单,加密效率高。
- **缺点:**密钥管理困难,特别是在多方通信时。
- 应用场景:
- 数据传输、文件加密等。
(3)非对称加密
- 特点:
- 密钥分为公钥和私钥,公钥公开,私钥保密。
- 加密和解密使用不同的密钥。
- 优劣势:
- **优点:**解决了密钥分发的难题。
- **缺点:**计算复杂度高,性能较差,不适合大量数据的加密。
- 应用场景:
- 密钥交换、数字签名等。
(4)混合加密
- 原理:
- 结合对称加密和非对称加密的优点。
- 使用非对称加密安全传递对称密钥,再用对称加密高效传输大量数据。
- 应用场景:
- 安全通信协议,如TLS/SSL。
(5)数字签名
- 原理:
- 使用私钥对摘要结果进行加密,生成签名。
- 使用公钥对签名进行解密,验证签名的有效性。
- 作用:
- 确保信息的完整性和不可抵赖性。
- 安全性问题:
- 公钥的分发和验证是关键,网络传输过程中可能被篡改。数字证书与传输安全层
(6)数字证书的作用与实现
- 问题背景
- **公钥分发的挑战:**在网络世界中,公钥的分发面临被篡改的风险,如何确保每个服务获取的公钥是授权服务器希望其获取的?
- **解决方案:**数字证书通过权威的证书颁发机构(CA)来解决公钥的可信分发问题。
- 数字证书的实现
- **基于权威公证人的信任:**类似于现实世界中的公安局,CA作为权威机构,负责发放和管理数字证书。
- 公开密钥基础设施(PKI):
- **定义:**PKI是一组硬件、软件、参与者、管理政策与流程组成的基础架构,用于创造、管理、分配、使用、存储以及撤销数字证书。
- 角色:
- **证书颁发机构(CA):**负责发放和管理数字证书。
- **注册管理中心(RA):**确保公钥和个人身份的链接,防止抵赖。
- 数字证书的内容
- **版本号(Version):**证书使用的X.509标准版本。
- **序列号(Serial Number):**证书的唯一标识符。
- **签名算法标识符(Signature Algorithm ID):**证书所用的数字签名算法。
- **认证机构的数字签名(Certificate Signature):**使用证书发布者私钥生成的签名。
- **认证机构(Issuer Name):**证书颁发者的可识别名。
- **有效期限(Validity Period):**证书的有效时间范围。
- **主题信息(Subject):**证书持有人的唯一标识符。
- **公钥信息(Public-Key):**证书持有人的公钥及其相关参数。
(7)传输安全层的实现
- 传输安全层的必要性
- **隔离复杂性:**通过分层的方式,将复杂的加密和安全过程隐藏起来,使上层应用无需关心底层的安全细节。
- 历史发展:
- **SSL 1.0:**1994年,Netscape公司开发,未正式发布。
- **SSL 2.0:**1995年发布,存在严重漏洞,未大规模使用。
- **SSL 3.0:**1996年发布,广泛应用于Web网络安全层。
- **TLS 1.0:**1999年,互联网标准化组织将SSL改名为TLS,形成国际标准。
- **TLS 1.1:**2006年发布,增加对CBC攻击的保护,但使用较少。
- **TLS 1.2:**2008年发布,支持90%以上的互联网HTTPS流量。
- **TLS 1.3:**2018年发布,显著提升访问速度,减少握手次数。
- TLS 1.2的握手过程
- **第一步:**客户端请求(Client Hello)
- **内容:**支持的协议版本、客户端生成的随机数、SessionID、支持的密码学算法套件、支持的数据压缩算法、其他可扩展信息。
- **第二步:**服务器回应(Server Hello)
- **内容:**确认的协议版本、服务器生成的随机数、SessionID、选定的密码学算法套件、选定的数据压缩方法、其他可扩展信息、服务器证书、密钥协商消息。
- **第三步:**客户端确认(Client Handshake Finished)
- **内容:**客户端证书(可选)、PreMasterSecret、编码改变通知、客户端握手结束通知。
- **第四步:**服务端确认(Server Handshake Finished)
- **内容:**编码改变通知、服务器握手结束通知。
- **第一步:**客户端请求(Client Hello)
- 安全性保障
- **加密传输:**使用对称加密算法和协商的密钥进行数据加密。
- **防篡改:**通过哈希值校验确保数据未被篡改。
- **身份验证:**通过证书验证服务器和客户端的身份。结构化总结
7、验证
(1)数据验证的重要性
- **安全问题频发:**数据验证不严谨导致的安全问题比其他安全攻击更为常见。
- **风险多样:**数据质量问题带来的风险有高有低,高风险的数据问题可能导致重大损失。
- **常规但重要:**虽然数据验证是一项常规工作,但它对系统的稳定性和数据一致性至关重要。
(2)数据验证的层级讨论
- **前端校验:**处理最基础的数据问题,如空值、格式等。
- 服务端校验:
- **Controller 层:**进行格式校验。
- **Service 层:**进行业务校验。
- **持久层:**确保数据写入数据库前的质量。
(3)Java Bean Validation 的优势
- **预置格式验证:**无业务含义的格式验证可以预置。
- **重用业务验证:**有业务含义的校验可以重用,集中管理。
- **避免污染业务代码:**将验证行为从业务逻辑中剥离,避免防御代码污染业务代码。
- **统一执行校验:**多个校验器可以统一执行,统一返回校验结果。
(4)自定义校验注解示例
- **@UniqueAccount:**确保用户对象唯一,不与数据库中任何已有用户的关键信息重复。
- **@AuthenticatedAccount:**确保传入的用户对象与当前登录用户一致。
- **@NotConflictAccount:**确保用户对象中的信息与其他用户无冲突。
(5)校验器实现
- **AuthenticatedAccountValidator:**检查当前登录用户。
- **UniqueAccountValidator:**检查用户信息是否唯一。
- **NotConflictAccountValidator:**检查用户信息是否与其他用户冲突。
(6)编码建议
- **预置默认提示信息:**确保校验不通过时用户能获得明确的修正提示。
- **分离格式校验和业务校验:**不带业务含义的格式校验注解放在类定义中,带业务逻辑的校验注解放在类定义外。
(7)分组校验
- **处理不同操作:**通过分组校验处理“新增”、“修改”、“删除”等不同操作中的校验需求。
(8)最佳实践总结
- **使用 Java Bean Validation:**遵循 JSR 380 规范,利用其预置的校验注解和自定义校验注解。
- **集中管理校验:**将校验行为集中管理,提高代码的可维护性和可扩展性。
- **统一处理校验结果:**提供统一的异常处理机制,确保用户获得一致的反馈。