API 访问控制最佳实践

API 访问控制最佳实践


需求调研

  1. 使用多云服务意味着依赖多种不同 API,默认需要一一创建对应账号。
  2. 同一账号下多用户间共享云账号密钥认证身份时,密钥有泄露风险。
  3. 同一账号下多用户协同操作时,各用户根据工作所需被授权使用的资源不同,需要对资源有细粒度控制。
  4. 在跨域/跨服务的场景中,一级或顶级域名不同的网站,无法读到彼此的客户端信息。

解决方案

  1. 使用统一身份认证服务(Identity and Access Management,IAM),控制用户对云服务和资源的访问。
  2. 当多用户协同操作时,各用户独立,避免与其他用户共享云账号密钥,并按需为各用户分配最低权限(仅授予执行操作需要的相关权限)。
  3. 规范 API 调用的认证鉴权,建立信任,通过用户联合身份认证使用已有账号登录多方平台。

实施细节

1. 明确基本用户

根据当前服务是否支持在控制台(Console)或通过 API 进行访问控制,将 Console 用户与 API 用户分离。
不建议为同一个 IAM 用户同时创建用于控制台操作的登录密码和用于 API 操作的访问密钥。通常客户端只创建登录密码,系统或应用程序只创建访问密钥。

  • Console 用户
    • 建议凭证:密码(常见凭证)。密码一般用于登录控制台,也可通过支持密码认证的开发者工具如 API、SDK 等访问资源和服务。
    • 密码使用者:客户端用户。
    • 安全建议一:仅使用密码登录控制台。
    • 安全建议二:定期修改密码。
  • API 用户
    • 建议凭证:访问密钥(Access Key,使用编程访问时的身份凭证)。使用支持密钥认证的开发者工具如 API、SDK 等访问资源和服务,还用于加密、签名验证。
    • 密钥使用者:系统,应用程序。
    • 安全建议一:妥善保管,避免泄露访问密钥(不在未加密的代码中嵌入,也不在同一账号的多用户间共享)。
    • 安全建议二:定期轮换密钥。
2. 分析访问动机
  • Console 用户的使用主体(实体用户)访问资源和服务
  • API 用户通过开发者工具编程访问资源和服务
  • Console 用户的非使用主体(虚拟用户)访问资源和服务
3. 集中控制资源

默认云账号是云资源的完全掌控者,使用云账号集中管理云资源。通过云账号创建的用户对云账号名下拥有的资源仅具备使用权而非拥有权。当用户离开所属组织时,实例或数据不会丢失。

  • 新用户:创建独立的用户,同时为其设置独立的安全凭证(登录密码或访问密钥)或仅设置临时凭证,并授权其访问最低权限范围内的资源。
  • 无效用户:及时移除。移除用户即可撤销其名下所有资源使用权限。
4. 访问控制扩展
  • 跨域/跨服务问题解决方案:引入 Security Token Service (STS)
    • 引入临时安全凭证和临时访问权限管理服务,作为 IAM 服务的扩展,解决跨域/跨服务联合身份认证的需求。
    • 所授权的用户可以获取一个自定义时效和访问权限的临时访问令牌。
  • 优势:考虑跨域/跨服务的联邦用户不能创建访问密钥的情况,使认证授权更可控。

操作结果

建立安全完善的用户身份认证、资源访问控制体系,有效优化账号、资产的安全管理。

API 参考

功能简述

IAM 服务

