热土用户介绍

最后更新:2026-05-23

什么是热土用户?

热土用户(RTUser)是由热土工作室开发的一套统一用户认证与授权系统,旨在为开发者提供便捷、安全、可靠的用户登录解决方案。通过热土用户,您的软件可以快速接入统一的用户账号体系,无需自行搭建复杂的用户管理系统。

🔐

安全认证

支持state参数防CSRF攻击,Token有效期管理完善

快速接入

提供完善的SDK和详细的接入文档,30分钟内完成基础接入

💾

数据存储

支持用户数据段存储,轻松实现跨设备数据同步

🌐

多端支持

支持桌面应用、Web应用等多种应用类型接入

系统架构

您的应用
API代理层
热土用户核心

所有API请求通过代理层转发,确保安全性和稳定性。代理地址:https://appapi.rtstudio.top/

核心流程

1

用户发起登录

应用打开授权登录页面,用户输入账号密码

2

授权确认

用户确认授权,系统生成访问Token

3

Token回调

Token通过回调返回给应用

4

获取用户信息

应用使用Token调用API获取用户信息

产品优势

最后更新:2026-05-23

为什么选择热土用户?

🎯

统一账号体系

用户只需一个热土账号,即可登录所有接入热土用户的软件,无需在每个软件单独注册账号。

🛡️

安全可靠

采用业界标准的OAuth授权流程,支持state参数防CSRF攻击,完善的Token有效期管理机制。

📦

开箱即用

提供完整的SDK、详细的接入文档和示例代码,开发者可快速完成接入,无需搭建复杂的用户系统。

🔄

数据同步

通过数据段功能,用户数据可在不同设备间同步,提升用户体验。

📊

可视化管理

开发者可通过仪表盘管理软件Token、查看授权用户、发布Beta测试等。

已验证与未验证软件

特性 已验证软件 未验证软件
登录提示 显示软件名称和开发者信息 显示风险警告
数据段功能 支持(最多10个) 不支持
用户信任度 较低
仪表盘显示 已授权应用 未授权应用
提示:推荐申请已验证软件认证,提升用户信任度和功能权限。

适用场景

最后更新:2026-05-23

典型的应用场景

🖥️

桌面应用

各类Windows/Mac桌面软件,通过本地HTTP服务器接收登录回调,实现用户认证。

示例:工具软件、游戏客户端、编辑器插件
🌐

Web应用

网站和Web应用,通过URL重定向接收Token回调,快速实现用户登录。

示例:在线工具、管理后台、SaaS平台
🔧

开发工具

IDE插件、命令行工具等开发者工具,快速接入用户体系。

示例:VS Code插件、自动化脚本工具
🎮

游戏与娱乐

游戏、娱乐类软件,利用数据段实现设置保存。

示例:独立游戏、音乐播放器

不适合的场景

注意:以下场景不建议使用热土用户:
  • 需要高度定制化认证流程的应用
  • 对用户数据有特殊合规要求的金融、医疗类应用
  • 需要完全自主控制用户数据的应用

接入指南

最后更新:2026-05-23

快速接入流程

1

准备阶段

