Tự động hóa quyền xóa dữ liệu bằng cách sử dụng webhook

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

Các quy định toàn cầu về bảo vệ dữ liệu và quyền riêng tư cấp cho cá nhân quyền kiểm soát dữ liệu của họ, bao gồm quyền yêu cầu xóa dữ liệu (thường được gọi là "quyền xóa dữ liệu" hoặc "quyền xóa"). Nếu bạn lưu trữ bất kỳ dữ liệu cá nhân hoặc Thông tin Cá nhân Nhận diện được (PII), chẳng hạn như ID người dùng, bạn có trách nhiệm tuân thủ các khung quyền riêng tư áp dụng bằng cách xóa vĩnh viễn thông tin này khi nhận được yêu cầu từ người dùng. Thông tin thêm có thể được tìm thấy trong RTBF và người sáng tạo.

Xem xét các lựa chọn thay thế

Đối với dữ liệu cá nhân trong các kho dữ liệu, tùy chọn tự động hóa dễ nhất là cấu hình các mẫu xóa RTBF. Khi Roblox xử lý một yêu cầu RTBF, nó tự động xóa các mục trong kho dữ liệu tiêu chuẩn hoặc theo thứ tự mà không yêu cầu bạn phải lưu trữ mã tùy chỉnh. Để cấu hình các mẫu và xem các mẫu được hỗ trợ, hãy xem Kho dữ liệu quyền được quên (RTBF).

Quy trình webhook trên trang này hữu ích khi:

  • Bạn lưu trữ dữ liệu cá nhân bên ngoài các kho dữ liệu.
  • Lược đồ kho dữ liệu hoặc trường hợp sử dụng của bạn không được hỗ trợ bởi các mẫu xóa RTBF.
  • Bạn cần xử lý hoặc logic xóa tùy chỉnh.

Quy trình webhook của người sáng tạo

Hướng dẫn này trình bày cách thiết lập một webhook và tạo một bot Discord chạy cục bộ sử dụng Open Cloud API cho các kho dữ liệu để tự động hóa việc xử lý các yêu cầu quyền xóa dữ liệu. Quy trình cho quá trình này như sau:

  1. Hỗ trợ Roblox nhận được một yêu cầu quyền xóa dữ liệu từ một người dùng.
  2. Webhook của Roblox được kích hoạt, chứa ID người dùng và danh sách ID Nơi Bắt Đầu cho các trò chơi mà họ đã tham gia trong payload.
  3. Bot của bạn lắng nghe các thông báo webhook này, xác minh tính xác thực của chúng và sử dụng Open Cloud API cho các kho dữ liệu để xóa dữ liệu PII được lưu trữ trong các kho dữ liệu.
  4. Bot phản hồi lại tin nhắn webhook trong Discord với trạng thái xóa.

Cấu hình một webhook với tích hợp bên thứ ba

Trước khi tạo một bot, hãy thiết lập một máy chủ với tích hợp webhook trên ứng dụng nhắn tin bên thứ ba. Sau đó, sử dụng máy chủ để cấu hình một webhook trên Bảng điều khiển Người sáng tạo.

Thiết lập một máy chủ

Các bước sau đây cho thấy cách thiết lập máy chủ bằng Discord.

  1. Tạo một máy chủ Discord mới. Nếu bạn không quen với quy trình này, hãy xem Hỗ trợ Discord.

  2. Máy chủ tự động tạo một kênh #general làm kênh mặc định của bạn. Nhấp vào biểu tượng Chỉnh sửa Kênh của kênh #general.

  3. Dưới Quyền, đặt kênh thành riêng tư.

  4. Tạo một tích hợp webhook với máy chủ mới, đặt tên cho nó là RTBF Hook. Nếu bạn không quen với quy trình này, hãy xem Hỗ trợ Discord.

  5. Sao chép URL webhook và lưu trữ nó ở một nơi an toàn. Chỉ cho phép các thành viên trong nhóm đáng tin cậy truy cập vào nó, vì việc rò rỉ URL có thể cho phép những kẻ xấu gửi tin nhắn giả và có thể xóa dữ liệu người dùng của bạn.

Cấu hình một webhook trên Roblox

