Skip to content

知识清单 - 安全性

安全性

  • OAuth: 用于身份验证的开放标准。
  • JWT(JSON Web Token): 用于安全传输信息的开放标准。

一、OAuth

OAuth(Open Authorization)是一个用于身份验证和授权的开放标准,用于在客户端和服务提供者之间进行安全的资源共享。OAuth 的目标是允许第三方应用程序(客户端)在用户授权的情况下,访问在其他服务上托管的用户资源,而不需要将用户的凭证直接提供给第三方。

OAuth(Open Authorization)是一个用于身份验证和授权的开放标准,用于在客户端和服务提供者之间进行安全的资源共享。OAuth 的目标是允许第三方应用程序(客户端)在用户授权的情况下,访问在其他服务上托管的用户资源,而不需要将用户的凭证直接提供给第三方。

OAuth 的核心角色有三个:

  1. 资源所有者(Resource Owner): 拥有受保护资源的用户。资源所有者是授权的主体。

  2. 客户端(Client): 通过请求访问受保护资源的第三方应用程序。客户端是资源的使用者。

  3. 授权服务器(Authorization Server): 负责验证资源所有者并颁发访问令牌(Access Token)给客户端。授权服务器和资源服务器可以是同一个实体,也可以是不同的实体。

  4. 资源服务器(Resource Server): 存储和提供受保护资源的服务器。资源服务器根据客户端的访问令牌决定是否允许客户端访问资源。

OAuth 的工作流程通常分为以下步骤:

  1. 客户端注册: 客户端在授权服务器上注册,并获得客户端标识和密钥。

  2. 授权请求: 客户端引导用户到授权服务器,请求授权。这通常包括重定向用户到授权服务器的认证页面。

  3. 用户授权: 用户登录并在授权服务器上授权客户端访问其资源。用户授权的方式包括授权码授权、密码授权、客户端凭证授权等。

  4. 授权颁发: 授权服务器验证用户身份,并颁发访问令牌给客户端。

  5. 资源访问: 客户端使用访问令牌请求资源服务器,以获取受保护资源。

  6. 资源响应: 资源服务器验证访问令牌,并向客户端提供受保护资源。

OAuth 2.0 和 OAuth 1.0a:

  • OAuth 1.0a: 使用签名机制,要求客户端提供签名,以确保请求的完整性。虽然安全,但相对繁琐。

  • OAuth 2.0: 简化了 OAuth 1.0a 的流程,通过使用访问令牌(Access Token)来提供对资源的访问。虽然不如 1.0a 安全,但更简便且广泛使用。

OAuth 2.0 主要包括授权码授权、密码授权、客户端凭证授权、隐式授权等多种授权方式。

OAuth 在许多 Web 应用程序和服务中广泛应用,为用户提供了安全且方便的第三方应用访问权限的机制。

二、JWT

JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在网络上安全地传输信息。JWT 是一种紧凑的、自包含的方式,用于在各方之间作为 JSON 对象传递信息。主要用于身份验证和在不同系统之间安全地传递声明。

JWT 的结构:

JWT 由三部分组成,这三部分由点(.)分隔开:

  1. Header(头部): 包含了令牌的类型(JWT)和所使用的签名算法,通常以 Base64 编码的 JSON 字符串表示。

    json
    {
      "alg": "HS256",
      "typ": "JWT"
    }
  2. Payload(负载): 包含了声明(claims),声明是关于实体(通常是用户)和其他数据的声明。有三种类型的声明:注册声明、公共声明、私有声明。

    json
    {
      "sub": "1234567890",
      "name": "John Doe",
      "admin": true
    }
  3. Signature(签名): 使用编码的头部、编码的负载和一个密钥(secret)来创建。签名的目的是验证消息的发送方以及消息在传递过程中没有被篡改。

    plaintext
    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret
    )

工作流程:

  1. 认证: 用户提供用户名和密码进行认证,服务端验证用户身份。

  2. 颁发 JWT: 服务端使用私钥签发 JWT,并将其返回给客户端。

  3. 存储 JWT: 客户端通常将 JWT 存储在本地,例如在浏览器的 localStorage 中。

  4. 携带 JWT: 客户端在后续请求中通过将 JWT 放入请求头或其他适当位置,将其携带到服务端。

  5. 验证和解析 JWT: 服务端收到请求后,验证 JWT 的签名,然后解析其中的信息。

  6. 授权: 根据 JWT 中的信息,服务端对客户端进行授权。

优势:

  1. 轻量且紧凑: JWT 的结构简单,因此相较于传统的身份验证机制,它更轻量且在网络传输中更紧凑。

  2. 可扩展性: 可以通过添加自定义声明来扩展 JWT 的功能,适应不同的应用场景。

  3. 无状态性: 由于 JWT 包含了所有必要的信息,服务器不需要在本地存储用户的会话信息,因此可以实现无状态的认证。

  4. 跨域支持: JWT 可以在不同域之间传输,并且可以通过配置 CORS(跨域资源共享)来支持跨域通信。

  5. 自包含性: JWT 包含了所有必要的信息,因此客户端可以解析 JWT 来获取用户的信息,而不必在每个请求中都去查询服务器。

