发布于 2026-01-06 6 阅读
0

🏰 钥匙城堡:实体-数字游戏中的 API 优先访问控制

🏰 钥匙城堡:实体-数字游戏中的 API 优先访问控制

这是Permit.io 授权挑战赛的参赛作品:API 优先授权的重新构想

目录

我建造的

Castle of Keys是一款受中世纪城堡启发而开发的交互式现实世界门禁控制游戏,并由Permit.io提供的外部授权提供支持。

玩家扮演国王、厨师或仆人等角色,尝试进入城堡的不同楼层。访问权限由外部策略控制,而非硬编码逻辑。


🔄 工作原理(分步流程)

  1. 玩家将RFID卡出示给连接到ESP32的读卡器。
  2. ESP32 读取 UID 并向发送请求proxy.php,其中包括 UID 和所需的操作(例如,access_floor_2)。
  3. proxy.php脚本使用私有令牌安全地将请求转发到 Permit.io API。
  4. Permit.io 返回是否允许访问("allow": true)或不允许。
  5. ESP32 会解析响应并激活相应的 LED:
    • ✅ 绿色 = 已授予访问权限
    • ❌ 红色 = 访问被拒绝
  6. 同时,ESP32 将日志发送到log.php— 用于在 Web 界面中进行可视化显示或调试。

⚠️注意: log.php Permit.io 的正常运行并不需要此功能。它用于在游戏界面中显示访问尝试。


🎮 演示

👉观看完整演示视频(网页+硬件):

🎮 或者试试网页版(无需硬件):试试城堡钥匙(网页演示)


💡我的旅程

这个项目的初衷是通过游戏化的方式赋予门禁系统以生命力。我想要创造的不仅仅是一个用户界面按钮或权限表,而是切实可感、可交互的实体体验。因此,我决定集成RFID读卡器等真实硬件,并很快会加入生物识别传感器,以打造既有趣又沉浸式的体验。


🔐 API优先授权

以下是我 ESP32 上运行的实际.ino代码。它使用 RC522 模块读取 RFID 卡,将 UID 发送到安全的 PHP 代理,并从 Permit.io 接收实时授权决定。

🔌 ESP32 代码(Arduino)

#include <WiFi.h>
#include <HTTPClient.h>
#include <SPI.h>
#include <MFRC522.h>

const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";


const char* permitUrl = "https://example.com/api/proxy.php"; // your private endpoint
const char* logUrl = "https://example.com/app/log.php";

#define RST_PIN 22
#define SS_PIN  21

MFRC522 rfid(SS_PIN, RST_PIN);

void setup() {
  Serial.begin(115200);
  SPI.begin();
  rfid.PCD_Init();

  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected!");
}

void loop() {
  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) {
    return;
  }

  String uid = "";
  for (byte i = 0; i < rfid.uid.size; i++) {
    uid += String(rfid.uid.uidByte[i], HEX);
  }
  uid.toUpperCase();

  Serial.print("Card detected: ");
  Serial.println(uid);

  // Make Permit.io authorization request
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(permitUrl);
    http.addHeader("Content-Type", "application/json");

    String payload = "{\"user\":{\"key\":\"" + uid + "\"},\"action\":\"" + action + "\",\"resource\":{\"type\":\"document\",\"tenant\":\"devs\"},\"context\":{}}";

    int httpResponseCode = http.POST(payload);

    if (httpResponseCode > 0) {
      String response = http.getString();
      Serial.println("Permit.io response: " + response);

      if (response.indexOf("\"allow\":true") > 0) {
        Serial.println("✅ Access granted");
        accessGranted = true;
        // digitalWrite(GREEN_LED, HIGH);
      } else {
        Serial.println("❌ Access denied");
        // digitalWrite(RED_LED, HIGH);
      }

    } else {
      Serial.print("Error on sending request: ");
      Serial.println(httpResponseCode);
    }

    http.end();

    // Send access log
    HTTPClient logHttp;
    logHttp.begin(logUrl);
    logHttp.addHeader("Content-Type", "application/json");

    String logPayload = "{\"uid\":\"" + uid + "\",\"action\":\"" + action + "\",\"status\":\"" + (accessGranted ? "granted" : "denied") + "\"}";
    logHttp.POST(logPayload);
    logHttp.end();
  }

  delay(3000); // Prevent repeated scans
}
Enter fullscreen mode Exit fullscreen mode

Permit.io 的 PHP 代理(ESP32 集成)

为了保护您的Permit.io API 密钥安全,我创建了一个简单的proxy.php文件。ESP32 会向这个 PHP 脚本发送请求,而不是直接调用 Permit.io。

以下是完整代码:

<?php
// proxy.php - Receives data from ESP32 and checks permission via Permit.io

// Read the incoming JSON from ESP32
$body = file_get_contents('php://input');
$data = json_decode($body, true);

// Prepare the payload for Permit.io
$payload = json_encode([
  "user" => [
    "key" => $data['user']  // UID from RFID card
  ],
  "action" => $data['action'], // Example: "access_floor_1"
  "resource" => [
    "type" => "document",   // Replace with your configured resource type
    "tenant" => "devs"      // Tenant ID (if applicable)
  ],
  "context" => new stdClass() // Additional context (empty for now)
]);

// Send the request to Permit.io
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://api.permit.io/v2/allowed");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  "Authorization: Bearer YOUR_PERMIT_API_KEY", // Replace with your Permit.io API key
  "Content-Type: application/json"
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Return the result back to the ESP32
http_response_code($http_code);
echo $response;
Enter fullscreen mode Exit fullscreen mode

✅ 结论

这个项目展示了将实际硬件与 Permit.io 集成是多么容易。只需几行代码和外部策略,即可安全地控制访问权限——无需任何硬编码。

文章来源:https://dev.to/jamesrmoro/castle-of-keys-api-first-access-control-in-a-physical-digital-game-2f70