Sau khi có được URL máy chủ bên thứ ba, hãy sử dụng nó để cấu hình một webhook trên Bảng điều khiển Người sáng tạo. hãy đảm bảo bạn thực hiện các cài đặt sau:

  • Thêm URL máy chủ Discord làm Webhook URL.
  • Bao gồm một Mật khẩu tùy chỉnh. Mặc dù mật khẩu là tùy chọn để hoàn thành cấu hình, bạn nên bao gồm một cái để ngăn chặn những kẻ xấu giả mạo Roblox và xóa dữ liệu của bạn. Để biết thêm thông tin về việc sử dụng mật khẩu, hãy xem Xác minh bảo mật webhook.
  • Chọn Yêu cầu Quyền Xóa Dữ liệu dưới Kích hoạt.

Bạn có thể kiểm tra webhook bằng cách sử dụng nút Kiểm tra Phản hồi để xem liệu bạn có nhận được thông báo trong kênh #general của máy chủ từ Roblox hay không. Nếu bạn không nhận được thông báo, hãy thử lại hoặc kiểm tra cài đặt máy chủ của bạn để khắc phục sự cố.

Cấu hình một bot

Sau khi bạn thêm webhook, hãy sử dụng nó để cấu hình bot với các bước sau. Để biết thêm thông tin, hãy xem tài liệu Discord.

  1. Điều hướng đến Trang Ứng dụng.
  2. Tạo một ứng dụng mới và đặt tên cho nó là RTBF Bot.
  3. Hệ thống sẽ chuyển hướng bạn đến cài đặt Thông tin Chung của bot. Sao chép và lưu ID ứng dụng của nó ở một nơi an toàn.
  4. Dưới menu cài đặt, chọn OAuth2.
  5. Điều hướng đến cài đặt OAuth2
    1. Bật phạm vi bot, danh sách các Quyền Bot bổ sung sẽ hiển thị.
    2. Thêm quyền Quản trị viên. Lưu thay đổi của bạn.
    3. Lưu URL được tạo.
  6. Sao chép URL được tạo. Để trang cài đặt ứng dụng mở.
  7. Điều hướng đến URL được tạo. Chọn máy chủ mục tiêu. Nhấp vào nút Tiếp tục và sau đó là nút Ủy quyền.
  8. Quay lại trang cài đặt ứng dụng và điều hướng đến cài đặt Bot.
  9. Dưới phần Ý định Cổng Đặc quyền, bật Ý định Nội dung Tin nhắn.
  10. Trong cài đặt Bot > phần Xây dựng Bot, lưu mã thông báo bot ở một nơi an toàn cho các bước sau. Nếu bạn không thấy mã thông báo, hãy nhấp vào nút Đặt lại Mã thông báo để tạo một cái mới.

Tạo một khóa API Open Cloud

Để cho phép bot bên thứ ba của bạn truy cập các kho dữ liệu của bạn để lưu trữ dữ liệu PII của người dùng, tạo một khóa API Open Cloud có thể truy cập các trò chơi của bạn và thêm quyền Xóa Mục của các kho dữ liệu để xóa dữ liệu. Nếu bạn sử dụng các kho dữ liệu theo thứ tự để lưu trữ PII, bạn cũng cần thêm quyền Ghi của các kho dữ liệu theo thứ tự. Sau khi hoàn tất, hãy sao chép và lưu khóa API ở một vị trí an toàn để sử dụng trong các bước sau.

Lấy các định danh của trò chơi và nơi

Để bot có thể xác định dữ liệu PII được yêu cầu xóa bởi người dùng, hãy lấy các định danh sau của tất cả các trò chơi mà bạn dự định sử dụng bot cho:

  • ID Vũ trụ, định danh duy nhất của trò chơi của bạn.
  • ID Nơi Bắt Đầu, định danh duy nhất của nơi bắt đầu của một trò chơi.

Để lấy các định danh này:

  1. Di chuột qua hình thu nhỏ của một trò chơi, nhấp vào nút và chọn Sao chép ID Vũ trụSao chép ID Nơi Bắt Đầu, tương ứng.

Thêm các script