确定软件类型(桌面/Web),获取软件Token或准备软件名称

  • 已验证软件:使用软件Token(申请见联系我们
  • 未验证软件:使用软件名称
2

开发阶段

集成SDK或自行实现登录流程

  • 桌面应用:启动本地HTTP服务器监听回调
  • Web应用:配置回调URL
  • 调用API获取用户信息
3

测试阶段

使用测试账号验证登录流程

  • 验证Token有效性
  • 测试用户信息获取
  • 测试数据段功能(如需要)
4

上线阶段

发布软件,用户可使用热土账号登录

登录URL参数说明

参数 必填 说明
port 桌面应用:本地端口;Web应用:回调网址
type token(已验证)或 name(未验证)
v 软件Token或软件名称
state 防CSRF的随机字符串(建议16字节)
env 可选 app(桌面)或 web(Web应用)
桌面应用示例
https://apilogin.rtstudio.top/?port=3456&type=token&v=your_token&state=random_state&env=app
Web应用示例
https://apilogin.rtstudio.top/?port=yourapp.com/callback&type=token&v=your_token&state=random_state&env=web

登录URL详解

最后更新:2026-05-23

URL基本结构

热土用户的登录授权URL遵循以下基本结构:

https://apilogin.rtstudio.top/?[参数列表]

所有参数通过URL查询字符串(Query String)传递,参数之间使用 & 符号分隔。

完整参数说明

参数名 必填 类型 说明
port 必填 string 回调接收地址
桌面应用:本地HTTP服务器端口(如 3456
Web应用:完整的回调URL路径(如 yourapp.com/callback
type 必填 string 软件标识类型
token - 已验证软件,使用软件Token标识
name - 未验证软件,使用软件名称标识
v 必填 string 软件标识值
type=token 时:填写软件Token
type=name 时:填写软件名称
state 必填 string 防CSRF攻击的随机字符串
建议使用16字节以上的随机值
回调时会原样返回,用于验证请求来源
env 可选 string 应用环境类型
app - 桌面应用(默认)
web - Web应用
影响登录页面的UI展示和回调处理方式

完整URL示例

桌面应用(已验证软件)

完整示例
https://apilogin.rtstudio.top/?port=3456&type=token&v=abc123def456&state=a1b2c3d4e5f6g7h8&env=app
port=3456 本地HTTP服务器监听端口
type=token 使用Token标识软件(已验证)
v=abc123def456 软件Token值
state=a1b2c3d4... 随机生成的防CSRF字符串
env=app 标识为桌面应用

桌面应用(未验证软件)

完整示例
https://apilogin.rtstudio.top/?port=3456&type=name&v=我的测试软件&state=random_state_123&env=app
注意:未验证软件使用 type=name 时,登录页面会显示风险警告提示,建议申请已验证认证。

Web应用

完整示例
https://apilogin.rtstudio.top/?port=https://yourapp.com/auth/callback&type=token&v=abc123def456&state=random_state&env=web
提示:Web应用的 port 参数需要填写完整的回调URL,用户登录成功后会重定向到此地址。

回调URL详解

用户完成登录授权后,系统会将结果通过回调URL返回给您的应用。

桌面应用回调

系统会向您的本地HTTP服务器发送GET请求:

成功回调
http://127.0.0.1:3456/?type=success&v=USER_ACCESS_TOKEN&state=YOUR_STATE
失败回调
http://127.0.0.1:3456/?type=error&v=错误信息&state=YOUR_STATE
回调参数 说明
type success 表示成功,error 表示失败
v 成功时为用户访问Token,失败时为错误信息
state 您在登录URL中传入的state值,用于验证

Web应用回调

系统会将用户重定向到您指定的回调URL:

成功回调
https://yourapp.com/auth/callback?type=success&v=USER_ACCESS_TOKEN&state=YOUR_STATE

您需要在回调页面解析URL参数,获取Token并验证state一致性。

State参数安全说明

⚠️ 重要安全提示

state 参数是防止CSRF(跨站请求伪造)攻击的关键机制,请务必正确使用:

  • 每次登录请求生成新的随机state值
  • 建议使用16字节以上的随机字符串
  • 在接收回调时,验证返回的state与发送时一致
  • 验证失败时应拒绝此次登录

State生成示例

Go语言
func generateState() (string, error) {
    b := make([]byte, 16)
    _, err := rand.Read(b)
    if err != nil {
        return "", err
    }
    return hex.EncodeToString(b), nil
}
Python
import secrets

def generate_state():
    return secrets.token_hex(16)  # 生成32字符的随机字符串

Token使用说明

获取到用户访问Token后,您可以:

  • 调用 /verify-access-token 验证Token有效性
  • 调用 /get-user-by-token 获取用户基本信息
  • 调用数据段相关API(仅已验证软件)
Token有效期:用户访问Token有效期为1年,过期后用户需要重新登录授权。

URL编码注意事项

当参数值包含特殊字符时,需要进行URL编码:

场景 原始值 编码后
软件名称含中文 我的测试软件 %E6%88%91%E7%9A%84%E6%B5%8B%E8%AF%95%E8%BD%AF%E4%BD
回调URL含特殊字符 app.com/auth?type=login app.com%2Fauth%3Ftype%3Dlogin
JavaScript URL编码
const softwareName = '我的测试软件';
const encodedName = encodeURIComponent(softwareName);
const loginUrl = `https://apilogin.rtstudio.top/?port=3456&type=name&v=${encodedName}&state=random_state`;

开发准备

2026-05-23

获取软件Token

步骤一:准备材料
  • 软件名称
  • 开发者信息
  • 软件功能描述
  • 软件截图(如有)
  • 下载链接(如有)
步骤二:提交申请

发送邮件至 miles@rtstu.com

邮件主题:软件认证申请 - [软件名称]

步骤三:等待审核

审核周期:1-3个工作日

审核通过后将收到包含软件Token的邮件

环境要求

应用类型 要求
桌面应用 能够启动本地HTTP服务器、打开浏览器
Web应用 能够处理URL重定向和查询参数

API地址

API代理地址
https://appapi.rtstudio.top/
说明:所有API请求都需要通过此代理地址进行调用。

API概览

2026-05-23

API列表

接口 方法 说明 权限要求
/verify-software-token POST 验证软件Token
/verify-access-token POST 验证用户Token
/get-user-by-token POST 获取用户信息 有效Token
/data-segments POST 创建数据段 已验证软件
/data-segments PUT 修改数据段 已验证软件
/data-segments DELETE 删除数据段 已验证软件
/data-segments/read POST 读取数据段 已验证软件

通用响应格式

{
    "success": true,
    "message": "操作成功",
    "data": {
        // 具体数据
    }
}
失败响应
{
    "success": false,
    "message": "错误描述"
}

认证相关API

2026-05-23

验证软件Token

POST /verify-software-token
验证软件登录Token的有效性

请求参数

参数名 类型 必填 说明
token string 软件Token

响应示例

{
    "success": true,
    "data": {
        "id": 1,
        "name": "测试软件",
        "developer": "测试开发者"
    }
}

验证用户Token

POST /verify-access-token
验证用户授权Token的有效性

请求参数

参数名 类型 必填 说明
token string 用户授权Token

响应示例

{
    "success": true,
    "data": {
        "id": 1,
        "user_id": 1,
        "software_id": 1,
        "expires_at": "2027-03-22T12:00:00Z"
    }
}

获取用户信息

POST /get-user-by-token
根据Token获取用户基本信息

请求参数

参数名 类型 必填 说明
token string 用户授权Token

响应示例

{
    "success": true,
    "data": {
        "id": 1,
        "uuid": "...",
        "username": "testuser",
        "email": "test@example.com",
        "email_verified": true,
        "is_beta_user": false
    }
}

数据段相关API

2026-05-23
⚠️ 重要安全提示

数据段功能设计用于存储用户偏好设置、软件配置、非关键业务数据等非敏感信息。

严禁使用数据段存储以下类型的数据:

  • VIP/会员状态、订阅权限等核心业务判定数据
  • 付费信息、充值记录、消费数据
  • 用户等级、积分、特权等可影响业务逻辑的数据
  • 密码、密钥、证书等安全凭证
  • 个人身份信息(身份证、银行卡等)

原因:数据段存储在用户可访问的系统中,用户可能查看或修改这些数据。将VIP状态等关键数据存储在数据段中,将导致用户可以自行"解锁"VIP功能,造成业务风险。

正确做法:VIP状态、付费信息等核心业务数据应由您的后端服务器独立管理,通过您自己的API进行验证,不应依赖热土用户系统的数据段功能。

数据段说明

📋 每个用户最多10个数据段(已验证软件)
📏 单个数据段内容限制1MB
🔒 仅已验证软件可使用

创建数据段

POST /data-segments
为用户创建新的数据段

请求参数

参数名 类型 必填 说明
email string 用户邮箱
token string 用户授权Token
name string 数据段名称(唯一标识)
content string 数据段内容(JSON字符串)

响应示例

{
    "success": true,
    "message": "数据段创建成功",
    "data": {
        "id": 1,
        "name": "user_settings",
        "content": "{\"theme\": \"dark\"}"
    }
}

读取数据段

POST /data-segments/read
读取指定数据段的内容

请求参数

参数名 类型 必填 说明
email string 用户邮箱
token string 用户授权Token
name string 数据段名称

响应示例

{
    "success": true,
    "data": {
        "id": 1,
        "name": "user_settings",
        "content": "{\"theme\": \"dark\", \"language\": \"zh-CN\"}",
        "created_at": "2026-03-22T12:00:00Z",
        "updated_at": "2026-03-22T12:00:00Z"
    }
}

修改数据段

PUT /data-segments
更新已存在的数据段内容

请求参数

参数名 类型 必填 说明
email string 用户邮箱
token string 用户授权Token
name string 数据段名称
content string 新的数据段内容

删除数据段

DELETE /data-segments
删除指定的数据段

请求参数

参数名 类型 必填 说明
email string 用户邮箱
token string 用户授权Token
name string 数据段名称

适合存储的数据示例

✅ 用户偏好设置

{"theme": "dark", "language": "zh-CN", "fontSize": 14}

✅ 软件窗口布局

{"width": 800, "height": 600, "x": 100, "y": 100}

✅ 游戏非关键数据

{"ImageQuality": 5, "controls": "default"}

不适合存储的数据示例

❌ VIP状态(错误示例)

{"isVIP": true, "vipLevel": 3, "vipExpires": "2027-12-31"}

⚠️ 用户可以自行修改为VIP状态,绕过付费验证

❌ 用户积分(错误示例)

{"points": 9999, "level": 10, "achievements": ["all"]}

⚠️ 用户可以自行修改积分和等级

Go SDK

2026-05-23

完整登录流程实现

以下是完整的Go语言SDK实现代码,包含登录流程、Token验证、用户信息获取等功能。

完整示例代码
// main.go
package main

import (
    "bytes"
    "crypto/rand"
    "encoding/hex"
    "encoding/json"
    "flag"
    "fmt"
    "io"
    "log"
    "net"
    "net/http"
    "os/exec"
    "runtime"
    "time"
)

const apiBaseURL = "https://appapi.rtstudio.top"

var loginType string
var value string

type verifyResponse struct {
    Success bool   `json:"success"`
    Data    any    `json:"data"`
    Message string `json:"message"`
}

func main() {
    flag.StringVar(&loginType, "type", "", "登录类型: token 或 name")
    flag.StringVar(&value, "v", "", "软件token或软件名称")
    flag.Parse()

    if loginType != "token" && loginType != "name" {
        log.Fatal("-type 必须是 'token' 或 'name'")
    }
    if value == "" {
        log.Fatal("-v 参数不能为空")
    }

    token, err := startLoginFlow(loginType, value)
    if err != nil {
        log.Fatalf("登录失败: %v", err)
    }

    userResult, err := getUserByToken(token)
    if err != nil {
        log.Fatalf("获取用户信息失败: %v", err)
    }
    
    if userResult.Success {
        log.Printf("登录成功,用户: %+v", userResult.Data)
    }
}

// startLoginFlow 启动登录流程
func startLoginFlow(loginType, value string) (string, error) {
    state, err := generateState()
    if err != nil {
        return "", fmt.Errorf("生成state失败: %v", err)
    }

    port, err := findAvailablePort()
    if err != nil {
        return "", fmt.Errorf("无法找到可用端口: %v", err)
    }

    tokenChan := make(chan string, 1)
    errChan := make(chan error, 1)

    server := &http.Server{
        Addr:         fmt.Sprintf(":%d", port),
        ReadTimeout:  10 * time.Second,
        WriteTimeout: 10 * time.Second,
    }

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        query := r.URL.Query()
        callbackType := query.Get("type")
        callbackValue := query.Get("v")
        callbackState := query.Get("state")

        if callbackType == "success" {
            if callbackState != state {
                errChan <- fmt.Errorf("state验证失败")
                http.Error(w, "state验证失败", http.StatusBadRequest)
                return
            }
            tokenChan <- callbackValue
            w.Write([]byte(`

✅ 登录完成

请关闭此窗口

`)) go func() { time.Sleep(500 * time.Millisecond) server.Close() }() } else if callbackType == "error" { errChan <- fmt.Errorf("登录失败: %s", callbackValue) go server.Close() } }) go func() { if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { errChan <- fmt.Errorf("HTTP服务器错误: %v", err) } }() time.Sleep(100 * time.Millisecond) loginURL := fmt.Sprintf("https://apilogin.rtstudio.top/?port=%d&type=%s&v=%s&state=%s&env=app", port, loginType, value, state) if err := openBrowser(loginURL); err != nil { return "", fmt.Errorf("打开浏览器失败: %v", err) } select { case token := <-tokenChan: return token, nil case err := <-errChan: return "", err case <-time.After(5 * time.Minute): server.Close() return "", fmt.Errorf("登录超时") } } func generateState() (string, error) { b := make([]byte, 16) if _, err := rand.Read(b); err != nil { return "", err } return hex.EncodeToString(b), nil } func findAvailablePort() (int, error) { listener, err := net.Listen("tcp", ":0") if err != nil { return 0, err } defer listener.Close() return listener.Addr().(*net.TCPAddr).Port, nil } func openBrowser(url string) error { switch runtime.GOOS { case "windows": return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() case "darwin": return exec.Command("open", url).Start() default: return exec.Command("xdg-open", url).Start() } } func getUserByToken(token string) (*verifyResponse, error) { reqBody := map[string]string{"token": token} jsonBody, _ := json.Marshal(reqBody) resp, err := http.Post(apiBaseURL+"/get-user-by-token", "application/json", bytes.NewBuffer(jsonBody)) if err != nil { return nil, fmt.Errorf("API请求失败: %v", err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) var result verifyResponse json.Unmarshal(body, &result) return &result, nil }

使用方法

# 已验证软件
go run main.go -type token -v your_software_token

# 未验证软件
go run main.go -type name -v your_software_name

其他语言

2026-05-23

Python示例

import requests
import webbrowser
import http.server
import socketserver
import threading
import secrets
import time

API_BASE_URL = "https://appapi.rtstudio.top"

def get_available_port():
    with socketserver.TCPServer(("localhost", 0), None) as s:
        return s.server_address[1]

def login(login_type, value):
    state = secrets.token_hex(16)
    port = get_available_port()
    
    token = None
    class Handler(http.server.BaseHTTPRequestHandler):
        def do_GET(self):
            query = parse_qs(urlparse(self.path).query)
            if query.get('type') == ['success'] and query.get('state') == [state]:
                token = query.get('v', [None])[0]
                self.send_response(200)
                self.end_headers()
                self.wfile.write(b'

登录完成

') server = socketserver.TCPServer(("localhost", port), Handler) thread = threading.Thread(target=server.serve_forever) thread.start() url = f"https://apilogin.rtstudio.top/?port={port}&type={login_type}&v={value}&state={state}&env=app" webbrowser.open(url) time.sleep(30) # 等待登录 server.shutdown() return token def get_user_by_token(token): resp = requests.post(f"{API_BASE_URL}/get-user-by-token", json={"token": token}) return resp.json()

更多SDK

更多语言的SDK正在开发中,如有需要请联系我们获取。

常见问题

2026-05-23
Q 软件Token和用户Token有什么区别?

软件Token用于标识软件身份,由热土工作室颁发;用户Token是用户登录后生成的访问令牌,用于获取用户信息。

Q 用户Token有效期是多久?

用户Token有效期为1年,过期后需重新登录授权。

Q 如何申请已验证软件?

发送邮件至 miles@rtstu.com,包含软件名称、开发者信息、功能描述等,审核周期1-3个工作日。

Q 数据段可以存储VIP状态吗?

不可以。数据段不适合存储VIP状态、付费信息等核心业务数据,因为这些数据用户可能查看或修改,会导致业务风险。VIP状态等应由您的后端独立管理。

Q state参数有什么作用?

state参数用于防止CSRF攻击,建议使用16字节以上的随机字符串,回调时验证state一致性。

联系我们

2026-05-23

成为开发者

成为开发者可获得以下权限:
  • 自主创建和管理软件Token
  • 发布Beta测试软件
  • 查看授权用户数据统计
  • 使用开发者控制台(id.rtstu.com)
1

加入热土工作室QQ群

群号: 922594184
入群申请: 填写"热土用户文档"
加入QQ群
2

私信群主申请加入

入群后,私信群主表达您希望成为开发者的意愿。

必要条件

个人开发者
  • 拥有一个热土用户账号
  • 拥有对外展示作品的公开渠道
  • 支持的渠道:X(Twitter)、Bilibili、GitHub、个人网站、博客等
  • 不支持:仅限微信朋友圈、私密社群等非公开渠道
团队/组织
  • 满足个人开发者的所有条件
  • 拥有团队/组织的官方账号(非个人账号)
  • 例如:Bilibili团队官方账号、GitHub组织账号等
  • 有明确的团队负责人作为主要联系人
3

提交材料并确认协议

向群主提交以下材料:

  • 您的热土用户账号(邮箱或用户名)
  • 展示渠道链接(如Bilibili主页、GitHub主页等)
  • 团队需额外提供:团队名称、团队官方账号链接、团队负责人信息

材料审核通过后,需确认开发者协议,即可获得开发者权限。

4

登录开发者控制台

完成以上步骤后,访问 id.rtstu.com 并选择「开发者」,即可开始管理您的软件。

软件认证申请(邮箱方式)

注意:此方式仅用于申请单个软件的已验证状态。如需自主管理多个软件、发布Beta测试等,请通过上方「成为开发者」流程获取完整权限。
邮件主题
软件认证申请 - [您的软件名称]
邮件内容需包含
  • 软件名称
  • 开发者/团队名称
  • 软件功能描述(简要)
  • 软件截图(如有)
  • 下载链接(如有)
发送邮箱

miles@rtstu.com

审核周期

1-3个工作日,审核通过后将收到包含软件Token的邮件回复。

联系方式汇总

💬

QQ群

922594184

加入群聊
📧

邮箱

miles@rtstu.com

发送邮件
🌐

开发者控制台

id.rtstu.com

访问控制台