安全注意事项:

  1. 使用 HTTPS: 所有的 JWT 通信都应该在安全的通道上进行,即使用 HTTPS。

  2. 令牌有效期: JWT 可以设置有效期,确保在一段时间后令牌失效。

  3. 避免敏感信息: 不要在 JWT 中存储敏感信息,因为 JWT 的内容可以被解码。

  4. 避免过长有效期: 不要设置过长的 JWT 有效期,以减少窃取风险。

JWT 是一种通用且强大的身份验证和授权机制,适用于多种应用场景,包括单点登录、API 认证等。

示例(使用 Node.js 和 jsonwebtoken 库):

javascript
const jwt = require('jsonwebtoken')

// 选择加密算法和设置密钥
const algorithm = 'HS256'
const secretKey = 'your_secret_key'

// 构建头部
const header = {
  alg: algorithm,
  typ: 'JWT'
}

// 构建负载
const payload = {
  sub: '1234567890',
  name: 'John Doe',
  admin: true,
  exp: Math.floor(Date.now() / 1000) + 3600 // 设置过期时间为1小时后
}

// 生成JWT
const token = jwt.sign(payload, secretKey, { algorithm })

console.log(token)

验证和解析 JWT 步骤:

  1. 获取 JWT: 从客户端收到 JWT。

  2. 拆分 JWT: 使用点号(.)拆分 JWT,分为头部、负载和签名三部分。

  3. 验证签名: 使用与生成 JWT 时相同的加密算法和密钥,对头部和负载进行签名验证。

  4. 解析负载: 将 Base64 解码后的负载部分转换为 JSON 对象,获取其中的声明信息。

验证和解析 JWT 示例(使用 Node.js 和 jsonwebtoken 库):

javascript
const jwt = require('jsonwebtoken')

// 从客户端收到的JWT
const receivedToken = 'your_received_jwt'

// 选择加密算法和设置密钥
const algorithm = 'HS256'
const secretKey = 'your_secret_key'

try {
  // 拆分JWT
  const [encodedHeader, encodedPayload, signature] = receivedToken.split('.')

  // 验证签名
  const isSignatureValid = jwt.verify(receivedToken, secretKey, {
    algorithms: [algorithm]
  })

  if (isSignatureValid) {
    // 解码负载
    const decodedPayload = jwt.decode(receivedToken)

    console.log('Signature is valid')
    console.log('Decoded Payload:', decodedPayload)
  } else {
    console.log('Signature is invalid')
  }
} catch (error) {
  console.error('Error:', error.message)
}

上述示例中,我们使用 Node.js 中 jsonwebtoken 库来验证和解析 JWT。jwt.verify函数用于验证 JWT 的签名,如果签名有效,就可以使用jwt.decode函数将负载解码为 JSON 对象。请注意,实际中需要适应应用场景选择合适的算法、密钥管理和声明内容,并且要处理异常情况,如签名无效或解码错误。

优势:

  1. 轻量和紧凑: JWT 是一种轻量级、紧凑的标准,适合在网络上快速传输信息。

  2. 自包含性: JWT 包含了所有必要的信息,客户端可以解码 JWT 以获取用户信息,减少了对服务器的查询次数。

  3. 无状态性: 由于 JWT 包含所有必要的信息,服务器不需要在本地存储用户的会话信息,实现了无状态的认证。

  4. 可扩展性: 可以通过添加自定义声明来扩展 JWT 的功能,适应不同的应用场景。

  5. 跨域支持: JWT 可以在不同域之间传输,并且可以通过配置 CORS(跨域资源共享)来支持跨域通信。

  6. 安全性: 当使用合适的加密算法和密钥管理时,JWT 可以提供较高的安全性。

  7. 广泛应用: JWT 广泛应用于身份验证、单点登录、API 认证等场景。

不足:

  1. 无法撤销: 一旦 JWT 生成并在客户端存储,服务器无法撤销或立即使其失效。过期时间是唯一可控制的机制。

  2. 不适用于保密信息: JWT 的内容可以通过 Base64 解码,因此不适合存储敏感信息,尽管可以使用加密算法提高安全性。

  3. 过期时间问题: 如果过期时间设置过短,可能导致用户频繁重新登录;如果设置过长,可能增加被滥用的风险。

  4. 无法处理状态变更: JWT 无法处理用户在会话期间的状态变更,例如用户被禁用或角色变更。

  5. 不适用于大量数据: JWT 适用于小型信息传输,但对于大量数据可能效率较低。

  6. 对称加密问题: 使用对称加密算法时,密钥的分发和管理可能成为挑战。

总体而言,JWT 是一种非常有用的工具,特别是在分布式系统和前后端分离的应用中。在使用时,需要权衡其优势和不足,根据具体的应用场景和安全需求来选择合适的配置和实践。