跳转至

机器对机器(M2M)应用

什么是 M2M 应用?

机器对机器(M2M)应用让后端服务、命令行工具(CLI)、定时任务和智能设备能够使用专属凭据获取访问令牌并与 API 交互。这些应用无需人工用户进行身份验证,而是使用自己的凭据安全地访问资源,从而简化整个技术栈中的自动化和集成工作。

常见使用场景

  • 应用后端: 支持在微服务或外部系统之间安全地传输数据、文件或日志。
  • CLI 工具: 让运行在开发或部署机器上的工具能够使用短期令牌访问 API。
  • 定时任务与守护进程: 让后台任务(例如定时任务、队列系统)能够安全地访问受保护的资源。
  • 物联网设备: 让每台智能设备都能独立进行身份验证,并将数据安全地发送到云端 API。

在 Authany 中设置 M2M 应用

1. 注册您的 API 资源

在 Authany 管理台中,进入 API 资源 页面:

  • 创建您的应用/设备将要访问的 API 资源。
  • 注册资源时,请指定其 标识符——它是代表您 API 的唯一 URI(例如 https://myapi.com/api)。
  • 该标识符会被设置为为此资源签发的 JWT 访问令牌中的 aud(audience)声明。
  • 定义 权限范围(Scope),实现精细的权限控制,例如 read:data、write:data 或 manage:config。
  • 权限范围(Scope)精确定义了客户端可以对您的 API 执行哪些操作。

2. 注册您的应用

在 应用 页面中:

  • 为每个需要访问 API 的后端服务、CLI 工具、任务或设备创建一个客户端应用。
  • 为该应用分配相关的 API 资源 和 权限范围(Scope),确保遵循最小权限原则。
  • 创建应用后,您可以在管理台中查看其 Client ID 和 Client Secret。请妥善保管 Client Secret,切勿将其暴露在客户端代码或公开仓库中。

3. 使用客户端凭据流程请求令牌

OAuth 2.0 RFC 6749 第 4.4 节中定义的 客户端凭据流程(Client Credentials Flow) 专为非用户的自动化访问而设计。

要在后端获取访问令牌,请使用您在管理台中注册的应用的 Client ID 和 Client Secret:

curl --request POST \
  --url https://myproject.authanyid.com/oauth2/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data resource=IDENTIFIER_OF_API_RESOURCE \
  --data client_id=CLIENT_ID \
  --data client_secret=CLIENT_SECRET
import urllib.parse
import urllib.request
import json

url = "https://myproject.authanyid.com/oauth2/token"
headers = {
    "Content-Type": "application/x-www-form-urlencoded"
}
data = {
    "grant_type": "client_credentials",
    "resource": "IDENTIFIER_OF_API_RESOURCE",
    "client_id": "CLIENT_ID",
    "client_secret": "CLIENT_SECRET"
}

encoded_data = urllib.parse.urlencode(data).encode('utf-8')
req = urllib.request.Request(url, data=encoded_data, headers=headers, method='POST')

with urllib.request.urlopen(req) as response:
    response_status = response.getcode()
    response_body = response.read().decode('utf-8')
    print("Response Status Code:", response_status)
    print("Response Body:", json.loads(response_body))
package main

import (
  "fmt"
  "io/ioutil"
  "net/http"
  "net/url"
  "strings"
)

func main() {
  data := url.Values{}
  data.Set("grant_type", "client_credentials")
  data.Set("resource", "IDENTIFIER_OF_API_RESOURCE")
  data.Set("client_id", "CLIENT_ID")
  data.Set("client_secret", "CLIENT_SECRET")

  req, _ := http.NewRequest("POST", "https://myproject.authanyid.com/oauth2/token", strings.NewReader(data.Encode()))
  req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

  resp, _ := http.DefaultClient.Do(req)
  defer resp.Body.Close()

  body, _ := ioutil.ReadAll(resp.Body)

  fmt.Println("Response Status Code:", resp.StatusCode)
  fmt.Println("Response Body:", string(body))
}
async function makeRequest() {
  const url = "https://myproject.authanyid.com/oauth2/token";
  const data = new URLSearchParams();
  data.append("grant_type", "client_credentials");
  data.append("resource", "IDENTIFIER_OF_API_RESOURCE");
  data.append("client_id", "CLIENT_ID");
  data.append("client_secret", "CLIENT_SECRET");

  const response = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: data,
  });

  const responseBody = await response.json();
  console.log("Response Status Code:", response.status);
  console.log("Response Body:", responseBody);
}

makeRequest();

您将获得一个访问令牌,其中只包含该客户端被允许的权限范围(Scope)。

有关令牌结构和声明的详细信息,请参阅 M2M 令牌。

4. 访问受保护的 API

在请求头中包含 Authorization 头,即可向您的 API 发送请求:

Authorization: Bearer <access_token>

现在,您的后端可以验证该令牌,并对允许的操作进行授权。

5. 在 API 服务器上验证令牌

请务必在您的 API 服务器中验证收到的 JWT 令牌:

  • 验证签发者(issuer)、受众(audience)、权限范围(scope)、过期时间和签名。
  • 拒绝令牌无效或已过期的请求。

示例代码和最佳实践请参阅 在后端验证 JWT。