用于安全管理用户身份和对资源的访问权限。
从四个层面考虑 API 的安全调用:Authentication(身份认证),Authorization(访问控制),Federation(联合认证),Delegation(最小权限)。

  1. 安全访问
    • 安全登录(Authentication
      • IAM Console 用户提供所属账号名、IAM 用户名、IAM 用户密码信息,实体 IAM 用户通过 IAM 用户登录链接(非实体用户通过一次性访问链接)登录控制台。
      • IAM API 用户通过访问密钥登录。
    • 最小权限原则(Delegation
      • 针对访问密钥进行权限分隔,减小因密钥轮换带来的资源访问影响范围。访问每个服务都使用一个独立密钥。
    • 定期修改身份凭证
      • 定期变更 Password:设置密码有效期策略。账号中的用户必须在设置时段内修改密码,否则密码自动失效。
      • 定期轮转 AK/SK:创建两对密钥,一主一备。先使用主密钥,一段时间后使用备用密钥,同时从控制台删除主密钥,然后重新生成一个密钥作为备用。
      • 定期轮换 Token:解决 Token 认证中存在的注销问题(若后端不增加额外逻辑,即使是用户被注销、账号被暂停、或密码已更改,Token 在过期前都有效)。
    • 删除不需要的身份凭证
      • 对当前仅需要登录控制台的用户,不为其创建访问密钥,或应及时删除其访问密钥。
      • 长期未登录的用户,及时删除其身份凭证,包括密码和访问密钥。
    • 敏感操作(如删除访问密钥、删除云服务器等)前需要二次验证身份,避免因安全凭证泄露产生的数据威胁。
      • 绑定了邮箱或手机的用户:输入验证码
      • 未绑定邮箱或手机的用户:输入登录密码
  2. 联合身份认证(Federation
    • 简述:服务提供商(Service Provider,SP)与身份提供商(Identity Provider,IdP)相互建立信任,统一使用 IdP 提供的用户信息进行登录。
    • 优势
      • 管理员只需创建一个账号,用户使用同一账号可同时访问多个系统的资源。
      • 除控制台登录页面外,还支持通过编程访问的方式进行身份联合认证。
    • 注:敏感操作保护对联邦用户不生效,无需二次验证。
    • 安全凭证:不支持永久访问密钥 AK/SK
      • 解决方案一:通过用户 ID Token 获取临时访问凭证(临时 AK/SK 和 Security Token)
      • 解决方案二:如需使用永久访问密钥,可以由账号或拥有同等权限的实体 IAM 用户创建密钥后共享给用户。
  3. 应用场景
    • 对云上用户进行管理与分权
      • 为不同应用创建独立的 IAM 用户,按需创建登录密码或访问密钥,并独立分配权限。
      • 为不需要权限的 IAM 用户移除权限。
    • 对云上应用进行动态身份管理与授权
      • 应用程序需要使用 Access Key 访问其他云服务 API。

最佳实践

服务主体(Entity)
云账号

云账号对名下资源有完整权限,因此使用密码和密钥登录具备同等效力。

  • 不建议对云账号创建访问密钥并使用该密钥进行日常工作。
  • 建议通过为云账号名下的独立用户创建访问密钥,使用用户来进行日常工作。
IAM 用户
  1. 新建用户
    • 云账号 IAM 用户:云账号授权该用户管理员权限,使用该用户代替云账号进行日常管理工作,保护云账号安全。
    • 普通 IAM 用户:即实体 IAM 用户。一个云账号下可以创建多个用户,对应企业员工、系统或应用程序。未被授权的新用户无权操作云账号资源。
  2. 基本信息:IAM 用户名(user),IAM 用户 ID(user_id),状态(state),创建时间(create_time),描述(user_info)
  3. 安全设置
    • 登录凭证:登录密码
    • 登录保护:使用二次验证,有效避免因密码泄露产生的安全隐患。
    • 访问密钥:AK(Access Key ID)/SK(Secret Access Key)
      • AK:访问密钥 ID,是与私有访问密钥(私钥)关联的唯一标识符,可标识发送者;访问密钥 ID 和私钥一起使用,对请求进行签名。
      • SK:是与访问密钥 ID 结合使用的密钥;对请求进行签名,并防止请求被修改。拥有用户私钥的任何人都可以解密该用户的登录信息,因此需要妥善保管。
凭证管理(Credential Management)

凭证,即用户通过系统认证的身份凭证数据。

  1. 基本类型
    • username + password
      密码的三种生成途径:
      • 用户通过密码直接登录控制台,自定义密码
      • 系统自动生成随机密码,发送给用户
      • 用户通过一次性访问链接登录控制台,自定义密码
    • Access Key
      两种访问密钥:
      • 永久访问密钥:AK/SK
        • Console 用户:成功登录控制台后,从“身份管理”页面进入“我的凭证”进行管理(新建、删除、下载)。
        • API 用户:由管理员生成,然后发给用户。由管理员在 IAM 服务中管理密钥。
        • 新建:每个用户最多创建两个访问密钥;每个访问密钥权限相同,相互独立。新建访问密钥属于敏感操作,需要二次验证身份。
        • 下载:每个访问密钥仅允许下载一次,需妥善保管;“我的凭证”页面仅显示访问密钥 ID 信息。
        • 删除:删除访问密钥属于敏感操作,需要二次验证身份。
      • 临时安全凭证:临时 AK/SK 和 Security Token
        • 应用场景:联合身份认证。联邦用户不能创建永久访问密钥,但可以创建临时访问凭证。
        • 使用:与永久安全凭证工作原理相似;通过接口获取。
          • 临时安全凭证为动态生成,不嵌入应用程序,也不进行存储;到期后无法使用,需重新获取。临时 AK/SK 和 Security Token 必须同时使用。
          • 信任:使用 AK/SK 进行对称加密的方法验证请求发送者的身份。
        • 优势
          • 临时 AK/SK 和 Security Token 遵循权限最小化原则。
          • 给外部用户授权时,无需新建或分享定期轮换、主动撤销的永久安全凭证 AK/SK,选择即时使用、定期过期的临时安全凭证进行授权,提高账号的安全性。
    • Authentication Token
      • 身份令牌(ID Token),在用户凭证被成功验证后,由认证服务生成并发出。
  2. 基本信息:IAM 用户名(user),IAM 用户 ID(user_id),账号名(account),账号 ID(account_id),访问密钥(access_key)
  3. 基本模块
    • API 凭证:调用 API 接口进行云资源管理时需要提供。
      • 基本信息:IAM 用户名(user),IAM 用户 ID(user_id),账号名(account),账号 ID(account_id),项目 ID(project_id)
    • 访问密钥:通过开发工具访问云的身份凭证,不能登录控制台。
      • 基本信息:访问密钥 ID,创建时间(create_time),状态(state),操作

API 调用

Step 1: 构造请求(Request)
  1. 规范 URL 结构
  2. 设计请求头(Request Header)
  3. 规范请求参数
  4. 明确请求方法(HTTP Method)
  5. 设计请求消息体(Request Payload / Body)
  6. 统一字符编码
Step 2: 认证鉴权(Authentication & Authorization)
  • 基于 Token 的认证
    • 规范:OAuth 2.0(基于 RFC 6749 规范)
      • 优势
        1. 可针对不同应用进行扩展:当 API 需要被不同应用调用,且调用方式不同时,使用 OAuth 服务可以灵活开发。
        2. 应用在申请 Token 时,OAuth 服务返回授权码给第三方应用,不会向第三方应用暴露用户的用户名和密码。
    • 实现:JWT(基于 RFC 7519 规范)
      优势:
      1. 使用无状态(stateless)、可扩展的方式处理应用中的用户会话,适用于简单的 REST API 认证。
        • 系统响应时间更快:前后端分离。服务端通过 Authentication Token 内嵌的声明获取用户会话信息,服务器 Session 不再额外存储,只需共享密钥即可让多个服务器都具备验证能力。另外,基于算法实现身份认证,减少了对数据库的访问。
        • 解决不能跨域/跨服务的问题:构建认证中心集中处理用户身份认证和签名发放,其他服务使用自有公钥即可验证用户签名;若验证失败(凭证非法或过期),则重定向到认证中心,重新验证用户身份。
      2. 传输:字节占用小,便于传输,可以通过 querystring,header 属性和 POST 请求消息体传输。
      3. 快速开发,易于理解:JWT 的编码规则使 Token 在 HTTP 上下文易于使用。另外由于 JSON 的通用性,JWT 可以进行跨语言支持。
      4. 安全:采用数字签名进行验证和信任。
    • 方案:OAuth 授权框架JWT(JSON Web 令牌)认证机制 同时使用
      • OAuth 授权框架颁发的 Access Token + Refresh Token 解决了使用 JWT 存在的续签问题。访问令牌过期后,应用使用 Refresh Token 即可获取新的 Access Token,无需用户参与。
  • 基于 AK/SK 的认证
    • 简述:使用 AK/SK 进行对称加密加密请求调用;基于签名算法或使用签名 SDK 对请求进行签名,通过签名认证验证请求发送者的身份。需要在请求中包含签名(Signature)信息。
    • 优势:通过加密可以确保请求的机密性、完整性,通过签名可以确保请求者身份的正确性。
    • 签名机制
      • 使用签名 SDK(区别于服务 SDK,仅提供签名功能):避免手动签名验证,方便调用接口、管理资源。
      • 使用签名算法:根据业务逻辑自定义 URL 编码规则和签名规范。
    • 签名值
      • 生成的签名串直接作为请求参数 Signature 添加到 HTTP 请求中。
      • 生成的签名串不直接作为请求参数,而是对其进行 URL 编码后添加到签名消息头 Authorization。注:Authorization 请求消息头未包含在已签名消息头 SignedHeaders 中。
    • 密钥状态:启用(允许访问云服务),禁用(禁止访问云服务)
    • 局限性:使用 AK/SK 认证时请求消息体大小可能有上限;若大小超过上限,则选择 Token 认证。
  • 权限检查
    • 当用户通过身份认证,调用 API 访问资源时,后台向 IAM 进行权限检查,以确保调用者拥有响应权限。每个不同的 API 根据涉及的资源以及 API 语义来确定需要检查哪些资源权限。
    • 权限:Allow(有响应权限) / Deny(无响应权限)
    • 实现:访问令牌 + 刷新令牌
Step 3: 返回结果(Response)
  1. 统一返回数据格式
    • XML:文本多为字符串,需要对元数据正确分层才能有效确保 XML 负载的数据类型。
    • JSON:(推荐)文本可读性高,比 XML 更简洁。
  2. 明确公共参数
  3. 设计响应消息头(Response Header)
    对应请求头(Request Header),响应消息头也有 Content-Type
  4. 设计响应消息体(Response Payload)
    通常以结构化格式返回,与响应消息头(Response Header)中 Content-Type对应。
  5. 状态码(Status Code)
    • 成功:返回 HTTP 标准状态码 2xx,代表调用成功;系统返回接口返回参数和请求 ID。
    • 失败:返回 HTTP 标准状态码 4xx5xx,代表调用异常。系统返回错误代码(error_code)、错误信息(error_msg)和请求ID(RequestId),不返回结果数据。
      • error_code:HTTP 标准返回码,业务逻辑相关错误代码(自定义,需要详细文档描述)。
        • 例:401,未授权,身份认证失败(对于需要登录的操作,服务器可能返回此响应)。
        • 例:403,鉴权失败,服务器拒绝请求。
      • error_msg:描述错误发生具体原因,与 error_code 对应。

关键技术辨析

  • 考虑单点登录方案时,需要了解什么是 OAuth,什么是 SSO,SSO 下不同策略 OAuth 和 SAML 的不同,以及 OAuth 与 OpenID 的不同,更重要的是区分 Authorization 和 Authentication。
  • 选择基于 Token 或 基于 AK/SK 进行认证鉴权时,需要了解当前业务应用场景和这几种方式的各自优劣势。
  • 判断 JWT(JSON Web Token) 能否代替 Session 管理之前,需要了解什么是 Token,以及 Access Token 和 Refresh Token 的区别。

Authentication vs Authorization

  • Authentication:身份认证,用于判断访问者是否是合法用户。
  • Authorization:访问授权,决定用户有哪些访问资源的权限。

Credential

应用程序或用户成功注册后,系统颁发的认证信息,包括 ID 和 Secret(有些凭证无 Secret 信息)。
主要使用三种类型:username + password,Token,AK/SK。

Token

访问资源的一种凭据。
用于调用 API 的 Token 称为 Access Token,存在有效期,过期需要重新获取(根据业务需求决定是否需要 Refresh Token 配合进行更新)。需要使用同一个 Token 鉴权时,可以缓存,避免频繁调用。如果应用访问用户资源,需要得到用户授权。授权成功后,系统(直接或通过授权码 Authorization Code 间接)返回 Access Token 给应用程序。
如果 Refresh Token 也过期,则需要用户重新登录授权。

  • JWT
    • 访问流程
      1. 创建账号(Account);
      2. 获取账号的认证信息(Credential),包括 email,client_id,和一对公钥/私钥;使用 client_id 和私钥创建一个 JWT;
      3. 将 JWT 发送给认证服务器来交换 Access Token;
      4. 应用程序获得来自认证服务器的 Access Token,借助 Access Token 访问 API。
    • 应用场景:应用程序可以借助 JWT 直接访问资源。一些 API 无需访问用户个人数据,因而无需经过用户授权。
      • 无需向认证服务器申请交换 Access Token;允许携带 JWT 作为 HTTP Header 的 bearer token 直接访问 API。
    • 优势
      • 确保数据完整性:确保数据确实来自被授权人,通过签名(而非加密数据)验证实现。
      • 用于接口调用:JWT 通常附在 HTTP Header 中。因为 SP 与应用程序共享一个 secret,所以应用程序可以通过 HTTP Header 提供的相同的 hash 算法来验证签名的正确性,从而判断应用是否有权调用 API。
      • 可替代 Session 机制:用户不需要提前登录,后端 Session 也无需记录用户登录信息。客户端本地保存一份合法的 JWT,用户需要调用 API 时,附上该合法 JWT;每次调用 API,后端都使用请求中附带的 JWT 做一次合法性验证,间接达到身份认证的目的。
  • 访问令牌(Access Token)
    • 表示授权(Authorization),承载用户的权限信息。Token 的权限由用户本身具有的权限决定。
    • 包含一组标准 JWT 和一组特定于标识的声明,用于通过向资源发送请求来获取对受保护资源的访问权。
  • 刷新令牌(Refresh Token)
    • 可用于获取新的访问令牌,且无需重新认证用户身份。
    • 使用:服务器一次颁发两个 Token,一个用于获取数据,另一个用于获取新的令牌。Token 到期前,用户使用 refresh token 字段发送请求更新 Token。
    • 安全性:用户不能只使用刷新令牌直接访问资源,因此持久存储刷新令牌比持久存储访问令牌更安全。

SP vs IdP

  • SP(Service Provider):负责提供资源(API 调用)的服务。
  • IdP(Identity Provider):负责认证的服务。

SSO

单点登录,即使用统一的用户管理体系,用户登录成功后可以访问所有系统。以下为几种可选策略。

SAML 2.0
  • 流程
    1. 用户通过 web 浏览器访问 SP,SP 仅提供服务,不负责用户认证;
    2. SP 向 IdP 发送一个 SAML 认证请求,同时 SP 将用户浏览器重定向到IdP;
    3. IdP 成功验证 SP 的请求后,通过 web 获取用户的用户名和密码进行登录;
    4. 用户成功登录后,IdP 生成包含用户信息的 SAML Token / SAML Assertion (本质为 XML 信息)返回给 SP,并将用户重定向到 SP;
    5. SP 验证拿到的 SAML Assertion,并解析出用户信息,根据信息允许用户访问资源。
  • 劣势:不适用于跨平台的应用场景。
OAuth 2.0

从获取 Access Token 到使用 Access Token 访问 API,整个过程遵循标准 OAuth 2.0 机制的 API 访问流程。

  • 流程
    1. 用户登录客户端/应用程序,通过客户端/应用程序访问 SP 的资源,SP 将用户重定向到 IdP 进行认证;
    2. IdP 先对用户进行身份认证,生成代表用户身份的 ID Token(带有签名的 JWT);然后 IdP 询问用户是否允许 SP/客户端/应用程序访问用户信息,若用户同意,IdP 返回一个 Authorization Code;
    3. 客户端/应用程序用 Authorization Code 向 IdP 交换(需要使用应用密钥,用作换取 Access Token 时鉴定应用身份的密码)Access Token和 ID Token;
    4. 成功交换后,客户端/应用程序使用 Access Token 向 SP 请求资源,通过获取的 ID Token 发起获取用户信息的请求;
    5. SP 接受请求后,针对当前得到的 Access Token 向 IdP 验证用户身份;成功确认身份后,SP 向客户端/应用程序发放资源。
  • 优势
    - 对比 SAML 2.0:用户从 IdP 返回客户端的方式(通过 URL 重定向)解决了 SAML 流程下无法解析 POST 内容的信息的问题。
    - 对比 OpenID:OAuth 2.0 同时支持认证和授权(但设计本意更倾向于授权而非认证)。OAuth允许被授权方访问授权方的数据;而 OpenID 只用于身份认证,被授权方无权访问授权方的数据。
    - Token 职责分离:Access Token 负责请求资源,Refresh Token 负责身份认证。
    - 一般用于有第三方接入的场景:管理对外权限,适合与 API 网关结合。
Openstack Identity Service: Keystone
  • 简述:Keystone 在 Openstack 框架中负责身份验证、颁发服务令牌。Openstack 其他服务通过 Keystone 注册服务的 Endpoint (服务访问的 URL)。任何服务间的调用都需要经过 Keystone 的身份验证。
  • 流程
    1. 用户携带 password 或其他 credential 进行 Keystone 认证;
    2. Keystone 认证成功后,返回临时 Token 给用户;
    3. 用户通过临时 Token 向 Keystone 获取服务访问目录,选择要访问的服务,通过用户名和密码向 Keystone 申请正式 Token;
    4. Keystone 认证成功后,返回正式 Token 给用户;
    5. 用户使用正式 Token 向目标服务发送请求,目标服务向 Keystone 验证用户 Token。
  • 优势
    - 跨域验证:区别于 UUID Token 只能持久化存入数据库,Keystone 支持不需要持久化的 Fernet Token。Fernet Token 需要对称加密密钥;该密钥周期性轮换,并被 multi-node 或 multi-region 部署中所有 Keystone nodes 共享,以便跨域验证。
    - 统一客户端认证:一个 Session 包含多种 credentials 时,每个服务请求对应一个 Authentication Plugin (负责认证,可复用),一个 Session 对象对应多个 Authentication Plugins;由 Openstack Client 保存该 Session 对象。使用同一 Session 对象的所有服务共享认证信息。
    - 标准服务:不期望客户端了解 Identity Token 或其他形式的 identification credential 信息,一切认证相关操作都交由 Session 和 plugins 处理。
    - 服务端无状态(stateless):Token 机制下服务端无需存储 Session 信息,Token 本身包含所有用户相关信息。

你可能感兴趣的:(API,设计,后端,saml,oauth,sso,api)