Sau khi bạn hoàn tất việc thiết lập webhook, bot và khóa API cho các kho dữ liệu, hãy thêm chúng vào các script thực hiện logic tự động hóa của bot. Ví dụ sau sử dụng Python 3.

  1. Cài đặt các thư viện Python bằng cách sử dụng các lệnh sau:

    Cài đặt Thư viện
    pip3 install discord
    pip3 install requests
    pip3 install urllib3==1.26.6
  2. Sao chép và lưu các script sau tương ứng với các phần khác nhau của logic bot trong cùng một thư mục:

    bot_config.py
    BOT_TOKEN = ""
    OPEN_CLOUD_API_KEY = ""
    ROBLOX_WEBHOOK_SECRET = ""
    # Từ điển của ID Nơi Bắt Đầu đến
    # (ID vũ trụ, danh sách (tên kho dữ liệu, phạm vi và khóa mục)) cho
    # Kho Dữ liệu Tiêu chuẩn
    # Dữ liệu người dùng được lưu trữ dưới các mục này sẽ bị xóa
    STANDARD_DATA_STORE_ENTRIES = {
    # ID Nơi Bắt Đầu
    111111111: (
    # ID Vũ trụ
    222222222,
    [
    ("StandardDataStore1", "Scope1", "Key1_{user_id}"),
    ("StandardDataStore1", "Scope1", "Key2_{user_id}"),
    ("StandardDataStore2", "Scope1", "Key3_{user_id}")
    ]
    ),
    33333333: (
    444444444,
    [
    ("StandardDataStore3", "Scope1", "Key1_{user_id}")
    ]
    )
    }
    # Từ điển của ID Nơi Bắt Đầu đến
    # (ID vũ trụ, danh sách (tên kho dữ liệu, phạm vi và khóa mục)) cho
    # Kho Dữ liệu Theo Thứ Tự
    # Dữ liệu người dùng được lưu trữ dưới các mục này sẽ bị xóa
    ORDERED_DATA_STORE_ENTRIES = {
    111111111: (
    222222222,
    [
    ("OrderedDataStore1", "Scope2", "Key4_{user_id}")
    ]
    )
    }
    data_stores_api.py
    import requests
    import bot_config
    from collections import defaultdict
    """
    Gọi Open Cloud API Kho Dữ liệu để xóa tất cả các mục cho user_id được cấu hình trong
    STANDARD_DATA_STORE_ENTRIES. Trả về danh sách các lần xóa thành công và thất bại.
    """
    def delete_standard_data_stores(user_id, start_place_ids):
    successes = defaultdict(list)
    failures = defaultdict(list)
    for owned_start_place_id in bot_config.STANDARD_DATA_STORE_ENTRIES:
    if owned_start_place_id not in start_place_ids:
    continue
    universe_id, universe_entries = bot_config.STANDARD_DATA_STORE_ENTRIES[owned_start_place_id]
    for (data_store_name, scope, entry_key) in universe_entries:
    entry_key = entry_key.replace("{user_id}", user_id)
    response = requests.delete(
    f"https://apis.roblox.com/datastores/v1/universes/{universe_id}/standard-datastores/datastore/entries/entry",
    headers={"x-api-key": bot_config.OPEN_CLOUD_API_KEY},
    params={
    "datastoreName": data_store_name,
    "scope": scope,
    "entryKey": entry_key
    }
    )
    if response.status_code in [200, 204]:
    successes[owned_start_place_id].append((data_store_name, scope, entry_key))
    else:
    failures[owned_start_place_id].append((data_store_name, scope, entry_key))
    return successes, failures
    """
    Gọi Open Cloud API Kho Dữ liệu Theo Thứ Tự để xóa tất cả các mục cho user_id được cấu hình trong
    ORDERED_DATA_STORE_ENTRIES. Trả về danh sách các lần xóa thành công và thất bại.
    """
    def delete_ordered_data_stores(user_id, start_place_ids):
    successes = defaultdict(list)
    failures = defaultdict(list)
    for owned_start_place_id in bot_config.ORDERED_DATA_STORE_ENTRIES:
    if owned_start_place_id not in start_place_ids:
    continue
    universe_id, universe_entries = bot_config.ORDERED_DATA_STORE_ENTRIES[owned_start_place_id]
    for (data_store_name, scope, entry_key) in universe_entries:
    entry_key = entry_key.replace("{user_id}", user_id)
    response = requests.delete(
    f"https://apis.roblox.com/ordered-data-stores/v1/universes/{universe_id}/orderedDatastores/{data_store_name}/scopes/{scope}/entries/{entry_key}",
    headers={"x-api-key": bot_config.OPEN_CLOUD_API_KEY}
    )
    if response.status_code in [200, 204, 404]:
    successes[owned_start_place_id].append((data_store_name, scope, entry_key))
    else:
    failures[owned_start_place_id].append((data_store_name, scope, entry_key))
    return successes, failures
    message_parser.py
    import time
    import hmac
    import hashlib
    import re
    import base64
    import bot_config
    """
    Phân tích tin nhắn nhận được để lấy chữ ký và dấu thời gian của Roblox, phần chân trang chỉ được thiết lập nếu bạn
    cấu hình mật khẩu webhook
    """
    def parse_footer(message):
    if not message.embeds[0].footer or \
    not message.embeds[0].footer.text:
    return "", 0
    footer_match = re.match(
    r"Roblox-Signature: (.*), Timestamp: (.*)",
    message.embeds[0].footer.text
    )
    if not footer_match:
    return "", 0
    else:
    signature = footer_match.group(1)
    timestamp = int(footer_match.group(2))
    return signature, timestamp
    """
    Xác minh chữ ký Roblox với mật khẩu đã cấu hình để kiểm tra tính hợp lệ
    """
    def validate_signature(message, signature, timestamp):
    if not message or not signature or not timestamp:
    return False
    # Ngăn chặn tấn công phát lại trong khoảng thời gian 300 giây
    request_timestamp_ms = timestamp * 1000
    window_time_ms = 300 * 1000
    oldest_timestamp_allowed = round(time.time() * 1000) - window_time_ms
    if request_timestamp_ms < oldest_timestamp_allowed:
    return False
    # Xác minh chữ ký
    timestamp_message = "{}.{}".format(timestamp, message.embeds[0].description)
    digest = hmac.new(
    bot_config.ROBLOX_WEBHOOK_SECRET.encode(),
    msg=timestamp_message.encode(),
    digestmod=hashlib.sha256
    ).digest()
    validated_signature = base64.b64encode(digest).decode()
    if signature != validated_signature:
    return False
    # Chữ ký hợp lệ
    return True
    """
    Phân tích một tin nhắn webhook nhận được trên Discord. Trích xuất ID người dùng, ngăn chặn tấn công phát lại
    dựa trên dấu thời gian nhận được, và xác minh chữ ký Roblox với mật khẩu đã cấu hình để kiểm tra tính hợp lệ.
    """
    def parse_message(message):
    # Phân tích tin nhắn nhận được để lấy ID người dùng và ID trò chơi
    if len(message.embeds) != 1 or \
    not message.embeds[0].description:
    return "", []
    description_match = re.match(
    r"You have received a new notification for Right to Erasure for the User Id: (.*) in " +
    r"the game\(s\) with Ids: (.*)",
    message.embeds[0].description
    )
    if not description_match:
    return "", []
    user_id = description_match.group(1)
    start_place_ids = set(int(item.strip()) for item in description_match.group(2).split(","))
    signature, timestamp = parse_footer(message)
    if validate_signature(message, signature, timestamp):
    return user_id, start_place_ids
    else:
    return "", []
    discord_bot.py
    import discord
    import bot_config
    import data_stores_api
    import message_parser
    def run():
    intents = discord.Intents.default()
    intents.message_content = True
    client = discord.Client(intents=intents)
    @client.event
    async def on_ready():
    print(f"{client.user} đang lắng nghe các tin nhắn Quyền Xóa Dữ liệu")
    """
    Xử lý các tin nhắn webhook từ Roblox
    """
    @client.event
    async def on_message(message):
    # Phân tích và xác minh tin nhắn
    user_id, start_place_ids = message_parser.parse_message(message)
    if not user_id or not start_place_ids:
    return
    # Xóa dữ liệu người dùng trong các kho dữ liệu tiêu chuẩn
    [successes, failures] = data_stores_api.delete_standard_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Đã xóa dữ liệu kho dữ liệu tiêu chuẩn cho " +
    f"ID người dùng: {user_id}, dữ liệu: {dict(successes)}")
    if failures:
    await message.reply(f"Không thể xóa dữ liệu kho dữ liệu tiêu chuẩn cho " +
    f"ID người dùng: {user_id}, dữ liệu: {dict(failures)}")
    # Xóa dữ liệu người dùng trong các kho dữ liệu theo thứ tự
    [successes, failures] = data_stores_api.delete_ordered_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Đã xóa dữ liệu kho dữ liệu theo thứ tự cho " +
    f"ID người dùng: {user_id}, dữ liệu: {dict(successes)}")
    if failures:
    await message.reply(f"Không thể xóa dữ liệu kho dữ liệu theo thứ tự cho " +
    f"ID người dùng: {user_id}, dữ liệu: {dict(failures)}")
    client.run(bot_config.BOT_TOKEN)
    if __name__ == "__main__":
    run()
  3. Trong tệp bot_config.py để cấu hình chính của bot:

    1. Đặt BOT_TOKEN thành mã thông báo được tạo bởi bot của bạn.
    2. Đặt OPEN_CLOUD_API_KEY là khóa API bạn đã tạo.
    3. Đặt ROBLOX_WEBHOOK_SECRET là mật khẩu bạn đã đặt khi cấu hình webhook trên Bảng điều khiển Người sáng tạo.
    4. Trong các từ điển STANDARD_DATA_STORE_ENTRIESORDERED_DATA_STORE_ENTRIES để xác định kho dữ liệu của mỗi bản ghi cần xóa:
      1. Thêm các ID Nơi Bắt Đầu đã sao chép của bạn làm khóa.
      2. Thêm ID Vũ trụ làm phần tử đầu tiên của giá trị tuple.
      3. Thay thế phần tử thứ hai của tuple bằng tên, phạm vi, tên khóa mục và ID người dùng liên quan của các kho dữ liệu của bạn. Nếu bạn sử dụng một lược đồ dữ liệu khác, hãy sửa đổi để phù hợp với lược đồ dữ liệu của riêng bạn.
  4. Thực hiện lệnh sau để chạy bot:

    Chạy Bot Discord
    python3 discord_bot.py
  5. Bot sau đó bắt đầu lắng nghe và xác minh các webhook Roblox cho các yêu cầu quyền xóa dữ liệu và gọi điểm cuối Open Cloud để xóa các kho dữ liệu tương ứng.

Kiểm tra

Bạn có thể tạo và chạy một tin nhắn thử nghiệm để xác minh rằng chương trình tùy chỉnh của bạn có thể xử lý đúng các yêu cầu quyền xóa dữ liệu và xóa dữ liệu PII:

  1. Gửi một yêu cầu HTTP POST đến máy chủ webhook Discord của bạn với nội dung yêu cầu sau:

    Ví dụ Yêu cầu
    curl -X POST {serverUrl}
    -H 'Content-Type: application/json'
    -d '{
    "embeds":[{
    "title":"RightToErasureRequest",
    "description":"Bạn đã nhận được một thông báo mới về Quyền Xóa Dữ liệu cho ID Người dùng: {userIds} trong trò chơi với ID: {gameIds}",
    "footer":{
    "icon_url":"https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
    "text":"Roblox-Signature: {robloxSignature}, Timestamp: {timestamp}"
    }
    }]
    }'
  2. Nếu bạn có một mật khẩu webhook:

    1. Tạo một Roblox-Signature bằng cách áp dụng mã hóa HMAC-SHA256 cho khóa bí mật webhook của bạn.
    2. Đặt thời gian hiện tại bằng cách sử dụng dấu thời gian UTC tính bằng giây là Timestamp.
  3. Ghép lại phần description theo định dạng sau:

    Định dạng Trường Mô tả
    {Timestamp}. Bạn đã nhận được một thông báo mới về Quyền Xóa Dữ liệu cho ID Người dùng: {userId} trong trò chơi với ID: {gameIds}`.

    Ví dụ:

    Ví dụ Trường Mô tả
    1683927229. Bn đã nhn được mt thông báo mi vQuyn Xóa Dliu cho ID Người dùng: 2425654247 trong trò chơi vi ID: 10539205763, 13260950955

Chương trình của bạn nên có khả năng xác định rằng tin nhắn của bạn đến từ nguồn chính thức của Roblox vì bạn đã mã hóa tin nhắn bằng mật khẩu của mình. Nó sẽ xóa dữ liệu PII liên quan đến yêu cầu của bạn.

Ví dụ Nội dung
{
"embeds": [
{
"title": "RightToErasureRequest",
"description": "Bạn đã nhận được một thông báo mới về Quyền Xóa Dữ liệu cho ID Người dùng: 2425654247 trong trò chơi với ID: 10539205763, 13260950955",
"footer": {
"icon_url": "https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
"text": "Roblox-Signature: UIe6GJ78MHCmU/zUKBYP3LV0lAqwWRFR6UEfPt1xBFw=, Timestamp: 1683927229"
}
}
]
}
©2026 Roblox Corporation. Roblox, logo Roblox và Powering Imagination là các nhãn hiệu đã đăng ký và chưa đăng ký của chúng tôi tại Hoa Kỳ và các quốc gia khác.